Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
FFmpeg cheat sheet

FFmpeg cheat sheet

A list of useful commands for the ffmpeg command line tool.

Download FFmpeg: https://www.ffmpeg.org/download.html

Full documentation: https://www.ffmpeg.org/ffmpeg.html

Basic conversion

ffmpeg -i in.mp4 out.avi

Remux an MKV file into MP4

ffmpeg -i in.mkv -c:v copy -c:a copy out.mp4

High-quality encoding

Use the crf (Constant Rate Factor) parameter to control the output quality. The lower crf, the higher the quality (range: 0-51). The default value is 23, and visually lossless compression corresponds to -crf 18. Use the preset parameter to control the speed of the compression process. Additional info: https://trac.ffmpeg.org/wiki/Encode/H.264

ffmpeg -i in.mp4 -preset slower -crf 18 out.mp4

Trimming

Without re-encoding:

ffmpeg -ss [start] -i in.mp4 -t [duration] -c copy out.mp4
  • -ss specifies the start time, e.g. 00:01:23.000 or 83 (in seconds)
  • -t specifies the duration of the clip (same format).
  • Recent ffmpeg also has a flag to supply the end time with -to.
  • -c copy copies the first video, audio, and subtitle bitstream from the input to the output file without re-encoding them. This won't harm the quality and make the command run within seconds.

With re-encoding:

If you leave out the -c copy option, ffmpeg will automatically re-encode the output video and audio according to the format you chose. For high quality video and audio, read the x264 Encoding Guide and the AAC Encoding Guide, respectively.

For example:

ffmpeg -ss [start] -i in.mp4 -t [duration] -c:v libx264 -c:a aac -strict experimental -b:a 128k out.mp4

Mux video and audio from another video

To copy the video from in0.mp4 and audio from in1.mp4:

ffmpeg -i in0.mp4 -i in1.mp4 -c copy -map 0:0 -map 1:1 -shortest out.mp4

Concat demuxer

First, make a text file.

file 'in1.mp4'
file 'in2.mp4'
file 'in3.mp4'
file 'in4.mp4'

Then, run ffmpeg:

ffmpeg -f concat -i list.txt -c copy out.mp4

Delay audio/video

Delay video by 3.84 seconds:

ffmpeg -i in.mp4 -itsoffset 3.84 -i in.mp4 -map 1:v -map 0:a -vcodec copy -acodec copy out.mp4

Delay audio by 3.84 seconds:

ffmpeg -i in.mp4 -itsoffset 3.84 -i in.mp4 -map 0:v -map 1:a -vcodec copy -acodec copy out.mp4

Burn subtitles

Use the libass library (make sure your ffmpeg install has the library in the configuration --enable-libass).

First convert the subtitles to .ass format:

ffmpeg -i sub.srt sub.ass

Then add them using a video filter:

ffmpeg -i in.mp4 -vf ass=sub.ass out.mp4

Extract the frames from a video

To extract all frames from between 1 and 5 seconds, and also between 11 and 15 seconds:

ffmpeg -i in.mp4 -vf select='between(t,1,5)+between(t,11,15)' -vsync 0 out%d.png

To extract one frame per second only:

ffmpeg -i in.mp4 -fps=1 -vsync 0 out%d.png

Rotate a video

Rotate 90 clockwise:

ffmpeg -i in.mov -vf "transpose=1" out.mov

For the transpose parameter you can pass:

0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

Use -vf "transpose=2,transpose=2" for 180 degrees.

Download "Transport Stream" video streams

  1. Locate the playlist file, e.g. using Chrome > F12 > Network > Filter: m3u8
  2. Download and concatenate the video fragments:
ffmpeg -i "path_to_playlist.m3u8" -c copy -bsf:a aac_adtstoasc out.mp4

If you get a "Protocol 'https not on whitelist 'file,crypto'!" error, add the protocol_whitelist option:

ffmpeg -protocol_whitelist "file,http,https,tcp,tls" -i "path_to_playlist.m3u8" -c copy -bsf:a aac_adtstoasc out.mp4

Mute some of the audio

To replace the first 90 seconds of audio with silence:

ffmpeg -i in.mp4 -vcodec copy -af "volume=enable='lte(t,90)':volume=0" out.mp4

To replace all audio between 1'20" and 1'30" with silence:

ffmpeg -i in.mp4 -vcodec copy -af "volume=enable='between(t,80,90)':volume=0" out.mp4

