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.
No comments to display
No comments to display