This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Go library and tools for parsing, writing, and manipulating MP4/ISOBMFF (ISO Base Media File Format) files. Specialized for fragmented MP4 (MPEG-DASH, MSS, HLS fMP4), with support for many video codecs (AVC, HEVC, AV1, VVC, AVS3), audio codecs (AAC, AC-3, Opus, FLAC), subtitle formats (WebVTT, TTML), and CENC/CBCS encryption.
make build # Build all CLI tools and examples
make test # go test ./...
make check # Full quality check (prepare + pre-commit + codespell)
make coverage # Generate coverage reports (HTML + text)
go test ./mp4/ # Test a single package
go test ./mp4/ -run TestName # Run a single testPre-commit hooks (trailing-whitespace, go-fmt, golangci-lint, go-unit-tests, commitlint) are enforced. Activate the venv before committing: source venv/bin/activate.
Conventional Commits enforced via commitlint: feat:, fix:, docs:, chore:, refactor:, test:, ci:.
- mp4 — Core package. Box encoding/decoding, file/fragment/segment structures, crypto, streaming.
- bits — Bit-level I/O primitives (SliceReader/SliceWriter, FixedSliceReader/FixedSliceWriter).
- avc, hevc, vvc, av1 — Video codec handling (NALU parsing, parameter set extraction).
- sei — Supplementary Enhancement Information messages for AVC/HEVC.
- aac — AAC audio (ADTS headers, codec descriptions).
- cmd/ — CLI tools (mp4ff-info, mp4ff-crop, mp4ff-encrypt, mp4ff-decrypt, etc.).
- examples/ — Usage demonstrations.
mp4.File is the top-level container:
- Progressive: Ftyp + Moov + Mdat (all metadata in Moov, samples in Mdat)
- Fragmented: Init (Ftyp + Moov) + Segments, each containing Fragments (Moof + Mdat pairs)
Every box type follows a strict pattern (see prft.go for a minimal example):
- File:
{boxname}.go, struct:{BoxName}Box - Required methods:
Type(),Size(),Encode(io.Writer),EncodeSW(bits.SliceWriter),Info() - Decoding functions:
Decode{BoxName}(hdr, startPos, r)andDecode{BoxName}SR(hdr, startPos, sr) - Registered in dispatch tables:
decodersanddecodersSR
Two parallel I/O paths exist and both must be maintained:
- io.Reader/io.Writer — standard, more flexible
- SliceReader/SliceWriter — preferred for performance (2-10x faster, far fewer allocations)
Container boxes hold Children []Box plus direct references to common children (e.g., MoovBox has Trak *TrakBox and Traks []*TrakBox). AddChild() updates both.
DecModeLazyMdat— skips reading mdat payload into memoryStreamFile/InitDecodeStream/ProcessFragments— incremental fragment processing with callbacksBoxSeekReader— emulates seeking on non-seekable streams
External APIs use 1-based sample numbers (sample 1 = first sample). Internal slice storage is 0-based.
- golangci-lint with max line length 140 (
llllinter) - Only external dependency:
github.com/go-test/deep - Test roundtrips with
boxDiffAfterEncodeAndDecode(t, box)helper - Test both io.Reader and SliceReader decode paths where possible
- Primary spec: ISO/IEC 14496-12:2021 (7th edition)