Skip to main content

FFmpeg cheat sheet

Before you start

Replace the example filenames and settings with your own. Keep the original files and use a different output filename for each experiment.

Commands use Bash/Zsh syntax. Available encoders depend on your FFmpeg build.

Inspect and preview

List encoders:

ffmpeg -encoders

List pixel formats:

ffmpeg -pix_fmts

Inspect a video:

ffprobe -hide_banner "input.mp4"

Play fullscreen, repeating three times. Use -loop 0 to repeat indefinitely:

ffplay -loop 3 -fs "input.mp4"

Convert video

Convert to H.264 video with AAC audio in MP4:

ffmpeg -i "input.mp4" -c:v libx264 -crf 18 -preset medium -pix_fmt yuv420p -c:a aac -b:a 192k -movflags +faststart "converted.mp4"

For libx264, lower CRF values generally mean higher quality and larger files. CRF 18 is a useful starting point, not a lossless setting. Quality options differ between encoders.

Convert to Xvid in AVI, resizing to 640 × 480 and removing audio:

ffmpeg -i "input.mp4" -vf "scale=640:480,setsar=1" -c:v libxvid -q:v 2 -an "xvid.avi"

This can stretch sources with a different aspect ratio. Your FFmpeg build must include libxvid.

Convert to raw video

Convert to raw yuv420p without resizing or explicitly changing the frame rate:

ffmpeg -i "input.mp4" -c:v rawvideo -pix_fmt yuv420p "output.yuv"

Raw video has no header storing its dimensions, pixel format or frame rate. Record the actual output settings alongside the file or in its filename.

yuv420p is a pixel format, not a color-space name.

Preview raw video

This example assumes 640 × 480 at 30 fps. Substitute your actual dimensions and frame rate:

ffplay -f rawvideo -video_size 640x480 -framerate 30 -pixel_format yuv420p -i "output.yuv"

Convert raw video to MP4

Use the settings that describe the raw file:

ffmpeg -f rawvideo -pixel_format yuv420p -video_size 640x480 -framerate 30 -i "output.yuv" -c:v libx264 -crf 18 -pix_fmt yuv420p "from-raw.mp4"

For 8-bit yuv420p with even dimensions, each frame uses width × height × 1.5 bytes. Raw video does not contain audio.

Rotate video

Rotate 90 degrees clockwise:

ffmpeg -i "input.mp4" -vf "transpose=1" -c:v libx264 -crf 18 -c:a aac "rotated-90.mp4"

Use transpose=2 for 90 degrees counterclockwise.

Rotate 180 degrees:

ffmpeg -i "input.mp4" -vf "transpose=2,transpose=2" -c:v libx264 -crf 18 -c:a aac "rotated-180.mp4"

Crop video

Crop an 80 × 60 region with its top-left corner at (200, 100):

ffmpeg -i "input.mp4" -vf "crop=80:60:200:100" -c:v libx264 -crf 18 -c:a aac "cropped.mp4"

The source must be large enough to contain the requested region.

Resize video

Resize to exactly 640 × 480:

ffmpeg -i "input.mp4" -vf "scale=640:480,setsar=1" -c:v libx264 -crf 18 -c:a aac "resized.mp4"

Preserve aspect ratio while resizing to width 640. The -2 chooses an even height:

ffmpeg -i "input.mp4" -vf "scale=640:-2" -c:v libx264 -crf 18 -c:a aac "resized-proportional.mp4"

Fill a 640 × 640 square while preserving aspect ratio, then crop the excess from the center:

ffmpeg -i "input.mp4" -vf "scale=640:640:force_original_aspect_ratio=increase,crop=640:640,setsar=1" -c:v libx264 -crf 18 -pix_fmt yuv420p -c:a aac "square.mp4"

Substitute your desired even width and height in both the scale and crop expressions.

Trim video

Fast cut starting at one second and lasting two seconds:

ffmpeg -ss 00:00:01 -i "input.mp4" -t 2 -c copy "cut-fast.mp4"

Stream copying avoids re-encoding, but cuts depend on keyframes and may not start exactly where requested.

For a more precise cut, re-encode:

ffmpeg -ss 00:00:01 -i "input.mp4" -t 2 -c:v libx264 -crf 18 -c:a aac "cut-precise.mp4"

