MP4 faststart is the single configuration flag that determines whether your MP4 file can stream over HTTP or has to be fully downloaded first. The default ffmpeg behavior produces files where the moov box (the metadata index) is at the end of the file, which means HTTP streaming can't start playing until the entire file is downloaded. Adding -movflags +faststart moves the moov box to the front, enabling progressive playback. It's a one-line fix with significant UX implications. This page is the engineering reference.
What faststart actually does
MP4 files have a structural choice in where to place the moov box (movie metadata atom) relative to the mdat box (media data):
Default ffmpeg output: moov at the END of the file. Encoder writes mdat as content is encoded; only after encoding completes does it write the moov with byte offsets pointing back into mdat.
Faststart output: moov at the START of the file. Either pre-computed during encoding (one-pass faststart) or rewritten after encoding (two-pass faststart).
The placement matters because of how MP4 playback works:
- Player downloads
ftypbox (small). - Player needs to find
moovto understand the file's structure. - Player downloads
moov(size depends on file length, but typically 0.1-1% of total file). - Player can now compute byte offsets for any sample in the file.
- Player starts downloading
mdatand playing.
If moov is at the end:
- Player has to download the entire
mdat(essentially the whole file) before reachingmoov. - Even with byte-range support, finding the moov requires speculatively reading the end of the file.
- Without HTTP range support, the player has to download the whole file before playback can start.
If moov is at the front:
- Player downloads
moovimmediately afterftyp. - Playback starts as soon as enough mdat content has loaded for buffer requirements.
- Progressive streaming works.
Why it matters
For progressive HTTP streaming (a common pattern for short-form video, downloads with playback, embedded video on websites), faststart is essentially mandatory.
Without faststart:
- Page-embedded videos take seconds to start playing while the full file downloads.
- Progress bars on download-while-watching scenarios are confused (download progresses but playback doesn't start).
- HTTP byte-range requests work in theory but require speculative range-fetching that not all CDNs/players support.
With faststart:
- Playback starts within ~1-2 seconds of page load (after enough buffer accumulates).
- Standard HTTP delivery works without specialized streaming infrastructure.
- Player UX matches user expectations.
For fragmented MP4 (CMAF), faststart is irrelevant — fMP4's structure is inherently streaming-friendly. The faststart concern applies specifically to progressive (non-fragmented) MP4.
ffmpeg faststart usage
The flag is -movflags +faststart:
ffmpeg -i input.mov -c:v libx264 -crf 22 -c:a aac -movflags +faststart output.mp4
The + prefix adds to existing movflags rather than replacing them. Common combinations:
-movflags "+faststart+rtphint"
The rtphint flag adds RTP hint tracks (useful for some streaming servers).
The actual mechanism ffmpeg uses is two-pass faststart by default:
- First pass: encode normally with moov at end.
- Second pass: read the entire file, write a new file with moov at front.
This means faststart doubles the I/O during encoding — the second pass reads the full file and writes a new copy. For large files (long video, high bitrate), this is meaningful additional time and disk space.
Two-pass vs one-pass faststart
Two-pass (default) is what ffmpeg does. Slower, simpler, always works.
One-pass faststart is theoretically possible: pre-compute moov size, reserve space at the front of the file, write mdat, then write the actual moov in the reserved space. ffmpeg doesn't support one-pass faststart natively because moov size depends on content (number of samples, etc.) which isn't known until encoding completes.
Some specialized tools (qt-faststart from libav, mp4-faststart utilities) do post-processing faststart on existing files. Functionally similar to ffmpeg's two-pass approach but without re-encoding.
For ffmpeg-based pipelines, two-pass is the practical answer. Plan disk space and time for the second pass.
Streaming start time
With faststart, the time-to-first-frame depends on:
- moov download time — typically 0.1-1% of file size; for a 100 MB file, moov is ~100 KB-1 MB.
- mdat buffer — player typically buffers 1-3 seconds of content before starting.
- Network throughput — bandwidth determines how fast both moov and mdat arrive.
For a 100 MB file at 10 Mbps connection:
- moov: ~100-1000 ms.
- 1-second buffer: ~800 KB at typical encoded bitrate ≈ 600 ms.
- Total time-to-first-frame: ~1-2 seconds.
Without faststart, the same file would require downloading ~100 MB before playback — closer to 80 seconds at 10 Mbps. Wildly different UX.
Verifying faststart
To verify a file has faststart applied:
ffprobe -v error -show_entries format -of json input.mp4 | grep -i moov
Or examine box order with mp4info:
mp4info input.mp4 | head -30
Look at the order of top-level boxes:
ftypthenmoovthenmdat= faststart applied (good for streaming).ftypthenmdatthenmoov= no faststart (bad for streaming).
For automated verification in pipelines, parse the box order programmatically:
import struct
with open('input.mp4', 'rb') as f:
while True:
header = f.read(8)
if not header: break
size = struct.unpack('>I', header[:4])[0]
box_type = header[4:8].decode()
print(box_type)
if size == 0: break # last box
f.seek(size - 8, 1)
Output should show ftyp, moov, then mdat for faststart-applied files.
When faststart matters vs doesn't
Faststart matters for:
- Progressive download and playback over HTTP.
- Direct file delivery via CDN to browsers/apps.
- Video embeds on web pages.
- VOD download-while-watching apps (common for mobile streaming services).
- Any MP4 file delivered as a complete file (vs segments).
Faststart doesn't matter for:
- Fragmented MP4 (CMAF) — inherently streaming-friendly.
- HLS/DASH-segmented delivery — segments are inherently small and don't have the moov-position issue.
- Local file playback — desktop players can seek to find moov.
- Files only used as encoder intermediate — recipient is the encoder, not a player.
For most modern streaming infrastructure (CMAF + HLS/DASH), faststart isn't a concern. For older patterns (progressive MP4 delivery, direct file embeds), it's critical.
Faststart and file size
The mechanical observation: faststart doesn't change file size meaningfully. The moov is the same content; just relocated. Total file size is identical to within a few KB (depending on padding).
Time and disk space cost:
- Encoding: same wall-time (the actual encode is unchanged).
- Faststart pass: roughly 2x the I/O bandwidth of writing the file (read entire input, write entire output).
- Total: ~10-30% additional time for the faststart pass on typical hardware.
For pipeline operations where time is constrained, faststart adds modest overhead. The benefit (progressive streaming works) is worth it for any progressive-MP4 use case.
Faststart vs progressive vs fragmented
The progressive MP4 delivery patterns:
Plain progressive MP4 (no faststart) — moov at end. Requires full file download before playback. Bad for streaming.
Faststart progressive MP4 — moov at front. Progressive streaming over HTTP works.
Fragmented MP4 (fMP4) — distinct container variant. Sequential moof+mdat fragments. Native streaming-friendly without faststart concept.
The progression: faststart is a workaround for plain MP4's structural constraint. Fragmented MP4 is the architectural solution for streaming-native MP4.
For 2026 production:
- Streaming pipelines use fragmented MP4 / CMAF for live and adaptive streaming.
- Progressive MP4 use cases use faststart to enable HTTP streaming.
- The two coexist for different use cases.
Operational considerations
Things that matter for faststart in production:
- Default to enabling faststart — unless you have a specific reason not to,
-movflags +faststartshould be in every progressive MP4 encoding pipeline. - Disk space for two-pass — temporary disk space equal to file size during the faststart pass. Plan accordingly.
- Verification step — automated pipeline verification should check moov position. Catch faststart failures before they reach production.
- CDN compatibility — most CDNs serve faststart MP4 correctly. Some legacy CDN configurations have issues with byte-range requests for non-faststart MP4 — usually solved by ensuring faststart.
- Player behavior — modern players handle both faststart and non-faststart correctly. Older players (legacy embedded systems, very old browsers) may behave differently. Test on actual targets.
- Streaming server behavior — some HTTP streaming servers (Wowza, etc.) handle non-faststart files via internal repackaging. For static-file delivery via CDN, faststart is the answer.
What MpegFlow does with MP4 faststart
MpegFlow's DAG runtime applies -movflags +faststart at the FfmpegExecutor stage that emits progressive MP4 outputs. CMAF / fragmented-MP4 outputs don't need or use faststart and that path is unchanged.
For pipelines producing both progressive MP4 (download/embed delivery) and CMAF (HLS/DASH streaming), the workflow models each output target as separate stages in the DAG; the partitioner persists each to job_stages with explicit dependency tracking and per-stage retry. Progressive MP4 stages run with faststart applied; CMAF stages use fragmented structure natively. Sibling cancellation propagates fatal failures across rendition outputs to avoid wasted compute on dependents.
When workflow specs require post-encode moov-position verification (some pipelines run this as a separate sanity check), it's expressed as a downstream stage that consumes the encode output via cross-stage data flow.
The strict-broker security model treats faststart as ordinary workflow configuration; workers carry no ambient credentials and operate per spec.
For customers asking about MP4 streaming optimization, the standing recommendation is: progressive MP4 with faststart for direct file delivery; CMAF for streaming infrastructure (HLS/DASH). Don't try to use non-faststart progressive MP4 for streaming; the UX is broken.
The general guidance: faststart is a mechanical fix for a structural issue with default MP4 box ordering. It costs modest time and disk space; it produces dramatically better streaming UX. Apply it to every progressive MP4 unless there's a specific reason not to.