Expand description
§mp4box
A minimal, dependency-light MP4/ISOBMFF parser and editor for Rust.
This crate parses the MP4 box tree (including 64-bit “large” boxes, UUID
boxes, and the codec configuration inside stsd sample entries), decodes
known box types into typed structures, extracts per-sample tables from
progressive and fragmented (fMP4/DASH/CMAF) files, and performs
non-destructive box editing with automatic size and chunk-offset fixup.
§Features
- Core parser with only
anyhow+serdeas dependencies, working with anyRead + Seeksource - Typed structured decoding (
registry::StructuredData) for headers, sample tables, fragments, DRM boxes (pssh/tenc), and codec configuration (esdsAudioSpecificConfig,avcC,hvcC, …) - Per-sample tables (
track_samples_from_path) for progressive and fragmented files: DTS/PTS, sizes, offsets, keyframes - Tolerant parsing (
get_boxes_tolerant): partial tree plus located issues instead of an error on damaged files - Non-destructive editing (
editfeature,edit::Editor): remove / insert / replace boxes, patch fields, set tags, faststart - iTunes metadata reading (
get_itunes_tags) and writing - JSON-serializable output perfect for web UIs and APIs
- Command-line tools (
clifeature):mp4dump,mp4info,mp4samples,mp4edit
§Use Cases
- CLIs for inspecting MP4 structure (e.g.
mp4dump) - Tauri/Electron desktop apps that need JSON output for UI
- Backend services that need to inspect or validate MP4 files
- Media processing tools and debugging utilities
§Quick start
use mp4box::get_boxes;
use std::fs::File;
fn main() -> anyhow::Result<()> {
let mut file = File::open("video.mp4")?;
let size = file.metadata()?.len();
// Parse structure only
let boxes = get_boxes(&mut file, size, false)?;
println!("Found {} top-level boxes", boxes.len());
// Parse with decoding of known box types
let mut file = File::open("video.mp4")?;
let decoded_boxes = get_boxes(&mut file, size, true)?;
// Print file type info
if let Some(ftyp) = decoded_boxes.iter().find(|b| b.typ == "ftyp") {
println!("File type: {}",
ftyp.decoded.as_deref().unwrap_or("unknown"));
}
Ok(())
}§Lower-level parsing
For more control, you can use the lower-level parser functions:
use mp4box::parser::{read_box_header, parse_children};
use mp4box::known_boxes::KnownBox;
use std::fs::File;
use std::io::{Seek, SeekFrom};
fn main() -> anyhow::Result<()> {
let mut file = File::open("video.mp4")?;
let file_len = file.metadata()?.len();
while file.stream_position()? < file_len {
let header = read_box_header(&mut file)?;
let known = KnownBox::from(header.typ);
println!("Box: {} ({}) at offset {:#x}",
header.typ, known.full_name(), header.start);
let end = if header.size == 0 { file_len } else { header.start + header.size };
file.seek(SeekFrom::Start(end))?;
}
Ok(())
}For more examples, see the mp4dump and mp4info binaries in this repository.
Re-exports§
pub use boxes::BoxHeader;pub use boxes::BoxKey;pub use boxes::BoxRef;pub use boxes::FourCC;pub use boxes::NodeKind;pub use parser::ParseIssue;pub use parser::parse_boxes;pub use parser::parse_boxes_tolerant;pub use parser::parse_children;pub use parser::read_box_header;pub use registry::BoxValue;pub use registry::Co64Data;pub use registry::CttsData;pub use registry::CttsEntry;pub use registry::HdlrData;pub use registry::MdhdData;pub use registry::Registry;pub use registry::SampleEntry;pub use registry::StcoData;pub use registry::StructuredData;pub use registry::StscData;pub use registry::StscEntry;pub use registry::StsdData;pub use registry::StssData;pub use registry::StszData;pub use registry::SttsData;pub use registry::SttsEntry;pub use registry::default_registry;pub use api::Box;pub use api::HexDump;pub use api::get_boxes;pub use api::get_boxes_tolerant;pub use api::get_boxes_with_registry;pub use api::hex_range;pub use samples::SampleInfo;pub use samples::TrackSamples;pub use samples::track_samples_from_path;pub use samples::track_samples_from_reader;