Split video

Split into the first two seconds and everything after that:

ffmpeg -i "input.mp4" -t 2 -c copy "cut-1.mp4" -ss 2 -c copy "cut-2.mp4"

For clean joins at an arbitrary split point, re-encode both parts.

Concatenate matching clips

Create a file named file-list.txt in the same folder as the clips:

file 'clip-1.mp4'
file 'clip-2.mp4'

Join them without re-encoding:

ffmpeg -f concat -i "file-list.txt" -c copy "joined.mp4"

The clips need compatible streams, including codecs, timing and video/audio parameters. Paths are relative to the list file.

Matching AAC clips produced an audio timestamp warning in the local test. Inspect the join; use a concat filter with re-encoding when seamless timing is required.

Change video speed

Eight times faster, removing audio:

ffmpeg -i "input.mp4" -vf "setpts=0.125*(PTS-STARTPTS)" -an -c:v libx264 -crf 18 "eight-times-faster.mp4"

Four times slower, removing audio:

ffmpeg -i "input.mp4" -vf "setpts=4*(PTS-STARTPTS)" -an -c:v libx264 -crf 18 "four-times-slower.mp4"

The multiplier changes duration. A multiplier of 0.125 means one eighth of the duration, or eight times the speed.

Slow motion duplicates existing frames unless interpolation is added. Output durations can differ slightly from the nominal multiplier because of frame timing.

Double the speed of both video and audio:

ffmpeg -i "input.mp4" -filter_complex "[0:v]setpts=0.5*(PTS-STARTPTS)[v];[0:a]atempo=2,asetpts=PTS-STARTPTS[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 18 -c:a aac "double-speed.mp4"

This command requires an audio stream.

Extract audio

Extract AAC audio without re-encoding:

ffmpeg -i "input.mp4" -vn -c:a copy "audio.m4a"

This assumes the source audio is AAC. For other codecs, select a suitable container or convert to WAV:

ffmpeg -i "input.mp4" -vn -c:a pcm_s16le "audio.wav"

Trim audio

Extract two seconds starting at one second:

ffmpeg -ss 00:00:01 -i "audio.wav" -t 2 -c:a pcm_s16le "audio-trimmed.wav"

Change audio volume

Halve the amplitude, approximately a 6 dB reduction:

ffmpeg -i "audio.wav" -af "volume=0.5" "audio-quieter.wav"

Change audio tempo

Double the tempo while approximately preserving pitch:

ffmpeg -i "audio.wav" -af "atempo=2.0" "audio-faster.wav"

For a conservative four-times speedup, use atempo=2,atempo=2.

Check the supported range in your installed version:

ffmpeg -h filter=atempo

Combine video and audio

Use video from the first input and audio from the second. End at the shorter input:

ffmpeg -i "input.mp4" -i "audio.wav" -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -b:a 192k -shortest "video-with-audio.mp4"

Explicit mapping prevents FFmpeg from choosing the original video's audio.

Remove audio

Copy the video without re-encoding and omit audio:

ffmpeg -i "input.mp4" -map 0:v:0 -c:v copy -an "muted.mp4"

Create video from a still image

Create a five-second silent video:

ffmpeg -loop 1 -framerate 30 -i "image.png" -t 5 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -crf 18 -pix_fmt yuv420p "still-video.mp4"

The scale expression ensures even dimensions for yuv420p.

Combine a still image and audio

Create a video showing the image for the duration of the audio:

ffmpeg -loop 1 -framerate 30 -i "image.png" -i "audio.wav" -map 0:v:0 -map 1:a:0 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -tune stillimage -pix_fmt yuv420p -c:a aac -b:a 192k -shortest "cover-video.mp4"

This creates a video, rather than embedding cover art into an audio-only file.

Extract a single frame

Save one frame at one second, resized to width 640:

ffmpeg -ss 00:00:01 -i "input.mp4" -vf "scale=640:-2" -frames:v 1 -update 1 "image.png"

Extract frames at intervals

Create output folders:

mkdir -p frames sampled keyframes bmps

One image per second:

ffmpeg -i "input.mp4" -vf "fps=1" "frames/frame-%04d.png"

Three images per second:

ffmpeg -i "input.mp4" -vf "fps=3" "sampled/three-per-second-%05d.png"

