Skip to main content

SegmentedMp4Muxer

Struct SegmentedMp4Muxer 

Source
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

Source

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.

Source

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.

Source

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.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more