diff --git a/crates/core/src/egress/recorder.rs b/crates/core/src/egress/recorder.rs index 36c6558..75d5ac9 100644 --- a/crates/core/src/egress/recorder.rs +++ b/crates/core/src/egress/recorder.rs @@ -1,6 +1,7 @@ use anyhow::Result; use ffmpeg_rs_raw::ffmpeg_sys_the_third::AVPacket; use ffmpeg_rs_raw::{Encoder, Muxer}; +use log::info; use std::collections::HashMap; use std::fs; use std::path::PathBuf; @@ -21,7 +22,7 @@ impl RecorderEgress { out_dir: PathBuf, variants: impl Iterator, ) -> Result { - let out_file = out_dir.join("recording.ts"); + let out_file = out_dir.join("recording.mp4"); let mut var_map = HashMap::new(); let muxer = unsafe { let mut m = Muxer::builder() @@ -31,7 +32,10 @@ impl RecorderEgress { let stream = m.add_stream_encoder(enc)?; var_map.insert(var.id(), (*stream).index); } - m.open(None)?; + let mut options = HashMap::new(); + options.insert("movflags".to_string(), "faststart".to_string()); + + m.open(Some(options))?; m }; Ok(Self { muxer, var_map }) diff --git a/crates/core/src/pipeline/runner.rs b/crates/core/src/pipeline/runner.rs index 60e3704..9c3dad5 100644 --- a/crates/core/src/pipeline/runner.rs +++ b/crates/core/src/pipeline/runner.rs @@ -22,8 +22,8 @@ use ffmpeg_rs_raw::ffmpeg_sys_the_third::AVCodecID::AV_CODEC_ID_WEBP; use ffmpeg_rs_raw::ffmpeg_sys_the_third::AVPictureType::AV_PICTURE_TYPE_NONE; use ffmpeg_rs_raw::ffmpeg_sys_the_third::AVPixelFormat::AV_PIX_FMT_YUV420P; use ffmpeg_rs_raw::ffmpeg_sys_the_third::{ - av_frame_clone, av_frame_free, av_get_sample_fmt, av_packet_free, av_rescale_q, AVFrame, - AVPacket, AV_NOPTS_VALUE, + av_frame_clone, av_frame_free, av_get_sample_fmt, av_packet_clone, av_packet_free, + av_rescale_q, AVFrame, AVPacket, AV_NOPTS_VALUE, }; use ffmpeg_rs_raw::{ cstr, get_frame_from_hw, AudioFifo, Decoder, Demuxer, Encoder, Resample, Scaler, StreamType, @@ -529,7 +529,8 @@ impl PipelineRunner { // pass new packets to egress for mut pkt in packets { for eg in egress.iter_mut() { - let er = eg.process_pkt(pkt, &var.id())?; + let pkt_clone = av_packet_clone(pkt); + let er = eg.process_pkt(pkt_clone, &var.id())?; ret.push(er); } av_packet_free(&mut pkt); diff --git a/crates/zap-stream/src/overseer.rs b/crates/zap-stream/src/overseer.rs index b2c64e1..c8629aa 100644 --- a/crates/zap-stream/src/overseer.rs +++ b/crates/zap-stream/src/overseer.rs @@ -378,10 +378,17 @@ impl Overseer for ZapStreamOverseer { _ => false, }); match var { - Some(var) => egress.push(EgressType::Recorder(EgressConfig { - name: "dvr".to_string(), - variants: [var.id()].into(), - })), + Some(var) => { + // take all streams in the same group as the matching video resolution (video+audio) + let vars_in_group = cfg + .variants + .iter() + .filter(|v| v.group_id() == var.group_id()); + egress.push(EgressType::Recorder(EgressConfig { + name: "dvr".to_string(), + variants: vars_in_group.map(|v| v.id()).collect(), + })) + } None => { warn!( "Invalid DVR config, no variant found with height {}",