---
name: ffmpeg
description: Process audio and video files using ffmpeg/ffprobe. Use when the user wants to convert, transcode, trim, merge, extract, resize, compress, or analyze multimedia files.
---

# FFmpeg

CLI reference for FFmpeg v8.x — a complete, cross-platform solution for recording, converting, and streaming audio and video.

Official docs: https://www.ffmpeg.org/documentation.html

## Tools

| Tool | Purpose |
|------|---------|
| `ffmpeg` | Transcode, convert, filter, mux/demux multimedia |
| `ffprobe` | Analyze and inspect multimedia streams |
| `ffplay` | Play multimedia files (interactive) |

---

## ffmpeg

### Synopsis

```
ffmpeg [global_options] {[input_options] -i input_url} ... {[output_options] output_url} ...
```

Options before `-i` apply to the input; options before the output URL apply to the output.

### Global Options

| Flag | Description |
|------|-------------|
| `-y` | Overwrite output files without asking |
| `-n` | Do not overwrite; exit if output exists |
| `-hide_banner` | Suppress copyright/build info banner |
| `-loglevel level` | Set log level: `quiet`, `error`, `warning`, `info` (default), `verbose`, `debug` |
| `-stats` | Print encoding progress/statistics |
| `-progress url` | Send machine-readable progress to url |
| `-report` | Dump full command line and log to a file |
| `-filter_threads n` | Number of threads for filter processing |

### Input/Output Options

| Flag | Description |
|------|-------------|
| `-i url` | Input file URL |
| `-f fmt` | Force input or output format |
| `-c[:stream] codec` | Select encoder/decoder; use `copy` for stream copying |
| `-t duration` | Limit duration (as input: read limit; as output: write limit) |
| `-to position` | Stop at position (timestamp) |
| `-ss position` | Seek to position (before `-i`: fast input seek; after: output seek) |
| `-sseof position` | Seek relative to end of file |
| `-itsoffset offset` | Set input time offset |
| `-itsscale scale` | Rescale input timestamps |
| `-metadata key=value` | Set metadata key/value pair |
| `-disposition value` | Set stream disposition flags |
| `-target type` | Specify target type: `vcd`, `svcd`, `dvd`, `dv`, `dv50` |
| `-stream_loop n` | Loop input stream n times (-1 = infinite) |
| `-frames[:stream] n` | Stop after n frames |
| `-fs limit` | Set file size limit in bytes |
| `-timestamp date` | Set recording timestamp |

### Video Options

| Flag | Description |
|------|-------------|
| `-vn` | Disable video |
| `-vcodec codec` | Set video codec (alias for `-c:v`) |
| `-r fps` | Set frame rate |
| `-fpsmax fps` | Set maximum frame rate |
| `-s WxH` | Set frame size |
| `-aspect ratio` | Set display aspect ratio (e.g. `16:9`) |
| `-pix_fmt format` | Set pixel format |
| `-vf filtergraph` | Apply video filter graph (alias for `-filter:v`) |
| `-pass n` | Two-pass encoding pass (1 or 2) |
| `-passlogfile prefix` | Two-pass log file prefix |
| `-vframes n` | Set number of video frames to output |
| `-autorotate` | Auto-rotate based on metadata (default on) |
| `-display_rotation angle` | Set video rotation metadata |
| `-display_hflip` | Horizontal flip metadata |
| `-display_vflip` | Vertical flip metadata |
| `-force_key_frames expr` | Force keyframes at specified times/expression |
| `-copyinkf` | Copy non-key frames at the beginning during stream copy |

### Audio Options

| Flag | Description |
|------|-------------|
| `-an` | Disable audio |
| `-acodec codec` | Set audio codec (alias for `-c:a`) |
| `-ar freq` | Set audio sample rate (Hz) |
| `-ac channels` | Set number of audio channels |
| `-af filtergraph` | Apply audio filter graph (alias for `-filter:a`) |
| `-sample_fmt fmt` | Set audio sample format |
| `-channel_layout layout` | Set audio channel layout |
| `-aq q` | Set audio quality (codec-specific VBR) |
| `-aframes n` | Set number of audio frames to output |

### Subtitle Options

