# FFmpeg packaging case kit

Recorded September 7, 2026. Native FFmpeg 8.0.1, Python 3.14.6, Darwin 25.3.0 x86_64.
Read `ffmpeg-version.txt` for the actual build configuration.

This is a local CLI experiment. No browser startup, network transfer, CDN,
WebAssembly performance, seek latency, adaptive switching or device compatibility
was measured.

## Inputs and controls

All source media is generated from FFmpeg lavfi `testsrc2` (a moving geometric
pattern, 320 x 180, 30 fps, 8 seconds) and `sine` (660 Hz, 48 kHz, 8 seconds).
There is no external footage or audio to download, and no spoken content.
The fixture is deliberately small. It does not model a complex camera upload.

`ordinary-gop90.mp4` uses H.264/libx264, CRF 23, medium preset, yuv420p,
90-frame GOP, scene cuts disabled, closed GOP, no B-frames, one video encoding
thread and AAC mono 64 kbit/s. `faststart-gop90.mp4` is a stream-copy remux of
that exact file. `aligned-gop60.mp4` is a separate encode of the same procedural
source recipe with a 60-frame GOP. It is not a re-encode of ordinary-gop90.mp4
and is not used to claim equal packet data or equal picture quality.

## Observations

1. MP4 moov offset: 331128 -> 32 bytes. mdat offset: 40 -> 8318 bytes.
   Both completed files are 339406 bytes; both moov boxes are 8278 bytes.
   All 240 video and 376 audio packet hashes, timestamps, durations and flags
   match in per-stream order across the remux. Whole-file hashes differ.
2. Both HLS packages request `-hls_time 2`. With keyframes at 0/3/6 seconds,
   EXTINF durations are 3/3/2 seconds. With keyframes at 0/2/4/6 seconds,
   EXTINF durations are 2/2/2/2 seconds. These are playlist durations, not wall
   times observed by a browser. Both complete local playlists decode through
   FFmpeg without an error and every referenced asset is present.

## Reproduce

Extract `ffmpeg-packaging-case-kit.zip` and verify the archived artifacts:

```sh
shasum -a 256 -c SHA256SUMS
```

With Python 3 and FFmpeg/ffprobe on PATH (libx264 and AAC enabled):

```sh
python3 reproduce.py --output ./ffmpeg-reproduction
```

No Python packages, fonts, network services or credentials are needed. Use a
fresh output directory: the script overwrites its named generated files.
The result includes `run.json`, full probe and packet-hash records, versions,
all generated media, `commands.json` and `commands.sh`.

The script reads MP4 top-level box lengths rather than searching raw bytes for
`moov`. Per-packet data comes from `ffprobe -show_packets -show_data_hash sha256`.
It verifies the observed box, payload/timing and HLS invariants; unexpected
results cause a nonzero exit after saving the evidence.

`commands.json` records the commands actually invoked and exit codes.
`commands.sh` is an alternative to regenerate the media alone; run it from a
new directory. It does not perform the Python box/hash comparisons.
Do not compare freshly generated hashes to this archive as a cross-version
guarantee: FFmpeg/libx264 versions and builds may change encoded bytes. Retain
new version logs, inspect the new packets and check the structural invariants.

The archive manifest and SHA256SUMS identify published artifacts. They exclude
the manifest, checksum list and archive itself to avoid circular checksums.

## Inspect HLS locally

The two HLS directories must retain `index.m3u8`, `init.mp4` and all `.m4s`
segments together. A single media fragment is not a complete MP4.

```sh
ffprobe -v error -show_streams -show_format -of json hls-gop90/index.m3u8
ffmpeg -v error -i hls-gop60/index.m3u8 -map 0:v:0 -map 0:a:0 -f null -
```

These packages have one rendition, so they do not test adaptive variant
alignment or switching. Encoding closed GOPs and writing the
`independent_segments` tag should not be confused with a browser compatibility
test. HTTP Range, CORS, MIME types and player interactions require separate
checks against an actual deployment.

## Primary references

- [MOV/MP4 muxer and faststart](https://ffmpeg.org/ffmpeg-formats.html)
- [HLS muxer](https://ffmpeg.org/ffmpeg-formats.html)
- [Stream copy](https://ffmpeg.org/ffmpeg.html#Streamcopy)
- [ffprobe options](https://ffmpeg.org/ffprobe.html#Main-options)

Original fixture recipe, experiment code, results and commentary: AI Creator.
