An mp4 muxer demuxer for mp4, made to work in WASM and async contexts.
- Standard for Fragmented mp4
- Easy to use api
- Performant async reader (too many async calls currently)
Why not mp4-rust ?
- Their code does not implement all the necessary features for fragmented mp4 streams
- Their reader is not async
- We set flags automatically according to data
- We use a very clean macro for box definition for easy implementation:
full_box! {
box (b"mvhd", Mvhd, MvhdBox, u32)
data {
creation_time: Mp4DateTime,
modification_time: Mp4DateTime,
timescale: u32,
duration: Mp4Duration,
rate: I16F16,
volume: I8F8,
_r1: u16, // reserved
_r2: [u32; 2], // reserved
matrix: MP4Matrix,
_r3: [u32; 6], // reserved
next_track_id: u32
}
}
let ftyp = FtypBox {
major_brand: *b"iso5",
minor_version: 1,
compatible_brands: vec![*b"isom", *b"avc1", *b"iso2", *b"iso5"],
};
let moov: MoovBox = Moov {
mvhd: Some(Default::default()),
mvex: Some(Mvex {
trex: traks.iter().map(|trak| {
Trex {
track_id: trak.tkhd.as_ref().map(|it|it.track_id).unwrap_or(0),
default_sample_description_index: 1,
default_sample_duration: 0,
default_sample_size: 0,
default_sample_flags: Default::default(),
}.into()
}).collect(),
}.into()),
traks: vec![Trak { /* trak info... */ }.into()],
}.into();
let mut buf = std::io::Cursor::new(vec![]);
ftyp.write(&mut buf)?;
moov.write(&mut buf)?;
return buf.into_inner();
- Make async reader read full box chunks once the size is known and decode using a synchronous reader (so we don't allocate for every byte)
- Make the box macro generate a View structure of the box so that existing data can be read without decoding everything and preserving the original structure
- Make an easy-to-use builder to generate files from a stream of codec wrapping boxes and headers