transmux — MPEG-2 TS → CMAF/fMP4 remux
Container-layer remux from MPEG-2 Transport Stream to fragmented MP4 / CMAF,
built to spec (ISO/IEC 14496-12:2015, RFC 8216). Samples-in: the caller
supplies demuxed encoded access units + codec config; transmux produces the
initialization and media segments (and the HLS playlists). No transcode, no
codec bitstream decoding. no_std + alloc.
Scope — container multiplexing only
transmux packages coded media; it never encodes or decodes it. It parses
codec config/parameter headers (SPS/PPS/VPS, AAC ASC, AC-3/E-AC-3 syncframe
BSI) only far enough to build the container boxes and derive metadata
(dimensions, profile, sample rate, codecs= MIME). The compressed samples
themselves are opaque payloads copied through byte-for-byte — decode/encode
is the caller's job (WebCodecs, FFmpeg, hardware). Demux (TS → elementary
streams) also lives in the caller.
Every box has a symmetric Parse / Serialize with byte-identical round-trip
coverage against real fMP4 fixtures.
Feature matrix
Container — ISOBMFF / CMAF boxes
| Group | Boxes | Status |
|---|---|---|
| File structure | ftyp, styp, mdat, free/skip, uuid |
✅ |
| Movie | moov · mvhd · trak · tkhd · mdia · mdhd · hdlr · minf · vmhd/smhd · dinf/dref |
✅ |
| Sample tables | stbl · stsd · stts · ctts · cslg · stsc · stsz · stco/co64 · stss · stsh |
✅ |
| Edit / fragment-init | edts/elst, mvex/trex |
✅ |
| Movie fragments | moof · mfhd · traf · tfhd · tfdt · trun |
✅ |
| Random access / index | sidx, mfra/tfra/mfro |
✅ |
| Inband events / refs | emsg, tref |
✅ |
| Encryption (CENC) | senc/saiz/saio/tenc/pssh/sinf/schm/frma |
✅ |
| Sample-entry ext | colr (HDR), pasp, clap |
✅ |
| Live / grouping | prft, sbgp/sgpd, subs |
✅ |
Codecs — sample entries + config (header parse only)
| Codec | Sample entry | Config box / decode | RFC 6381 | Status |
|---|---|---|---|---|
| H.264 / AVC | avc1 (avc2/avc3/avc4) |
avcC + SPS/PPS decode (profile/level/chroma/bit-depth/dims/interlaced) |
avc1.PPCCLL |
✅ |
| H.265 / HEVC | hvc1 (hev1) |
hvcC + VPS/SPS + profile_tier_level decode |
hvc1.… |
✅ |
| AAC | mp4a |
esds / ES_Descriptor + AudioSpecificConfig (+ADTS) |
mp4a.40.N |
✅ |
| AC-3 | ac-3 |
dac3 + syncframe BSI parse |
ac-3 |
✅ |
| E-AC-3 | ec-3 |
dec3 + syncframe BSI parse |
ec-3 |
✅ |
| HE-AAC (SBR/PS) | mp4a |
explicit-SBR/PS ASC | mp4a.40.5/29 |
✅ |
| AC-4 | ac-4 |
dac4 |
ac-4 |
✅ |
| MPEG-H 3D | mha1/mhm1 |
mhaC |
— | ✅ |
| AV1 | av01 |
av1C |
av01.… |
✅ |
| Opus / FLAC / VP9 | Opus/fLaC/vp09 |
dOps/dfLa/vpcC |
— | ✅ |
| DTS | dtsc/dtsh/dtsl/dtse |
ddts |
— | ✅ |
Text / captions
| Format | Sample entry | Status |
|---|---|---|
| WebVTT / TTML | wvtt / stpp |
✅ |
| CEA-608/708 (in-band SEI) | SEI extraction | ⬜ #430 |
Pipeline & packaging
| Feature | API | Status |
|---|---|---|
| Init segment | build_init_segment (ftyp + fragmented-init moov) |
✅ |
| Media segment (batch) | build_media_segment (styp + moof + mdat) from TrackSpec / Sample |
✅ |
| Streaming segmenter | Segmenter — push samples → take_ready segments, keyframe-cut at a target duration |
✅ |
| NAL conversion | Annex B ↔ length-prefixed (annexb_to_length_prefixed / length_prefixed_to_annexb) |
✅ |
| HLS playlists | MediaPlaylist / MasterPlaylist (RFC 8216) |
✅ |
✅ = implemented + round-trip-tested · ⬜ = planned (issue linked)
Quick start
use ;
// Describe each track (codec config synthesised by the caller from SPS/PPS, ADTS…).
let tracks: = /* … */ Vecnew;
let init = build_init_segment?; // ftyp + moov
// Feed samples per fragment.
let video: = /* … */ Vecnew;
let media = build_media_segment?; // styp + moof + mdat
# Ok::
For a live/streaming source, Segmenter owns the segment-cutting state machine:
use ;
#
# if false
# Ok::
Codec metadata comes straight from the parsed headers — no external SPS parser:
# if false
tests/ts_to_cmaf.rs demonstrates the full path end-to-end: demux a real
H.264+AAC TS, synthesise avcC/esds, and emit byte-identical-config CMAF.
Spec grounding
Every layout cites its source (ISO/IEC 14496-12 boxes; 14496-1 §7.2.6 esds;
ITU-T H.264 §7.3.2.1.1 / H.265 §7.3.2.2 SPS; ETSI TS 102 366 Annex F AC-3/E-AC-3).
Codec-config tests decode real ffmpeg-encoded fixtures and assert against an
independent oracle (trace_headers fields; ffmpeg's own MP4-muxer config boxes).
License
MIT OR Apache-2.0.