every.channel/evolution/proposals/ECP-0033-x264-cmaf-fmp4.md
2026-02-15 16:17:27 -05:00

3 KiB

ECP-0033: Deterministic x264 + CMAF(fMP4) Segment Mode

Summary

Add an optional stream mode that publishes HLS-compatible CMAF-style fragmented MP4 segments (.m4s) encoded with single-threaded libx264 + AAC, alongside a separate init segment (init.mp4). The init segment is published on a dedicated MoQ side-track so subscribers can start playback without out-of-band files.

This is an incremental step toward a MoQ-native media pipeline while keeping browser playback practical via standard HLS fMP4 semantics.

Goals

  • Provide a "mature codec path" for experimentation: libx264 + AAC.
  • Make output more browser-friendly than raw MPEG-TS while staying simple.
  • Preserve deterministic encoding constraints where feasible:
    • single-threaded encoder
    • +bitexact flags
    • fixed GOP
  • Keep the change reversible:
    • default remains raw TS chunk publication
    • CMAF mode is opt-in via CLI

Non-Goals

  • Full CMAF compliance validation across players.
  • Multi-track audio language selection.
  • End-to-end determinism across independent antennas (this requires timebase normalization and additional constraints).
  • MoQ wire-level media standardization (that belongs in a later ECP).

Design

  • Publisher (ec-node moq-publish) adds --encode {ts|cmaf}.
  • In cmaf mode:
    • ingest bytes from the source (TS file/HDHR/iptv adapter)
    • invoke ffmpeg to encode and segment to HLS fMP4:
      • writes init.mp4 and segment_%06d.m4s
    • publish:
      • init.mp4 as a single MoQ object on --init-track (default: init)
      • .m4s segments as MoQ objects on the main track
    • all MoQ tracks (objects, init, manifests) are created before the broadcast is published to avoid implementation quirks where late-added tracks are not deliverable
    • manifests remain per-epoch over the segment objects only (init is out-of-manifest for now)
  • Subscriber (ec-node moq-subscribe) adds:
    • --container {ts|cmaf}
    • --subscribe-init to fetch init.mp4 from --init-track
    • local output becomes:
      • index.m3u8 with #EXT-X-MAP:URI="init.mp4"
      • init.mp4
      • rolling window of segment_*.m4s

Rationale

  • fMP4 (CMAF-style) is broadly supported by modern HLS implementations and aligns with future MoQ media layouts.
  • libx264 is stable and widely available, making it a pragmatic baseline for determinism experiments.
  • Publishing init as a side-track avoids special cases in the primary segment stream and keeps the UI/receiver model "a stream is a stream".

Risks

  • MP4 muxers can embed non-deterministic metadata (timestamps/brands). We mitigate by:
    • +bitexact flags and single-threaded encoding
    • stripping container metadata where feasible (future follow-up may be needed)
  • Segment boundaries are time-based and depend on timestamps/keyframes; cross-antenna byte equality is not guaranteed yet.

Rollout

  • Land CMAF mode behind --encode cmaf and --container cmaf.
  • Add an ignored HDHomeRun E2E test that exercises split-source mesh in CMAF mode.