| Flag | Description |
|------|-------------|
| `-sn` | Disable subtitles |
| `-scodec codec` | Set subtitle codec (alias for `-c:s`) |
| `-fix_sub_duration` | Fix subtitle durations to avoid overlap |

### Stream Selection

| Flag | Description |
|------|-------------|
| `-map input:stream` | Manually select streams for output |
| `-dn` | Disable data streams |

Stream specifiers: `v` (video), `V` (video, no images), `a` (audio), `s` (subtitle), `d` (data). Index with `:N` (e.g. `a:0` = first audio).

### Hardware Acceleration

| Flag | Description |
|------|-------------|
| `-hwaccel method` | HW accel method: `cuda`, `vaapi`, `qsv`, `vulkan`, `auto` |
| `-hwaccel_device device` | Select HW device |
| `-init_hw_device type=name` | Initialize HW device |

---

## ffprobe

### Synopsis

```
ffprobe [options] input_url
```

### Main Options

| Flag | Description |
|------|-------------|
| `-show_format` | Show container format info |
| `-show_streams` | Show per-stream info |
| `-show_packets` | Show per-packet info |
| `-show_frames` | Show per-frame info |
| `-show_chapters` | Show chapter info |
| `-show_programs` | Show program info |
| `-show_entries section=key1,key2` | Show only specific fields |
| `-show_error` | Show probe errors |
| `-select_streams specifier` | Filter to specific streams (e.g. `v:0`, `a`) |
| `-count_frames` | Count frames per stream |
| `-count_packets` | Count packets per stream |
| `-read_intervals intervals` | Analyze specific time ranges |

### Output Formats

Set with `-output_format` (or `-of`, `-print_format`):

| Format | Description |
|--------|-------------|
| `default` | `[SECTION] key=value [/SECTION]` |
| `json` | JSON output (most useful for parsing) |
| `xml` | XML output |
| `csv` | Comma-separated values |
| `flat` | Flat `key=value` per line |
| `ini` | INI-style sections |

### Display Options

| Flag | Description |
|------|-------------|
| `-pretty` | Human-readable units and time formatting |
| `-unit` | Show value units |
| `-sexagesimal` | Format times as HH:MM:SS.us |
| `-hide_banner` | Suppress copyright/build info |
| `-o output_url` | Write output to file instead of stdout |

---

## Common Codecs

### Video Encoders

#### libx264 (H.264)

| Option | Description |
|--------|-------------|
| `-preset` | Speed/quality: `ultrafast`, `superfast`, `veryfast`, `faster`, `fast`, `medium` (default), `slow`, `slower`, `veryslow` |
| `-crf` | Constant quality: 0 (lossless) to 51 (worst). 18-23 is typical |
| `-profile:v` | `baseline`, `main`, `high` |
| `-tune` | `film`, `animation`, `grain`, `stillimage`, `fastdecode`, `zerolatency` |
| `-b:v` | Target bitrate (e.g. `2M`) |

#### libx265 (H.265/HEVC)

| Option | Description |
|--------|-------------|
| `-preset` | Same presets as x264 |
| `-crf` | 0-51, default 28. Similar quality to x264 at lower bitrate |
| `-profile:v` | `main`, `main10`, `main12` |
| `-b:v` | Target bitrate |

#### libvpx-vp9 (VP9)

| Option | Description |
|--------|-------------|
| `-crf` | 0-63. 31 is a good default |
| `-b:v` | Target bitrate (set to `0` for pure CRF mode) |
| `-cpu-used` | Speed: 0 (slowest/best) to 8 (fastest) |
| `-deadline` | `best`, `good` (default), `realtime` |
| `-row-mt 1` | Enable row-based multithreading |

#### libsvtav1 (SVT-AV1)

| Option | Description |
|--------|-------------|
| `-crf` | 0-63. 30 is a good default |
| `-preset` | 0 (slowest/best) to 13 (fastest). 8 is a good default |
| `-b:v` | Target bitrate |

#### libaom-av1 (AOM AV1)

| Option | Description |
|--------|-------------|
| `-crf` | 0-63 |
| `-cpu-used` | 0 (best) to 8 (fastest) |
| `-b:v` | Target bitrate (set to `0` for pure CRF mode) |
| `-tiles` | Tile columns x rows for parallelism |

### Audio Encoders

#### aac (Native AAC)

| Option | Description |
|--------|-------------|
| `-b:a` | Bitrate: `128k`, `192k`, `256k` |
| `-profile:a` | `aac_low` (default), `aac_he`, `aac_he_v2` |

#### libmp3lame (MP3)

| Option | Description |
|--------|-------------|
| `-b:a` | CBR bitrate: `128k`, `192k`, `320k` |
| `-q:a` | VBR quality: 0 (best) to 9 (worst). 2 is a good default |

#### libopus (Opus)

| Option | Description |
|--------|-------------|
| `-b:a` | Bitrate: `64k` to `256k`. 128k is a good default |
| `-vbr` | `on` (default), `off`, `constrained` |
| `-application` | `audio` (default), `voip`, `lowdelay` |

#### libvorbis (Vorbis)

| Option | Description |
|--------|-------------|
| `-q:a` | VBR quality: -1 to 10. 5 is a good default |
| `-b:a` | ABR bitrate |

#### flac (FLAC)

| Option | Description |
|--------|-------------|
| `-compression_level` | 0 (fast) to 12 (best). 5 is default |

---

## Common Container Formats

| Format | Extensions | Notes |
|--------|-----------|-------|
| `mp4` | .mp4, .m4a, .m4v | Use `-movflags +faststart` for web streaming |
| `matroska` | .mkv | Supports virtually all codecs |
| `webm` | .webm | VP8/VP9/AV1 + Vorbis/Opus for web |
| `avi` | .avi | Legacy; limited codec support |
| `mpegts` | .ts | Broadcast transport stream |
| `ogg` | .ogg, .ogv | Vorbis/Opus/Theora container |
| `wav` | .wav | Uncompressed PCM audio |
| `flac` | .flac | Lossless audio |
| `mp3` | .mp3 | MPEG audio layer 3 |
| `hls` | .m3u8 | HTTP Live Streaming |
| `dash` | .mpd | DASH adaptive streaming |
| `gif` | .gif | Animated GIF |
| `image2` | various | Image sequence input/output |
| `concat` | text file | Concatenation demuxer (file list) |
| `null` | — | Discard output (benchmarking) |

---

## Common Video Filters (`-vf`)

| Filter | Description | Example |
|--------|-------------|---------|
| `scale=W:H` | Resize video. Use `-1` or `-2` to auto-calculate | `scale=1280:720`, `scale=-2:480` |
| `crop=W:H:X:Y` | Crop to WxH starting at X,Y | `crop=640:480:100:50` |
| `pad=W:H:X:Y:color` | Pad video with borders | `pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black` |
| `overlay=X:Y` | Composite second input over first | `overlay=10:10` |
| `transpose=N` | Rotate: 0=90ccw+vflip, 1=90cw, 2=90ccw, 3=90cw+vflip | `transpose=1` |
| `hflip` / `vflip` | Horizontal / vertical flip | `hflip` |
| `rotate=angle` | Rotate by arbitrary angle (radians) | `rotate=PI/4` |
| `fps=N` | Change frame rate | `fps=30` |
| `setpts=expr` | Modify presentation timestamps | `setpts=0.5*PTS` (2x speed) |
| `trim=start:end` | Extract time range | `trim=start=10:end=20` |
| `drawtext=opts` | Overlay text | `drawtext=text='Hello':fontsize=24:x=10:y=10` |
| `fade=t=type:st=S:d=D` | Fade in/out | `fade=t=in:st=0:d=2` |
| `eq=opts` | Adjust brightness/contrast/saturation | `eq=brightness=0.1:contrast=1.2` |
| `format=pix_fmt` | Convert pixel format | `format=yuv420p` |
| `concat=n:v:a` | Concatenate segments | `concat=n=2:v=1:a=1` |
| `split` / `select` | Duplicate / select frames | `select='eq(pict_type,I)'` |
| `deinterlace` / `yadif` | Remove interlacing | `yadif=1` |
| `boxblur=R` | Apply box blur | `boxblur=5:1` |
| `subtitles=file` | Burn in subtitles from file | `subtitles=subs.srt` |
| `palettegen` / `paletteuse` | Generate/apply palette for GIF | Used in two-pass GIF creation |
| `colorchannelmixer` | Mix color channels | `colorchannelmixer=.3:.4:.3:0:.3:.4:.3:0:.3:.4:.3` (grayscale) |

## Common Audio Filters (`-af`)

| Filter | Description | Example |
|--------|-------------|---------|
| `volume=V` | Adjust volume | `volume=1.5`, `volume=-3dB` |
| `loudnorm` | EBU R128 loudness normalization | `loudnorm=I=-16:TP=-1.5:LRA=11` |
| `atempo=T` | Change tempo (0.5-100.0) | `atempo=2.0` (2x speed) |
| `aresample=rate` | Resample audio | `aresample=44100` |
| `amerge` | Merge audio channels | `amerge=inputs=2` |
| `afade=t=type:st=S:d=D` | Audio fade in/out | `afade=t=in:st=0:d=3` |
| `highpass=f=freq` | High-pass filter | `highpass=f=200` |
| `lowpass=f=freq` | Low-pass filter | `lowpass=f=3000` |
| `equalizer=f:t:w:g` | Parametric EQ | `equalizer=f=1000:t=q:w=1:g=5` |
| `acompressor` | Dynamic range compression | `acompressor=threshold=-20dB:ratio=4` |
| `silenceremove` | Remove silence | `silenceremove=1:0:-50dB` |
| `silencedetect` | Detect silence | `silencedetect=n=-30dB:d=2` |
| `adelay=delays` | Delay audio channels | `adelay=1000\|1000` (ms) |
| `aecho=id:ig:delays:decays` | Add echo effect | `aecho=0.8:0.88:60:0.4` |
| `pan=layout:gains` | Remix channels | `pan=mono\|c0=0.5*c0+0.5*c1` |

---

## Common Recipes

### Convert format

```bash
ffmpeg -i input.mkv output.mp4
```

### Transcode with CRF quality

```bash
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -c:a aac -b:a 192k output.mp4
```

### Extract audio

```bash
ffmpeg -i video.mp4 -vn -c:a copy audio.m4a
```

### Extract video (no audio)

```bash
ffmpeg -i input.mp4 -an -c:v copy output.mp4
```

### Trim / cut

```bash
ffmpeg -ss 00:01:30 -to 00:03:00 -i input.mp4 -c copy output.mp4
```

### Resize video

```bash
ffmpeg -i input.mp4 -vf "scale=1280:720" -c:a copy output.mp4
```

### Compress video (lower quality)

```bash
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k output.mp4
```

### Two-pass encoding

```bash
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 1 -f null /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 2M -pass 2 output.mp4
```

### Concatenate files (concat demuxer)

```bash
# files.txt contains:
# file 'part1.mp4'
# file 'part2.mp4'
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4
```

### Add subtitles (burn-in)

```bash
ffmpeg -i input.mp4 -vf "subtitles=subs.srt" output.mp4
```

### Create GIF

```bash
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif
```

### Add watermark / overlay

```bash
ffmpeg -i video.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4
```

### Change speed (video + audio)

```bash
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" output.mp4
```

### Extract frames as images

```bash
ffmpeg -i input.mp4 -vf "fps=1" frame_%04d.png
```

### Merge audio and video

```bash
ffmpeg -i video.mp4 -i audio.m4a -c:v copy -c:a copy -shortest output.mp4
```

### Normalize audio loudness

```bash
ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" -c:v copy output.mp4
```

### Convert to web-optimized MP4

```bash
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart output.mp4
```

### Probe file info (JSON)

```bash
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
```

### Get duration only

```bash
ffprobe -v quiet -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
```

### Get resolution only

```bash
ffprobe -v quiet -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4
```

---

## Source

- Website: https://ffmpeg.org/
- Documentation: https://www.ffmpeg.org/documentation.html
- CLI reference: https://www.ffmpeg.org/ffmpeg.html
- Filters reference: https://www.ffmpeg.org/ffmpeg-filters.html
- Codecs reference: https://www.ffmpeg.org/ffmpeg-codecs.html
- Formats reference: https://www.ffmpeg.org/ffmpeg-formats.html
- Wiki: https://trac.ffmpeg.org/wiki
