C.W.K.
Stream
Lesson 05 of 10 · published

The Three-Stage Pipeline — Decode → Filter → Encode

~12 min · pipeline, architecture, muxer, demuxer

Level 0Viewer
0 XP0/73 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

What ffmpeg actually does, every time

Every ffmpeg invocation runs the same five-stage pipeline. Once you can draw it on a napkin, command-line flags stop feeling random.

  1. Demux — open the input container, split it into raw streams (video, audio, subtitle, data).
  2. Decode — convert each compressed stream into raw frames or samples.
  3. Filter — optionally run filters (scale, crop, drawtext, loudnorm, fps, …).
  4. Encode — compress the raw frames/samples back into a codec.
  5. Mux — wrap the encoded streams into the output container.

If you skip the encode step (-c copy), you have a remux: the bits go straight from demuxer to muxer with no re-encoding. That's why remuxing is sub-second on a 4K file but a re-encode of the same file takes minutes.

How flags map to stages

The order of flags on the command line is not the order they execute. Position matters: input flags go before -i, output flags go before the output filename. The mental model:

  • -ss 30 before -i = seek (skip to 30s) at demux time — fast.
  • -ss 30 after -i = seek by decoding all 30s and discarding — slow but frame-accurate.
  • -c:v libx264 before output filename = encoder choice for stage 4.
  • -vf scale=1280:720 = stage 3 filter applied to the video stream.

Code

All five stages on one line·bash
# Demux input.mov, decode video+audio, scale to 720p,
# encode to H.264 + AAC, mux into output.mp4
ffmpeg -i input.mov \
  -vf "scale=1280:720" \
  -c:v libx264 -crf 20 -preset slow \
  -c:a aac -b:a 192k \
  output.mp4
Skip encoding entirely (remux)·bash
# Demux + mux only — the same compressed bits land in a new container
# 30 seconds vs 30 minutes for a 4K source
ffmpeg -i input.mkv -c copy output.mp4

# Verify nothing got re-encoded: byte count should be very close
ls -lh input.mkv output.mp4

External links

Exercise

Take a single 30-second video clip. Run two commands: (1) ffmpeg -i clip.mp4 -c copy out_remux.mp4 and (2) ffmpeg -i clip.mp4 -c:v libx264 -crf 23 -c:a aac out_encode.mp4. Note the wall-clock time for each (use time). Confirm with ffprobe that out_remux.mp4 has the same codec_name as the input but a possibly different format_name.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.