我正在rust中构建一个程序(每晚,异步等待,期货预览,tokio 0.2+)以通过RTSP记录来自IP摄像机的视频。
记录器模块会生成创建视频块的ffmpeg进程。它还捕获并记录ffmpeg的stderr / stdout并将其记录到屏幕。如果发生错误(网络等),ffmpeg可能会死,所以我想无限期地重启15秒。
我想创建动态Recorder s 集合。我想在运行时添加/删除记录器。在某个时候,对于每个创建的记录器,我必须获取其未来并将其传递给tokio::spawn
。从黑匣子的角度来看,我希望记录器提供两种方法:add(r: Recorder OR all recorder params) -> RecorderHandle
和remove(rh: RecorderHandle)
。
tokio::spawn
的将来?.await
上?run()
方法可以吗?有什么建议吗?run_infinite()
方法可以吗?pub struct RtspRecorder {
rtsp_url: url::Url,
segment_time: std::time::Duration,
output_strftime: String,
output_directory: std::path::PathBuf
}
impl RtspRecorder {
pub fn new( /* just all fields are passed to the struct */ ) -> Self { /* (...) */}
fn ffmpeg_command_build(&self) -> tokio_net::process::Command { /* sets env and command line arguments */ }
pub async fn run(
&self,
) -> Box<dyn std::error::Error> {
let mut command = self.ffmpeg_command_build();
let mut child = command.spawn().unwrap();
let stdout = tokio::codec::FramedRead::new(child.stdout().take().unwrap(), tokio::codec::LinesCodec::default())
.for_each(|message| { log::info!("ffmpeg stdout: {}", message.unwrap()); return futures::future::ready(()); });
let stderr = tokio::codec::FramedRead::new(child.stderr().take().unwrap(), tokio::codec::LinesCodec::default())
.for_each(|message| { log::warn!("ffmpeg stderr: {}", message.unwrap()); return futures::future::ready(()); });
let futures_results = futures::future::join3(child, stdout, stderr).await;
return match futures_results.0 {
Err(e) => e.into(),
Ok(exit_status) => format!("ffmpeg exited with status: {:?}", exit_status).into()
}
}
pub async fn run_infinite(
&self
) {
loop {
let error = self.run().await;
log::warn!("error during run: {:?}, restarting...", error);
tokio_timer::delay_for(std::time::Duration::from_secs(15)).await;
}
}
}