General
The ffmpeg Pipeline Nobody Explains
Athreya aka Maneshwar DEV Community 周榜
1 views
Hello, I'm Maneshwar, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product.
ffmpeg is the one CLI tool everyone uses and most doesn't understand
Every developer has run this exact incantation at some point in their life, copy-pasted from a Stack Overflow answer from 2014, with zero idea what it does:
ffmpeg -i input.mov -vcodec h264 -acodec mp2 output.mp4
It works. You move on. You never ask what -vcodec actually does, or why some conversions finish in a blink and others chew your CPU for ten minutes.
Turns out there's a genuinely elegant pipeline hiding under the hood, and once you see it, half of ffmpeg's flag soup starts making sense on its own.
ffmpeg was created by Fabrice Bellard back in the year 2000, and the name is a mashup of "fast forward" and MPEG, the Moving Picture Experts Group, the folks behind most of the video formats you've heard of.
It's not just a CLI toy either.
It's the encode/decode engine quietly running inside Chrome, Blender, YouTube, Vimeo, and roughly half of every video-adjacent tool you've ever used.
Source: ffmpeg.org.
The pipeline nobody tells you about
Here's the thing that clicked for me: ffmpeg isn't one operation, it's a pipeline, and every flag you pass just tweaks one stage of it.
Walk through it left to right:
Input — your file lands, in.mp4, whatever.
Demux — a demultiplexer splits the container into its separate streams. Your "video file" was never one thing, it's a video track, an audio track, maybe subtitles, all interleaved into one file for convenience.
Decode — each stream's compressed packets get decoded into raw, uncompressed frames. This is the CPU-hungry part.
Filter — optional. This is the only stage that actually touches pixels or audio samples: brightness, contrast, scaling, adding subtitles, drawing a waveform. Skip it and nothing changes.
Encode — raw frames get compressed back down into packets, in whatever codec you asked for.
Mux — a multiplexer interleaves the encoded streams back into one output container.
Output — out.mkv, done.
ffmpeg -i in.mp4 out.mp4 runs the whole thing with sane defaults. ffprobe just runs the first couple of stages and prints what it finds, no encode required, which is why it's instant.
With over 100 codecs supported, that same seven-stop pipeline is how ffmpeg decodes, encodes, transcodes, filters, and plays basically any multimedia file that exists. Source: ffmpeg.org/about.html.
The flag that changes everything: -c copy
Once you see the pipeline, one thing jumps out immediately: decode and encode are the only expensive stages. Demux and mux are just bookkeeping, shuffling bytes around.
So what happens if you skip decode and encode entirely?
ffmpeg -i input.mp4 -c copy output.mkv
-c copy tells ffmpeg "don't touch the streams, just repackage them." It demuxes, then immediately muxes into the new container.
No decode, no encode, no quality loss, because the actual video bytes never change, they just get moved into a different box.
This is why converting .mp4 to .mkv is instant, but converting .mp4 to .webm is not: mp4 and mkv can both hold H.264 video, so it's a pure repackage.
webm wants VP8/VP9/AV1, a codec mp4 usually isn't carrying, so ffmpeg has no choice but to actually decode and re-encode every frame.
Once you've internalized that, most of ffmpeg's common recipes stop being magic incantations and start being obvious:
ffmpeg -i input.mov -c copy -ss 00:00:30 -t 00:00:10 clip.mov
Trim ten seconds starting at 0:30. Since we're not changing codecs, -c copy keeps it instant. Same file, smaller slice.
Need to glue several clips together? List them in a text file and hand it to the concat demuxer:
ffmpeg -f concat -safe 0 -i list.txt -c copy joined.mp4
Still -c copy. Still no re-encode. It's the same pipeline principle, just applied to multiple inputs instead of one.
When you actually need the expensive path
Sometimes copy isn't an option, because you're deliberately changing the pixels or the codec, not just the wrapper. That's when -vf (video filter) and real encode flags come in:
ffmpeg -i input.mp4 -vf "scale=1280:720" -r 30 -b:v 2M -c:v libx264 output.mp4
-vf scale resizes, -r sets the frame rate, -b:v sets the video bitrate, -c:v libx264 picks the encoder. Every one of these forces a real decode → filter → encode pass, which is exactly why this version is slow and -c copy isn't.
Subtitles go through the same filter stage. Got an .srt file? Convert it to .ass first, then burn it in with -vf subtitles, since -vf is the only stage in the whole pipeline that's allowed to touch a frame.
Here's the decision tree I actually keep in my head now, roughly:
flowchart TD
A[I have a media file and ffmpeg] --> B{Just changing container, same codecs?}
B -->|yes| B1[-c copy]
B -->|no| C{Need a smaller file or a different codec?}
C -->|yes| C1[-c:v libx264 -c:a aac]
C -->|no| D{Just trimming a section?}
D -->|yes| D1[-ss start -t dur -c copy]
D -->|no| E{Joining multiple clips together?}
E -->|yes| E1[concat demuxer + -c copy]
E -->|no| F{Changing resolution, framerate or bitrate?}
F -->|yes| F1[-vf scale, -r, -b:v]
F -->|no| G{Burning in subtitles?}
G -->|yes| G1[srt to ass, then -vf subtitles]
classDef decision fill:#f4d35e,stroke:#b8991f,color:#1a1a1a
classDef start fill:#e9ecef,stroke:#6c757d,color:#1a1a1a
classDef action fill:#5ee6c8,stroke:#1f9c86,color:#1a1a1a
class A start
class B,C,D,E,F,G decision
class B1,C1,D1,E1,F1,G1 action
Every branch of that tree is the same seven-stage pipeline, just with a different subset of stages actually doing work.
The rest of the toolbox
Two more binaries ship alongside ffmpeg and are worth knowing exist:
ffprobe — inspects a file and dumps its metadata: codecs, resolution, duration, bitrate, stream count. It's the tool for "wait, what actually is this file" before you commit to a slow encode.
ffplay — a minimal media player built on the same libraries, for when you just want to preview something from the terminal without opening a full video app.
And under all three sits a stack of libraries, libavcodec, libavformat, libavfilter, and friends, that other software links against directly rather than shelling out to the CLI. That's the actual reason ffmpeg ended up powering Chrome's media playback and Blender's video editor: it was never really "a command line tool," it was a media engine that happened to ship a command line tool as its front door.
Why this is worth knowing
None of this is trivia for its own sake.
Once the pipeline is in your head, ffmpeg's entire flag surface stops being a wall of options to memorize.
You start asking "which stage am I actually touching" before you type a command, and the answer tells you whether it'll take a second or a coffee break, and whether you even need to.
That's the whole trick.
The tool has a hundred flags, but only one shape underneath all of them.
Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production secure and reliable without slowing you down.
I'm building LiveReview, a blast-radius aware AI code review built for your business-critical systems.
Instead of presenting every diff with equal emphasis, LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters.
Spend code review effort where business risk is highest — not spread evenly across every diff.
⭐ Star it on GitHub:
HexmosTech
/
LiveReview
Blast-Radius Aware AI Code Review for Business-Critical Systems
LiveReview: Blast-Radius Aware AI Code Review for Business-Critical Systems
LiveReview is an AI code reviewer that scores every hunk of a diff by blast radius: how far a change reaches through your call graph, how much persistent state it touches, and how well-tested it is. A 3-line change to a shared auth check can outrank a 300-line UI tweak. Your team's attention goes to the highest-risk code first, not spread evenly across every diff.
blast-radius-demo.mp4
LiveReview's Blast Radius & Review Priority scoring, live in the diff viewer.
The exact math, not a black box
Visualize blast radius at a glance
Every factor that feeds the score
How does Blast Radius scoring work? (a more technical explanation)
Here's the goal:
A 3-line fix in a function used by 40 other files, that also writes to a database, should score high.
A 300-line UI change in one file, fully covered by…
View on GitHub
Click below to try LiveReview with your codebase:
Read original: https://dev.to/lovestaco/the-ffmpeg-pipeline-nobody-explains-7d8
← Previous
D-Matrix Raptor 3D-DRAM Accelerator for Generative Inference at Hot Chips 2026
Next →
One Callback URL Misconfiguration Leaks Every OAuth Token
Related
One Callback URL Misconfiguration Leaks Every OAuth Token
General
0
DEV Community 周榜
Designing a Production-Ready Data Science Pipeline: From Raw Events to Monitored Models
General
0
DEV Community 周榜
Put your particle effects in CI: the silent-skip bug nobody catches by eye
General
0
DEV Community 周榜
What Does a Production RAG System Need? Vector Search, Chunking, Guardrails, and Cost Controls
General
0
DEV Community 周榜
Comments0
No comments yet — be the first