Deinterlace

Deinterlacing using "yet another deinterlacing filter".

ffmpeg -i in.mp4 -vf yadif out.mp4

Create a video slideshow from images

Parameters: -r marks the image framerate (inverse time of each image); -vf fps=25 marks the true framerate of the output.

ffmpeg -r 1/5 -i img%03d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p out.mp4

Extract images from a video

  • Extract all frames: ffmpeg -i input.mp4 thumb%04d.jpg -hide_banner
  • Extract a frame each second: ffmpeg -i input.mp4 -vf fps=1 thumb%04d.jpg -hide_banner
  • Extract only one frame: ffmpeg -i input.mp4 -ss 00:00:10.000 -vframes 1 thumb.jpg

Metadata: Change the title

ffmpeg -i in.mp4 -map_metadata -1 -metadata title="My Title" -c:v copy -c:a copy out.mp4
@debuti
Copy link

debuti commented Oct 4, 2020

Awesome!! Many thanks

@javier-cantu
Copy link

javier-cantu commented Dec 4, 2020

OMG this is awesome!
Thank you very much!

@QidiLiu
Copy link

QidiLiu commented Dec 8, 2020

Thanks!

@SunKing2
Copy link

SunKing2 commented Dec 29, 2020

That To extract all frames from between 1 and 5 seconds, and also between 11 and 15 seconds is priceless; I've been looking for a better way, and that's it!, Thanks!
From: https://ffmpeg.org/ffmpeg-all.html#Video-Options "-r: As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps. This is not the same as the -framerate option used for some input formats like image2 or v4l2 (it used to be the same in older versions of FFmpeg). If in doubt use -framerate instead of the input option -r. "
So reading from img%03d.png uses image2 so it -framerate would be more appropriate.
From https://twitter.com/ffmpeg/status/943266612047577089?lang=en Still seeing "-strict -2" or "-strict experimental" being used unnecessarily. It is no longer needed for the FFmpeg AAC encoder unless your ffmpeg cli tool is really old, and if that's the case please update.
fps is not even an option so
ffmpeg -i in.mp4 -fps=1 -vsync 0 out%d.png
cannot work.
ffmpeg -i in.mp4 -vf "fps=1" out%04d.png
would work. I avoid the filter and even though it's not quite as accurate, I use:
ffmpeg -i in.mp4 -r 1 out%04d.png

@RojjaCebolla
Copy link

RojjaCebolla commented Feb 27, 2021

Thanks for this cheatsheet! I've used it a couple times for the simpler stuff. I had trouble just now with the command for merging a DASH_AUDIO and DASH_VIDEO file together. I tried this:
ffmpeg -i rollover0.mp4 -i rollover1.mp4 -c copy -map 0:0 -map 1:1 -shortest rollingover.mp4
and it said this:
Stream map '1:1' matches no streams. To ignore this, add a trailing '?' to the map.

I had better luck with the following from superuser!
ffmpeg -i rollover0.mp4 -i rollover1.mp4 -c:v copy -c:a aac -shortest rollingover.mp4

@steven2358
Copy link
Author

steven2358 commented Mar 1, 2021

I tried this:
ffmpeg -i rollover0.mp4 -i rollover1.mp4 -c copy -map 0:0 -map 1:1 -shortest rollingover.mp4
and it said this:
Stream map '1:1' matches no streams. To ignore this, add a trailing '?' to the map.

Usually the problem is the stream index. If rollingover1.mp4 only contains audio or video then the stream you want has index 0, not 1. In that case the following command should work:

ffmpeg -i rollover0.mp4 -i rollover1.mp4 -c copy -map 0:0 -map 1:0 -shortest rollingover.mp4

@acnhia
Copy link

acnhia commented Mar 29, 2021

Hi I am looking for commands for these 2 use cases, could you please help

  1. If a Prores has baked in Video+audio (5.1, mono, downmix) -. output a clean prores video + 5.1 audio tracks only.
  2. if a prores stereo L&R are in single track need a clean output with L and R on different tracks

@dcambria
Copy link

dcambria commented Apr 23, 2021

how to start a video from X frame, like -ss?

@paulschreiber
Copy link

paulschreiber commented Apr 25, 2021

ffmpeg -i in.mkv -c:v copy -c:a copy out.mp4

You can simplify to:

ffmpeg -i in.mkv -c copy out.mp4

