mp4-track 0.1.0

Track-level MP4 reader and progressive writer with bounded parsing
Documentation
  • Coverage
  • 100%
    223 out of 223 items documented1 out of 1 items with examples
  • Size
  • Source code size: 2.0 MB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 2.4 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 9s Average build duration of successful builds.
  • all releases: 9s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hey-jj/mp4-track
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hey-jj

mp4-track

mp4-track reads tracks, sample tables, codec configuration, edit lists, event messages, fragments, and common user metadata from MP4 and ISO base media files. It also writes progressive MP4 files from encoded samples.

The reader accepts any Read + Seek stream. It walks box headers before loading data, skips media payloads during open, and applies configurable limits to movie boxes, fragment boxes, samples, fragment counts, and nesting depth. Sample offsets and time values use 64-bit arithmetic. Malformed input returns a typed Error.

Reading samples

use mp4_track::{Mp4Reader, TrackId};
use std::fs::File;

let file = File::open("movie.mp4")?;
let mut reader = Mp4Reader::open(file)?;

for track in reader.tracks() {
    println!("track {} has {} table samples", track.id.0, track.sample_count);
}

if let Some(info) = reader.samples(TrackId(1))?.next() {
    let sample = reader.read_sample(TrackId(1), info.index)?;
    println!("read {} bytes at decode time {}", sample.data.len(), info.dts);
}
# Ok::<(), Box<dyn std::error::Error>>(())

read_sample_into reuses a caller-owned Vec<u8>. samples and sample_info read metadata already expanded during open, so they perform no stream I/O.

Writing a progressive file

Create an Mp4Writer, add every track, then pass encoded samples in output order. Consecutive samples from the same track form one chunk. finish writes the movie box and fixes the media-data size.

use mp4_track::{Mp4Writer, WriterConfig};
use std::io::Cursor;

let output = Cursor::new(Vec::new());
let writer = Mp4Writer::new(output, WriterConfig::default())?;
// Add TrackConfig values and encoded samples before calling finish.
# let _ = writer;
# Ok::<(), Box<dyn std::error::Error>>(())

The writer selects 32-bit chunk offsets when they fit. Set ChunkOffsetChoice::Co64 to force 64-bit chunk offsets.

Supported data

Progressive reads cover stts, ctts, stss, stsc, stsz, stco, and co64. Codec parsing covers avc1, avc3, hvc1, hev1, mp4a, and Opus. Other sample entries retain their body bytes. Fragmented reads cover trex, tfhd, tfdt, and trun when each track fragment supplies an explicit base offset or uses default-base-is-moof.

The current release targets 64-bit systems. Compact sample sizes, compressed movie boxes, encryption boxes, sample groups, media item boxes, and fragmented output are outside its supported surface.

Resource limits

Limits::default() permits movie boxes up to 256 MiB, fragment boxes up to 64 MiB, samples up to 64 MiB, 500,000 samples per track, one million fragments, and 32 levels of box nesting. Sample tables that declare more samples than the limit are rejected before any table is allocated. Pass a Limits value to Mp4Reader::open_with when an application needs lower bounds.

License

MIT