Encoding and Settings
Optimised daily command
Good for archiving, streaming (non-live), and wide device playback:
ffmpeg -i input.mp4 \
-vf "scale=w=1080:h=1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1:1" \
-crf 18 -preset veryslow -threads 0 -tune fastdecode -movflags +faststart \
output.mp4
| Flag | Purpose |
|---|---|
-crf 18 |
High quality constant rate factor (see H264 section) |
-preset veryslow |
Slower encoding, better compression for same quality. Use ultrafast when speed matters more than size |
-threads 0 |
Let ffmpeg optimise thread count (default, usually best to omit) |
-tune fastdecode |
Output requires less compute to decode - good for edge devices. Use zerolatency for fast encoding and low-latency streaming |
-movflags +faststart |
Move metadata to front for faster web playback |
H264 (libx264)
Default for MP4 output. Always specify -c:v libx264 explicitly.
CRF (Constant Rate Factor)
Default bitrate control for libx264 and libx265. Best for quality-focused encoding where file size is secondary.
- Range: 0-51 (0 = lossless 8-bit, for 10-bit use
-qp 0) - Default: 23
- Recommended: 17-28 (17-18 visually lossless)
- Exponential scale: CRF +6 = roughly half bitrate/file size; -6 = roughly double
- Common high-quality:
-crf 18; better quality:-crf 10
CRF allows the encoder to attempt a certain output quality for the whole file. It adjusts the quantizer for each frame to maintain requested quality. The downside is you cannot target a specific file size or bitrate, so this is not recommended for streaming.
format=yuv420p
H264 YUV planar colour format for broad playback compatibility:
ffmpeg -i input.mp4 -vf format=yuv420p -c:v libx264 output.mp4
Required for QuickTime and most players. Use when converting images to video or experiencing playback issues. Alias: -pix_fmt yuv420p.
-movflags +faststart
Moves metadata to front of container. Supported in MP4, M4A, MOV.
ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
Works with both libx264 and libx265:
ffmpeg -i input.mp4 -c:v libx265 -c:a copy -movflags +faststart output.mp4
Verify with ffprobe:
ffprobe -v trace -i output.mp4
Look for type:'moov' near the beginning. YouTube recommends faststart for uploads.
H265 (libx265)
Similar controls to H264. Use -vtag hvc1 for Apple compatibility (iOS AirDrop):
ffmpeg -i input.mp4 -c:v libx265 -vtag hvc1 -c:a copy output.mp4
VP9 (libvpx-vp9)
Open, royalty-free format owned by Google. Used by YouTube. Saves 20-50% bitrate vs libx264 at same visual quality.
Constant quality encoding
Must use -crf with -b:v 0 (setting -b:v higher or omitting it invokes Constrained Quality mode instead):
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 15 -b:v 0 -c:a libopus output.webm
- CRF range: 0-63 (lower = better)
- Recommended: 15-35, with 31 for 1080p
- Default audio encoder: libopus (re-encodes AAC to Opus)
- CPU/speed/threading controls
1-pass vs 2-pass encoding
VP9, libx264, and libx265 all support both modes.
| Use case | Recommended mode |
|---|---|
| Archival | CRF (single pass) |
| Streaming (non-live) | Two-pass CRF or ABR with VBV-constrained bitrate |
| Live streaming | One-pass CRF or ABR with VBV, or CBR |
| Encoding for devices | Two-pass ABR |
Two-pass CRF in VP9 (reference): first pass calculates optimal encoding parameters, second pass achieves better compression for web-hosted video.
Codec flags quick reference
| Flag | Purpose |
|---|---|
-c:v |
Video encoder |
-c:a |
Audio encoder |
-c:a aac |
AAC audio (default, good practice to specify) |
-c:a libmp3lame |
MP3 encoding |
-an |
Disable audio output |
-c copy (stream copy) - detailed
Re-muxes without re-encoding - dramatically faster than transcoding.
| Flag | Purpose |
|---|---|
-c copy |
Copy all streams |
-c:v copy |
Copy video only |
-c:a copy (or -acodec copy) |
Copy audio only |
Remuxing rewraps streams into a new container without altering them. Transcoding changes compression and quality. MP4 can be remuxed to MKV and MOV (all H264 containers).
When NOT to use -c copy
- Applying video filters (scale, overlay, subtitles, trim, fade)
- Mixing or modifying audio (amix, atempo, volume)
- Frame-accurate trimming (can only cut at keyframes)
- Burning subtitles
- Transcoding between codecs
- Compressing media
Input/output seeking - detailed
Input seeking (-ss before -i)
ffmpeg -ss 00:00:03 -i input.mp4 -frames:v 1 output.jpg
Parses by keyframe - very fast but less accurate. In H264 with 25fps, keyframes typically every ~10 seconds. Resets timestamps to trimmed version - adjust filters accordingly.
Output seeking (-ss after -i)
ffmpeg -i input.mp4 -ss 00:00:03 -frames:v 1 output.jpg
Decodes and discards until timestamp - frame-accurate but slower.
The trimming problem
Use output seeking WITHOUT -c:v copy for reliable trimming:
Input seeking +
-c:v copybug: FFmpeg bug report, Stack Overflow discussionOutput seeking +
-c:v copyblack frames: Copies frames that depend on a missing keyframe. Explanation
From ffmpeg docs:
When used as an input option, seeks in this input file to position. In most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.
Re-encoded output may have different bitrate - adjust as needed.
GPU acceleration - detailed
Nvidia (NVENC)
H264 via Nvidia GPU:
ffmpeg -i input.avi -c:v h264_nvenc output.mp4
H265 via Nvidia GPU:
ffmpeg -i input.avi -c:v hevc_nvenc output.mp4
Intel Quick Sync Video (QSV)
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -i input.avi -c:v h264_qsv output.mp4
AMD (VAAPI)
More complex setup and less broadly supported than Nvidia/Intel options.