An MP4 / M4A is a tree of nested boxes (atoms): every box opens with a big-endian u32 size and a four-character type code, then holds either more boxes or a typed payload. Defined by ISO/IEC 14496-12 (ISO Base Media File Format), originally derived from QuickTime. Hover a field to light its bytes, click a + for its lookup table. Color marks kind (see the key).
Every MP4 is a flat sequence of top-level boxes; moov holds the entire metadata tree.
A FullBox. timescale and duration are the only two fields most readers want.
Absolute file offsets. This is the structure that breaks when a file is rewritten.
stsc, which maps samples to chunks, and stsz, which gives each sample's size. The three together turn a chunk offset into a byte range; any one alone does not. The bytes they point into live in mdat, which holds the raw coded audio and nothing else -- no framing, no index.free atom next to moov. Growing a tag eats padding; shrinking one gives it back. Nothing after it moves, so every stco offset stays correct and the edit is a patch rather than a rewrite. That padding is the mechanism behind in-place tagging, and a writer that ignores it forces a full rewrite for a one-character title change.Raw encoded audio frames with no intrinsic framing. May appear before moov (streaming layout) or after it. The stco/co64 box inside stbl holds absolute file offsets into mdat; duration = sum of the stts sample deltas / mvhd timescale. Because samples are reached only through stsc + stsz + stco/co64, any bytes in mdat that no sample table points at are a legal cavity -- edit leftovers, alignment padding, or a place to hide data.
Payload is zeroed or arbitrary. Sized to let moov be rewritten in place without moving stco sample offsets into mdat.
The whole metadata path in one view: a named atom, its data sub-atom, and the text.
ilst is not the first thing inside meta. After meta's four version/flags bytes comes an hdlr handler atom -- mdir/appl for iTunes metadata -- and only then ilst. It declares what kind of metadata follows, and skipping past it is the normal thing to do.8 bytes before every box. Example: 00 00 00 18 66 74 79 70 = size 24, type "ftyp".
16-byte payload after the 8-byte header (total box = 24 bytes). major_brand "M4A ", minor_version 0, compatible_brands "M4A " + "mp42".
Typical top-level layout for an M4A audio file. All timing, codec, and tag metadata lives inside moov; raw samples live in mdat.
ftyp brand declaration (first box in file)
moov movie container
├─ mvhd timescale + duration (length = duration / timescale)
├─ trak audio track
│ └─ mdia › minf › stbl sample tables
│ ├─ stsd codec ("mp4a" = AAC, "alac" = ALAC)
│ ├─ stts time-to-sample table
│ ├─ stsc sample-to-chunk mapping
│ ├─ stsz per-sample byte sizes
│ └─ stco chunk offsets into mdat
└─ udta › meta › ilst iTunes tags (title, artist, artwork, BPM ...)
mdat raw encoded audio samples
Streaming files (DASH, HLS) drop the single moov + mdat for repeated fragments. Here moov is an init segment carrying an mvex that declares fragments follow but holds no samples; each fragment is a moof (with traf > trun giving per-sample sizes and offsets) paired with its own mdat. Segments may open with a styp brand box. Sample offsets then live in trun, not stco.