Lesson 2 of 7

Transcoding Video

Convert videos between formats and codecs. Control quality with CRF, manage bitrates, and choose the right encoding preset for your use case.

What is Transcoding?

Transcoding is the process of decoding a video from its current format and re-encoding it into a different format. You might transcode to shrink a file for the web, make a video compatible with a specific device, or switch to a more efficient codec to save storage costs.

This is different from remuxing (which we covered in Lesson 1 using -c copy). Remuxing just changes the container without touching the encoded data. Transcoding re-encodes the data itself.

Containers vs. Codecs

Before diving into transcoding, it helps to understand the difference between containers and codecs — the two concepts people confuse most often:

  • Container (MP4, MKV, WebM, MOV) — the "box" that holds video and audio streams, subtitles, and metadata
  • Codec (H.264, H.265, VP9, AV1) — the algorithm used to compress and decompress the actual video data

An MP4 file could contain H.264 video, H.265 video, or even AV1 video. The container and codec are independent choices. When you transcode, you are changing the codec. When you remux, you are changing the container.

Choosing a Video Codec

H.264 (libx264) — The Safe Default

Plays everywhere: browsers, phones, smart TVs, social media. If you are unsure which codec to use, use H.264.

ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4

H.265 / HEVC (libx265) — Smaller Files

Produces 40-50% smaller files than H.264 at the same quality. Supported on most modern devices but not all browsers.

ffmpeg -i input.mov -c:v libx265 -tag:v hvc1 -c:a aac output.mp4

The -tag:v hvc1 flag ensures compatibility with Apple devices and QuickTime.

VP9 (libvpx-vp9) — Open Source, Web-Optimized

Google's open codec. Used by YouTube. Comparable compression to H.265. Works in Chrome, Firefox, and Edge.

ffmpeg -i input.mov -c:v libvpx-vp9 -b:v 2M -c:a libopus output.webm

AV1 (libsvtav1) — Best Compression, Slowest Encode

Next-generation codec. 30% smaller than H.265. Encoding is slow, but playback support is growing quickly.

ffmpeg -i input.mov -c:v libsvtav1 -crf 30 -preset 6 -c:a libopus output.mp4

Controlling Quality with CRF

CRF (Constant Rate Factor) is the most common way to control quality in FFmpeg. It tells the encoder: "I care about quality, not file size — pick whatever bitrate is needed to maintain this quality level."

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

Lower CRF = higher quality = larger file. The scale depends on the codec:

CRF ValueQuality (H.264)Use Case
0LosslessArchiving (huge files)
18Visually losslessMaster copies, editing
23Default — good qualityGeneral use (recommended starting point)
28Noticeable compressionPreviews, thumbnails
51WorstMinimum file size

Tip: Start at CRF 23 for H.264 (or CRF 28 for H.265 — the scales are different). Test the output. If it looks good, try a higher CRF to save space. If you see artifacts, lower it.

Target Bitrate Encoding

When you need predictable file sizes — for example, streaming at a fixed bandwidth — use target bitrate instead of CRF:

ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -c:a aac -b:a 128k output.mp4

Common bitrate targets for H.264:

  • 720p: 2-4 Mbps
  • 1080p: 4-8 Mbps
  • 4K: 15-30 Mbps

Encoding Speed with Presets

Presets control the trade-off between encoding speed and compression efficiency. A slower preset produces a smaller file at the same quality, but takes longer to encode.

ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 output.mp4

The available presets, from fastest to smallest output:

ultrafast → superfast → veryfast → faster → fast → medium → slow → slower → veryslow

medium is the default and a solid choice for most use cases. Use fast or veryfast when encoding time matters more than file size (e.g. live processing). Use slow for final renders where you want every byte optimized.

Two-Pass Encoding

When you need both a target bitrate and the best possible quality, use two-pass encoding. The first pass analyzes the video complexity. The second pass uses that analysis to distribute bits optimally.

# Pass 1 — analyze (output is discarded) ffmpeg -i input.mp4 -c:v libx264 -b:v 4M -pass 1 -an -f null /dev/null # Pass 2 — encode using the analysis ffmpeg -i input.mp4 -c:v libx264 -b:v 4M -pass 2 -c:a aac output.mp4

Two-pass is especially useful for long videos with varying complexity — like a tutorial that alternates between a talking head (simple) and a screen recording (complex). The encoder allocates more bits to the complex scenes.

Practical Recipes

Web-optimized MP4 (fast start)

ffmpeg -i input.mov -c:v libx264 -crf 23 -preset fast -movflags +faststart -c:a aac output.mp4

The -movflags +faststart flag moves the metadata to the beginning of the file, so browsers can start playing before the full download completes. Always use this for web video.

Batch convert a folder

for f in *.mov; do ffmpeg -i "$f" -c:v libx264 -crf 23 -c:a aac "${f%.mov}.mp4" done

Convert to H.265 for storage savings

ffmpeg -i input.mp4 -c:v libx265 -crf 28 -tag:v hvc1 -preset medium -c:a aac output_h265.mp4

Key Takeaways

  • Containers (MP4, MKV) hold streams; codecs (H.264, H.265) compress them — they are independent choices
  • H.264 is the safest default. H.265 saves ~50% space. AV1 saves more but encodes slowly.
  • Use CRF when quality matters, target bitrate when file size matters
  • Start at CRF 23 (H.264) or CRF 28 (H.265) and adjust from there
  • Always add -movflags +faststart for web video
  • Two-pass encoding gives the best quality at a fixed bitrate

Try This With FFmpeg Micro

Instead of running FFmpeg locally, you can use FFmpeg Micro's API to process videos in the cloud. No installation required.