One image every four seconds:

ffmpeg -i "input.mp4" -vf "fps=1/4" "sampled/every-four-seconds-%04d.png"

Every fifteenth decoded frame, starting with frame zero:

ffmpeg -i "input.mp4" -vf "select='not(mod(n,15))'" -fps_mode vfr "sampled/every-fifteenth-%04d.png"

Selecting every fifteenth frame depends on the source frame rate. Use fps when you want to sample by time.

Extract I frames

ffmpeg -i "input.mp4" -vf "select='eq(pict_type,I)'" -fps_mode vfr "keyframes/frame-%04d.png"

These are I-pictures. Depending on the codec, an I-picture is not necessarily an independently seekable keyframe.

Extract all frames as BMP

Export every decoded frame without inserting or dropping frames:

ffmpeg -i "input.mp4" -fps_mode passthrough "bmps/%04d.bmp"

Count decoded frames

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 "input.mp4"

Build video from an image sequence

Encode bmps/0001.bmp, 0002.bmp and so on at 30 fps:

ffmpeg -framerate 30 -start_number 1 -i "bmps/%04d.bmp" -c:v libx264 -crf 18 -preset fast -pix_fmt yuv420p -movflags +faststart "sequence.mp4"

Choose the intended playback rate explicitly. Numbered files do not retain the source timestamps. Preserving variable-frame-rate timing requires separate timing information.

Create a slideshow

Use img001.png, img002.png and so on, showing each image for five seconds:

ffmpeg -framerate 1/5 -start_number 1 -i "img%03d.png" -vf "fps=30,scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -crf 18 -pix_fmt yuv420p "slideshow.mp4"

Use identically sized images. Input -framerate 1/5 sets five seconds per image; fps=30 produces regular 30 fps output.

Control I P and B frames

Encode H.264 with every frame an I-frame:

ffmpeg -i "input.mp4" -c:v libx264 -crf 18 -g 1 -bf 0 -an "all-intra.mp4"

Use a fixed 60-frame keyframe interval with no B-frames:

ffmpeg -i "input.mp4" -c:v libx264 -crf 18 -g 60 -keyint_min 60 -sc_threshold 0 -bf 0 -an "fixed-gop.mp4"

For a short H.264 experiment with one initial I-frame and no scene-cut I-frames:

ffmpeg -i "input.mp4" -c:v libx264 -crf 17 -x264-params "keyint=999999:min-keyint=999999:scenecut=0" -bf 0 -an "long-gop.mp4"

The clip must be shorter than the keyframe interval. Encoder limits vary; a large -g is not a codec-independent guarantee of one I-frame.

Inspect decoded frame types:

ffprobe -v error -select_streams v:0 -show_entries frame=pict_type -of csv=p=0 "long-gop.mp4"

Create an animated GIF

Create a three-second GIF at 12 fps and width 640, using a generated palette:

ffmpeg -i "input.mp4" -t 3 -filter_complex "[0:v]fps=12,scale=640:-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse" -an -loop 0 "animation.gif"

GIF timing uses hundredths of a second, so some requested frame rates are approximated.

Add subtitles

Add an SRT file as a selectable subtitle track in MKV:

ffmpeg -i "input.mp4" -i "subtitles.srt" -map 0:v:0 -map '0:a?' -map 1:s:0 -c copy "subtitled.mkv"

For MP4, convert the subtitles to mov_text:

ffmpeg -i "input.mp4" -i "subtitles.srt" -map 0:v:0 -map '0:a?' -map 1:s:0 -c:v copy -c:a aac -c:s mov_text "subtitled.mp4"

These commands add selectable subtitles rather than burning text into the picture.

Prepare video for datamoshing

Create a silent MPEG-4 Part 2 AVI with a long GOP and no B-frames:

ffmpeg -i "input.mp4" -vf "scale=640:480,setsar=1,fps=24" -c:v mpeg4 -q:v 2 -g 999 -bf 0 -pix_fmt yuv420p -an "mosh-source.avi"

This normalizes to 640 × 480 at 24 fps and may stretch other aspect ratios. Prepare all clips using the same settings.

Inspect the frame types. The tested MPEG-4 encoder clamps large GOP requests to 600 and can still introduce I-frames.