@jugshaurya
Copy link

jugshaurya commented May 13, 2021

I am using

ffmpeg -f concat -safe 0 -protocol_whitelist file,http,https,tcp,tls,crypto -i ${args.fileList} -c copy ${outputFileName}

and fileList is a file in /tmp/tmp-65420oJVGcsBokCX.txt file with data

file '/home/shaurya/dev/git_repos/merge-videos/assets/course/1.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/2.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/3.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/4.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/5.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/6.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/7.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/8.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/9.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/10.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/11.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/12.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/13.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/14.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/15.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/16.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/17.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/18.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/19.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/20.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/21.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/22.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/23.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/24.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/25.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/26.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/27.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/28.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/29.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/30.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/31.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/32.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/33.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/34.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/35.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/36.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/37.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/38.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/39.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/40.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/41.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/42.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/43.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/44.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/45.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/46.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/47.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/48.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/49.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/50.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/51.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/52.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/53.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/54.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/55.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/56.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/57.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/58.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/59.mp4'
file '/home/shaurya/dev/git_repos/merge-videos/assets/course/60.mp4'

and I am trying to merge these videos into a single video, but this error is coming and only the initial 21 videos are merging, and the rest just not!
can you please look into it (Invalid data found when processing input below image) and let me know if I need to change something in the above command?

Github Repo for the same: https://github.com/jugshaurya/merge-videos

Screenshot from 2021-05-13 13-26-21

@steven2358
Thank you in advance

@steven2358
Copy link
Author

steven2358 commented May 13, 2021

@jugshaurya I don't see the error at first glance. I suggest you start with a minimal working example and extend it until you hit an error.

@jugshaurya
Copy link

jugshaurya commented May 13, 2021

