pub struct SegmentedMp4Muxer { /* private fields */ }Expand description
Builds a SegmentedMp4Muxer the same two-phase way as a plain
Mp4Muxer (every track’s shape must be known before the first byte
is written) — create picks the rotation policy and how segments get
named, add_stream registers each track exactly like
Mp4Muxer::add_stream, open writes the first segment’s header and
returns one Sink per track.
let mut muxer = SegmentedMp4Muxer::create(
SegmentPolicy::Duration(Duration::from_secs(600)),
|index| PathBuf::from(format!("rec_{index:04}.mp4")),
);
muxer.add_stream("video", video_encoder.parameters(), video_time_base);
muxer.add_stream("audio", audio_encoder.parameters(), audio_time_base);
let mut sinks = muxer.open()?;Implementations§
Source§impl SegmentedMp4Muxer
impl SegmentedMp4Muxer
Sourcepub fn create(
policy: SegmentPolicy,
naming: impl FnMut(u64) -> PathBuf + Send + 'static,
) -> Self
pub fn create( policy: SegmentPolicy, naming: impl FnMut(u64) -> PathBuf + Send + 'static, ) -> Self
naming(index) names each segment file, index starting at 0 —
called once up front for the first segment and again on every
rotation. Typically a closure building a path from a fixed
directory/prefix (e.g. |i| dir.join(format!("rec_{i:04}.mp4")));
a timestamp-based scheme works just as well since index is only
ever used to call this, never to build the path itself.
Sourcepub fn add_stream(
&mut self,
name: impl Into<String>,
parameters: Parameters,
time_base: Rational,
)
pub fn add_stream( &mut self, name: impl Into<String>, parameters: Parameters, time_base: Rational, )
Registers one more track every segment file will hold — same
contract as Mp4Muxer::add_stream (same order rules, same
name/parameters/time_base meaning), except this can’t fail:
nothing here touches ffmpeg yet, it’s only recorded for
SegmentedMp4Muxer::open (and every later rotation) to replay.
Whichever stream’s parameters.medium() is
[ffmpeg::media::Type::Video] (at most one is expected) becomes
the keyframe-gating track described in SegmentedMp4Muxer::open’s
own docs — no separate flag to pass.
Sourcepub fn open(self) -> Result<Vec<Box<dyn Sink>>>
pub fn open(self) -> Result<Vec<Box<dyn Sink>>>
Writes the first segment’s header and returns one Sink per
track, in the order SegmentedMp4Muxer::add_stream added them —
same shape as Mp4Muxer::open. All returned Sinks share one
rotation lock: a track’s consume blocks while another track (on
its own thread) is mid-rotation, same tradeoff Mp4Muxer’s own
shared file lock already makes.
Rotation timing: once a segment has run at least as long as the
configured SegmentPolicy, the cut happens on the video
track’s next keyframe (found via add_stream’s parameters — see
its own docs) — not immediately, and not on an arbitrary packet —
so every segment file is independently decodable from its own
first frame, the same way a real segment/HLS muxer cuts. A segment
can therefore run somewhat longer than requested if keyframes are
sparse; there’s no hard cap. If no track’s parameters.medium()
was Video (an audio-only recording), any packet on any track is
an equally valid cut point, so rotation happens as soon as the
policy is due.
The final segment is finalized the same way a plain Mp4Muxer
finalizes its one file: once every track has reported Eos or
ControlMsg::Stop (see Mp4Muxer::open’s own docs) — a
rotation mid-recording reuses that exact mechanism to close the
outgoing segment before opening the next one.