--- ogImage: "/og/why-ffmpeg-map-0-breaks-your-mp4-and-mkv-remux.jpg" banner: "/banners/why-ffmpeg-map-0-breaks-your-mp4-and-mkv-remux.jpg" title: "Why ffmpeg -map 0 Breaks Your Remux: The Hidden Matrix of Multi-Track MP4 and Matroska" description: "Why using -map 0 silently aborts Matroska muxers, drops subtitle fonts, and corrupts Apple playback: an empirical teardown of container constraints across multi-track media pipelines." pubDate: 2026-10-27 category: engineering blueprint: self-hosted-infrastructure blueprintLayer: L1-compute-storage-network tags: ["ffmpeg", "containers", "mp4", "matroska", "subtitles", "media-pipeline"] draft: false summary: audience: "Media Systems Engineers, Full-Stack Architects & Streaming DevOps" painPoint: "A media remuxing daemon using naive -map 0 silently crashed on container conversions, dropped stylised subtitles, and broke track selection on iOS clients." impact: - metric: "Zero Muxer Aborts" detail: "Isolated incompatible QuickTime chapters and mobile timecode streams (tmcd) that caused Matroska muxers to fatal-error on generic -map 0 invocations." - metric: "100% Subtitle Survival" detail: "Architected deterministic conversion from ASS/SRT into mov_text for MP4 while preserving bit-exact font attachments in Matroska." - metric: "Cross-Platform Metadata" detail: "Dual-wrote track titles to both udta/name (Apple) and hdlr (ffprobe/VLC), solving the silent loss of track names during secondary remux passes." stack: ["FFmpeg", "ffprobe", "Python", "Matroska/MP4 Specifications"] jumpLinks: business: "#the-naive-map-0-that-breaks-in-production" architecture: "#the-hidden-matrix-of-container-behavior" result: "#the-result" dynamicCta: true --- ## The naive `-map 0` that breaks in production Every developer automating FFmpeg reaches for the same shortcut when preserving secondary tracks during a transcode: ```bash ffmpeg -i source.mkv -map 0 -c:v libx265 -c:a copy output.mp4 ``` The logic seems bulletproof: map all streams (`-map 0`), transcode the video stream to save bits, and copy every accompanying audio track, subtitle, and chapter without losing data. In production across a large, diverse video archive, this command fails catastrophically in four distinct ways: 1. **It hard-crashes on Matroska output**: If an MP4 source contains Apple QuickTime text chapters (`bin_data`) or iPhone timecode tracks (`tmcd`), FFmpeg aborts instantly: `Only audio, video, and subtitles are supported for Matroska.` 2. **It hard-crashes on MP4 output**: In standard stream copy mode (`-c:s copy`), any ASS, SSA, SRT, or graphical Bitmap (PGS) subtitle triggers fatal aborts: `Could not find tag for codec ass in stream #2, codec not currently supported in container.` Even when enabling subtitle transcoding to `-c:s mov_text`, graphical bitmap subtitles (`hdmv_pgs_subtitle` or `dvd_subtitle`) cannot be converted into text atoms and cause identical muxer crashes. 3. **It silently strips font attachments**: When remuxing into MP4, attached `.ttf` or `.otf` styling fonts cause fatal errors: `Could not find tag for codec ttf`. 4. **It silently wipes audio track names on iOS**: Apple devices read track labels from `udta/name`, whereas VLC, ExoPlayer, and ffprobe read from `hdlr/handler_name`. FFmpeg's demuxer only reads `handler_name` back, so a secondary remux silently drops the Apple tag. Building an automated, crash-proof media pipeline means never treating containers as transparent envelopes. It requires an explicit, policy-driven stream planner. --- ## The hidden matrix of container behavior Through automated test fixtures and packet-level MD5 hashing across thousands of source files, I mapped the exact boundaries between MP4 and Matroska (`.mkv`): | Feature / Track Type | MP4 (`.mp4`) Constraints | Matroska (`.mkv`) Behavior | |---|---|---| | **Audio Codecs** | Officially supports AAC. AC-3/E-AC-3 work on Apple, but Android player matrices break. | Accepts anything bit-exact (FLAC, DTS-HD, TrueHD, Opus, AAC). | | **Text Subtitles** | **Only accepts `mov_text` (tx3g)**. ASS, SRT, WebVTT cause immediate muxer fatal aborts. | Copies ASS, SSA, SRT verbatim without re-encoding. | | **Subtitle Styling** | `mov_text` strips fonts, positioning, shadows, and karaoke fades. Only basic bold/italic survives. | Preserves all Aegisub styling, override tags, and positioning. | | **Font Attachments** | **Refused outright**. `Could not find tag for codec ttf`. | Carried verbatim bit-for-bit via `0:t` stream mapping. | | **Timecode / Chapter Data** | Holds QuickTime text and `tmcd` streams natively. | **Fatal error** if passed raw QuickTime/timecode data tracks. | | **Metadata Preservation** | Drops `creation_time` without `-map_metadata 0`; drops custom tags without `-movflags +use_metadata_tags`. | Preserves arbitrary key-value tags natively. | Notice the asymmetry: **MP4 is an end-user distribution container with strict parser gates, while Matroska is a high-fidelity archival container.** Treating them identically with `-map 0` guarantees pipeline crashes. **Why not standardize exclusively on MKV?** Because container selection is dictated by downstream client decoding contracts. Native Apple playback engines (`AVPlayer` on iOS/macOS and WebKit `