I am trying to merge 60 videos in a folder. and I got the `file 'paths/to/file' for each mp4 file as pasted above.
Following your advice, I tried to merge the initial 30 videos then the initial 15 videos, and so on...(using binary search) and found out because of video 22 error was coming. If I deleted 22.mp4 all rest 59 are merging correctly. I played 22.mp4 and found that It is quitting after the 4th minute even when the video is 9 min.

So I understand that the video has some error, not the FFmpeg command. Thanks for the advice @steven2358

@MarvusMedia
Copy link

MarvusMedia commented Aug 8, 2021

Thanks so much for this - it's very useful!

I realise you probably get inundated with questions, but if you can spare a moment, could you tell me if it's possible to use a CD's 'frame' numbers (as shown by ffprobe) rather than seconds (often with recurring decimals) as start and end points when extracting individual tracks with libcdio? Thanks. :)
Marcus

@nikk-ca
Copy link

nikk-ca commented Aug 13, 2021

Super handy!

Just one quick thing, under Extract the frames from a video:
ffmpeg -i in.mp4 -fps=1 -vsync 0 out%d.png should be ffmpeg -i in.mp4 -vf fps=1 -vsync 0 out%d.png, yes?

@Ghayas-cyber
Copy link

Ghayas-cyber commented Nov 11, 2021

Hello. I have a Reference video in YUV format. I have encoded video (Encoded in MPEG4) .mp4.
Now My task is to calculate VMAF for YUV (Reference video) and MPEG4 (Distorted).
Can you please help me out. Thanks

@MarvusMedia
Copy link

MarvusMedia commented Nov 11, 2021

Super handy!

Just one quick thing, under Extract the frames from a video: ffmpeg -i in.mp4 -fps=1 -vsync 0 out%d.png should be ffmpeg -i in.mp4 -vf fps=1 -vsync 0 out%d.png, yes?

No, -fps sets the framerate. It's not a video filter.

@Ghayas-cyber
Copy link

Ghayas-cyber commented Nov 12, 2021

Hello
I have two files Reference (YUV) & distorted (YUV). I am calculating the VMAF score. When I run the command I get following output.

Option video_size not found.

@nikk-ca
Copy link

nikk-ca commented Jan 24, 2022

No, -fps sets the framerate. It's not a video filter.

@MarvusMedia

It's documented as a video filter here. Maybe you mean -r?

@MarvusMedia
Copy link

MarvusMedia commented Jan 24, 2022

It's documented as a video filter here. Maybe you mean -r?

@nikk-ca

Sorry, yes, I was thinking of -r.
-fps is indeed used to force a new framerate.

@JirkaSulkov
Copy link

JirkaSulkov commented Feb 7, 2022

Hi, I'm trying to save AAC audio from video to WAV, but it still reports an error on file size. Don't know what it can be?

D:>ffmpeg.exe -i D.mkv D.wav
Output #0, wav, to 'D.wav':
Stream #0:0(cze): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s (default)

[wav @ 00000151cf2a98c0] Filesize 10.880.815.182 invalid for wav, output file will be broken
size=10.625.796kB time=17:08:02.62 bitrate=1411.2kbits/s speed= 328x

JirkaS

@MarvusMedia
Copy link

MarvusMedia commented Feb 8, 2022

Is D.mkv really 17 hours long? If not, then it may be a malformed file (maybe an incomplete download) and ffmpeg is misreading the duration.

Can you do "D:>ffprobe D.mkv" and post the results?

@JirkaSulkov
Copy link

JirkaSulkov commented Feb 10, 2022

The D.mkv file is not downloaded. I created it in the VideoPad program. I combined 24 parts. This is due to incorrect playback on the smartTV. According to the playlist, all parts will be played at once, but the Subtitle must be set for each.
After linking to a large file, I needed to sync the subtitles in the SubtitleEdit program. But the Waveform soundtrack will only be created by 12:25:29. In consultation with the author of the SE, I found out that it will terminate FFmpeg earlier.
Here is the output of ffprobe.
D:\FF>ffprobe d.mkv
ffprobe version N-90707-g01170e9db0 Copyright (c) 2007-2018 the FFmpeg developers
built with gcc 7.1.0 (GCC)
configuration: --arch=x86_64 --target-os=mingw32 --cross-prefix=/home/jacek/ffenv/04/jpff/cross_compilers/mingw-w64-x86_64/bin/x86_64-w64-mingw32- --pkg-config=pkg-config --pkg-config-flags=--static --enable-gray --enable-version3 --disable-debug --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-w32threads --extra-cflags=-DPTW32_STATIC_LIB --extra-libs=-lstdc++ --enable-gpl --enable-version3 --enable-libx264 --enable-libx265 --enable-libxvid --enable-libmp3lame --enable-libfdk-aac --enable-libopus --enable-zlib --enable-fontconfig --enable-libass --enable-iconv --enable-libfreetype --extra-cflags=-DLIBTWOLAME_STATIC --extra-cflags=-DMODPLUG_STATIC --extra-cflags=-DCACA_STATIC --extra-cflags='-mtune=generic' --extra-cflags=-O3 --enable-shared --disable-static --prefix=/home/jacek/ffenv/04/jpff/win64/ffmpeg_git_with_fdk_aac_xp_compat_shared
libavutil 56. 13.100 / 56. 13.100
libavcodec 58. 17.100 / 58. 17.100
libavformat 58. 11.101 / 58. 11.101
libavdevice 58. 2.100 / 58. 2.100
libavfilter 7. 15.100 / 7. 15.100
libswscale 5. 0.102 / 5. 0.102
libswresample 3. 0.101 / 3. 0.101
libpostproc 55. 0.100 / 55. 0.100
Input #0, matroska,webm, from 'd.mkv':
Metadata:
encoder : libebml v1.4.2 + libmatroska v1.6.4
creation_time : 2022-01-31T22:57:04.000000Z
Duration: 17:08:02.92, start: 0.000000, bitrate: 874 kb/s
Stream #0:0: Video: h264 (Main), yuv420p(progressive), 800x600 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
Metadata:
BPS : 712784
DURATION : 17:08:02.920000000
NUMBER_OF_FRAMES: 1542073
NUMBER_OF_BYTES : 5495827574
_STATISTICS_WRITING_APP: mkvmerge v64.0.0 ('Willows') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2022-01-31 22:57:04
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(cze): Audio: ac3, 44100 Hz, stereo, fltp, 160 kb/s (default)
Metadata:
BPS : 160000
DURATION : 17:08:02.625000000
NUMBER_OF_FRAMES: 1770966
NUMBER_OF_BYTES : 1233652506
_STATISTICS_WRITING_APP: mkvmerge v64.0.0 ('Willows') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2022-01-31 22:57:04
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES

D:\FF>

@MarvusMedia
Copy link

MarvusMedia commented Feb 10, 2022

Other than suggesting a compressed audio format instead of WAV, I don't really know how to help you. Sorry.
Maybe someone else can answer.
Good luck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment