How to Convert Video Format with FFmpeg

Apr 21, 2026

Video format conversion is one of the most common tasks in media processing. Whether you need MP4 for the web, MOV for Apple workflows, or WebM for open-source projects, FFmpeg handles them all from the command line. This guide covers everything from basic conversions to advanced codec selection and batch processing.

Basic Format Conversion

The simplest conversion just changes the container format. FFmpeg detects the output format from the file extension:

# Convert MKV to MP4
ffmpeg -i input.mkv output.mp4

# Convert AVI to MOV
ffmpeg -i input.avi output.mov

# Convert MP4 to WebM
ffmpeg -i input.mp4 output.webm

When you don't specify codecs, FFmpeg picks defaults for the target container. This works but doesn't give you control over quality or compatibility.

Understanding Containers vs Codecs

Before diving deeper, it helps to understand the difference:

  • Container (MP4, MKV, MOV, AVI, WebM) — the file format that holds video, audio, and metadata
  • Video codec (H.264, H.265, VP9, AV1) — how video data is compressed
  • Audio codec (AAC, Opus, MP3, FLAC) — how audio data is compressed

A container is like a box; codecs are what's inside. The same video codec can live in different containers.

ContainerCommon Video CodecsCommon Audio CodecsBest For
MP4H.264, H.265, AV1AAC, MP3Web, mobile, general use
MKVAnyAnyArchiving, multi-track media
MOVH.264, H.265, ProResAAC, PCMApple ecosystem, editing
WebMVP8, VP9, AV1Vorbis, OpusWeb (open-source)
AVIH.264, MPEG-4MP3, PCMLegacy compatibility

Codec Selection Guide

H.264 — Maximum Compatibility

H.264 (libx264) plays on virtually every device and browser. It's the safest choice for general distribution.

ffmpeg -i input.avi -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

H.265 (HEVC) — Better Compression

H.265 (libx265) delivers ~50% smaller files at the same quality. Support is growing but not yet universal.

ffmpeg -i input.avi -c:v libx265 -crf 28 -preset medium -c:a aac -b:a 128k output.mp4

Note: H.265 uses a different CRF scale. CRF 28 in H.265 is roughly equivalent to CRF 23 in H.264.

VP9 — Open-Source, Web-Friendly

VP9 is Google's royalty-free codec. It pairs with WebM and is supported by all modern browsers.

ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm

The -b:v 0 tells FFmpeg to use pure CRF mode (no bitrate ceiling).

AV1 — Next Generation

AV1 offers the best compression ratio but encoding is very slow. Use it when you have time and want the smallest files.

ffmpeg -i input.mp4 -c:v libaom-av1 -crf 30 -cpu-used 4 -c:a libopus -b:a 128k output.mkv

-cpu-used 4 speeds up encoding significantly (range 0-8, higher = faster but lower quality).

Codec Comparison

CodecCompressionSpeedBrowser SupportLicense
H.264GoodFastUniversalLicensed
H.265BetterMediumGrowingLicensed
VP9BetterSlowAll modernRoyalty-free
AV1BestVery slowGrowingRoyalty-free

Audio Codec Pairing

Each container works best with certain audio codecs:

# MP4 + AAC (most common pairing)
ffmpeg -i input.mkv -c:v libx264 -crf 23 -c:a aac -b:a 192k output.mp4

# WebM + Opus (best quality per bitrate)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm

# MKV + FLAC (lossless audio)
ffmpeg -i input.mov -c:v libx264 -crf 18 -c:a flac output.mkv

# MOV + PCM (uncompressed, for editing)
ffmpeg -i input.mp4 -c:v copy -c:a pcm_s16le output.mov
Audio CodecQualityFile SizeBest Container
AACGoodSmallMP4, MOV
OpusExcellentSmallestWebM, MKV
MP3GoodSmallMP4, AVI, MKV
FLACLosslessLargeMKV
PCMLosslessVery largeMOV, WAV

Stream Copy — Instant Conversion

When the source codecs are compatible with the target container, you can copy streams without re-encoding. This is instant and lossless:

# Remux MKV to MP4 without re-encoding
ffmpeg -i input.mkv -c copy output.mp4

# Copy video, re-encode audio only
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 128k output.mp4

Stream copy only works when the codecs are supported by the target container. For example, you can't put VP9 video into an AVI container.

Quality vs File Size

CRF Mode — Best for Local Files

CRF (Constant Rate Factor) gives the best quality-to-size ratio. The encoder adjusts bitrate scene by scene. For a deeper dive into compression techniques, see our video compression guide.

# High quality (larger file)
ffmpeg -i input.avi -c:v libx264 -crf 18 -c:a aac -b:a 192k output.mp4

# Balanced quality
ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mp4

