Almost every FFmpeg task comes down to one fundamental decision: do you copy the existing streams or re-encode them? Choosing right can mean the difference between a one-second lossless operation and a ten-minute lossy one. This guide explains what each path does, when to use it, and the one caveat that trips people up — container compatibility. Once this clicks, most other FFmpeg commands make sense. Estimated time: 6 minutes.

Tested with: FFmpeg 8.1


What You’ll Learn

  1. What stream copy (-c copy) actually does
  2. What re-encoding does and why it costs more
  3. A side-by-side comparison
  4. The container compatibility caveat
  5. When to copy and when to re-encode
  6. Copying or re-encoding individual streams
  7. Troubleshooting and FAQ

1. Stream Copy (-c copy)

Stream copy moves the already-compressed audio and video packets from the input straight into a new container, without decoding or re-compressing them. The basic command:

ffmpeg -i input.mp4 -c copy output.mp4
  • -c copy … copy all streams as-is (shorthand for -c:v copy -c:a copy ...).

Because nothing is decoded, stream copy is:

  • Lossless — not a single bit of the media is altered.
  • Fast — typically finishes in seconds, limited mostly by disk speed.
  • Light — almost no CPU usage.

It’s the right tool for changing containers (remuxing), cutting on keyframes, or merging streams — anything that doesn’t need to alter the actual picture or sound.


2. Re-encoding

Re-encoding decodes each frame back to raw form and then compresses it again with a chosen encoder. The basic command:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac output.mp4
  • -c:v libx264 … re-encode video to H.264.
  • -crf 23 … quality target (lower = better quality, larger file).
  • -c:a aac … re-encode audio to AAC.

Re-encoding is:

  • Lossy — recompression discards some detail (for lossy codecs). Quality never improves.
  • Slow — every frame is decoded and encoded; this is CPU-heavy.
  • Flexible — you can change codec, resolution, bitrate, frame rate, filters, and more.

It’s required whenever you need to actually change the media: compress it, resize it, convert to an incompatible codec, or apply filters.


3. Side by Side

-c copy (stream copy)Re-encode
QualityLossless (identical)Lossy (some loss)
SpeedSecondsMinutes (CPU-bound)
CPU usageMinimalHigh
File size~Same as sourceControllable
Change codec?NoYes
Resize / filter?NoYes
Change container?YesYes
Cut anywhere?Keyframes onlyAny frame

The rule of thumb: copy when you can, re-encode when you must.


4. The Container Compatibility Caveat

Stream copy fails if the source codec isn’t allowed inside the target container. Each container accepts only certain codecs. For example:

  • MP4 accepts H.264, HEVC, AAC — but not PCM or ProRes.
  • WebM accepts VP9/AV1 + Opus/Vorbis — but not H.264 or AAC.

So this can fail even though no quality change is intended:

ffmpeg -i input.mp4 -c copy output.mp4

If FFmpeg prints Could not find tag for codec ... in stream, the codec doesn’t fit the chosen container. Your options are to pick a compatible container, or re-encode just the offending stream to a codec the container accepts (Section 6).

Source codecTarget containerCopy works?
H.264 + AACMP4 / MKVYes
HEVC + AACMP4 (add -tag:v hvc1)Yes
VP9 + OpusWebM / MKVYes
VP9 + OpusMP4No (re-encode)
PCM audioMP4No (re-encode audio)
Almost anythingMKVUsually yes

MKV is the most permissive container, which is why stream copy “just works” into MKV far more often than into MP4.


5. When to Copy and When to Re-encode

Use -c copy when:

  • Changing only the container (e.g., MKV to MP4, MOV to MP4).
  • Trimming at keyframe boundaries.
  • Merging or splitting without altering the media.
  • The streams are already compatible with the target.

Re-encode when:

  • Compressing to reduce file size.
  • Changing resolution, frame rate, or pixel format.
  • Converting to a codec the container or device requires.
  • Applying filters (scale, crop, overlay, subtitles burn-in, color).
  • Cutting frame-accurately between keyframes.

6. Per-stream Choices

You don’t have to treat every stream the same. A common pattern is to copy the video (the expensive part to encode) while re-encoding only the audio into a compatible codec:

ffmpeg -i input.mp4 -c:v copy -c:a aac -b:a 192k output.mp4

Here the video is untouched and instant, and only the audio is re-encoded — far faster than a full re-encode while solving an audio-codec incompatibility. The reverse (re-encode video, copy audio) works too:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a copy output.mp4

7. Troubleshooting

Error 1: Could not find tag for codec ... in stream

Cause: The source codec isn’t allowed in the target container during a copy. Fix: Choose a compatible container (MKV is most permissive) or re-encode that stream (Section 6).

Error 2: The trimmed copy starts with a frozen frame or black gap

Cause: Stream copy can only cut on keyframes, so the cut snaps to the nearest one. Fix: Re-encode for frame-accurate cuts, or accept the keyframe boundary. See the trimming workflow in related guides.

Error 3: Re-encoding made the file bigger, not smaller

Cause: Your -crf (or bitrate) is set higher quality than the source warrants. Fix: Raise the CRF number (e.g., 23 to 26) to compress more, and confirm you actually need to re-encode at all.

Error 4: Copy succeeds but the file won’t play in a browser

Cause: The moov atom is at the end of the MP4. Fix: Add -movflags +faststart. See the faststart guide.


FAQ

Q1. Does -c copy ever change quality? A. No. It copies compressed packets verbatim — the media is bit-for-bit identical. Only re-encoding can change quality.

Q2. Why is re-encoding so much slower? A. It decodes every frame to raw pixels and compresses them again. Copy just moves existing packets, which is orders of magnitude less work.

Q3. Can I re-encode without losing quality? A. Only with lossless encoders (e.g. FFV1, or -qp 0 for libx264), which produce huge files. Normal lossy re-encoding always discards some detail.

Q4. How do I know which codecs my file uses? A. Run ffprobe input.mp4 and read the stream lines, or use ffprobe -show_streams. Then check the table in Section 4 for copy compatibility.

Q5. Should I default to copy or re-encode? A. Default to -c copy. Only re-encode when you actually need to change the media (size, resolution, codec, filters) or when copy fails due to container incompatibility.



Tested with FFmpeg 8.1 — verified with our command-check script Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-codecs.html