# Smaller file (lower quality)
ffmpeg -i input.avi -c:v libx264 -crf 28 -c:a aac -b:a 96k output.mp4

Two-Pass Encoding — Best for Target File Size

When you need a specific file size, use two-pass encoding:

# Pass 1: analyze
ffmpeg -i input.avi -c:v libx264 -b:v 2M -pass 1 -an -f null /dev/null

# Pass 2: encode
ffmpeg -i input.avi -c:v libx264 -b:v 2M -pass 2 -c:a aac -b:a 128k output.mp4

Presets — Speed vs Compression

Slower presets produce smaller files at the same quality:

# Fast encoding, larger file
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4

# Slow encoding, smaller file
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset slow -c:a aac output.mp4

Converting with Resolution Changes

Combine format conversion with scaling:

# Convert to 720p MP4
ffmpeg -i input.mkv -c:v libx264 -crf 23 -vf "scale=-2:720" -c:a aac -b:a 128k output.mp4

# Convert to 1080p WebM
ffmpeg -i input.avi -c:v libvpx-vp9 -crf 30 -b:v 0 -vf "scale=-2:1080" -c:a libopus output.webm

Batch Conversion Scripts

Convert All Files in a Directory

# Convert all AVI files to MP4
for f in *.avi; do
  ffmpeg -i "$f" -c:v libx264 -crf 23 -c:a aac -b:a 128k "${f%.avi}.mp4"
done

# Convert all MKV files to MP4 (stream copy if possible)
for f in *.mkv; do
  ffmpeg -i "$f" -c copy "${f%.mkv}.mp4"
done

Convert with Custom Quality per Format

#!/bin/bash
# Batch convert to multiple formats
INPUT="input.mp4"

# Web-optimized MP4
ffmpeg -i "$INPUT" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart web.mp4

# High-quality MKV archive
ffmpeg -i "$INPUT" -c:v libx265 -crf 22 -preset slow -c:a flac archive.mkv

# WebM for open-source hosting
ffmpeg -i "$INPUT" -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k web.webm

Recursive Conversion

# Find and convert all AVI files recursively
find . -name "*.avi" -exec sh -c '
  ffmpeg -i "$1" -c:v libx264 -crf 23 -c:a aac "${1%.avi}.mp4"
' _ {} \;

Web Optimization — faststart

For MP4 files served on the web, always add -movflags +faststart. This moves metadata to the beginning of the file so playback can start before the full download completes:

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

Common Conversion Recipes

Here are ready-to-use commands for the most frequent conversions:

# MOV (iPhone) to MP4 for sharing
ffmpeg -i input.mov -c:v libx264 -crf 23 -c:a aac -b:a 128k -movflags +faststart output.mp4

# AVI to MP4 (re-encode)
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

# MP4 to WebM for web embedding
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm

# MKV to MP4 (lossless remux)
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4

# Any format to GIF (short clip)
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1" -t 5 output.gif

# MP4 to HLS for streaming
ffmpeg -i input.mp4 -c copy -hls_time 10 -hls_list_size 0 output.m3u8

Troubleshooting

"Discarding packet" warnings — The source container has compatibility issues. Add -err_detect ignore_err to skip corrupt packets.

"Non-monotonous DTS" errors — Timestamp issues in the source. Fix with:

ffmpeg -i input.mkv -fflags +genpts -c:v libx264 -crf 23 -c:a aac output.mp4

Codec not supported in container — You're trying to put an incompatible codec in a container (e.g., VP9 in AVI). Either change the container or re-encode with a compatible codec.

Output file is larger than input — This happens when converting from a more efficient codec to a less efficient one, or when the source was heavily compressed. Try lowering the CRF value or using a more efficient codec.

Cloud Alternative with FFHub

Converting video formats locally works fine for one-off tasks, but batch conversions can tie up your machine for hours. FFHub lets you run FFmpeg commands in the cloud via API — same FFmpeg syntax, no local CPU usage.

This is especially useful when you need to convert large batches of files, integrate format conversion into a web application, or process videos on machines without FFmpeg installed.

Summary

  • Use stream copy (-c copy) when codecs are compatible — it's instant
  • Choose H.264 + AAC in MP4 for maximum compatibility
  • Choose VP9 + Opus in WebM for web-focused, royalty-free delivery
  • Use CRF mode for quality-focused encoding
  • Add -movflags +faststart for web-served MP4 files
  • Use batch scripts to convert entire directories at once
  • How to Compress Video with FFmpeg - Reduce file size with CRF, presets, and resolution scaling
  • How to Extract Audio from Video with FFmpeg - Pull audio tracks from any video format
  • FFmpeg Video Compression Best Practices - Advanced encoding strategies for optimal quality and size
FFHub

FFHub