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
06s (Export from 07:00-13:00)
for i in *.mov; do ffmpeg -ss 00:00:07.01 -i "$i" -t 6 -c copy "${i%.*}_UNSLATED.mov"; done
15s (Export from 07:00-22:00)
for i in *.mov; do ffmpeg -ss 00:00:07.01 -i "$i" -t 15 -c copy "${i%.*}_UNSLATED.mov"; done
30s (Export from 07:00-0:37:00)
for i in *.mov; do ffmpeg -ss 00:00:07.01 -i "$i" -t 30 -c copy "${i%.*}_UNSLATED.mov"; done
45s (Export from 07:00-0:52:00)
for i in *.mov; do ffmpeg -ss 00:00:07.01 -i "$i" -t 45.01 -c copy "${i%.*}_UNSLATED.mov"; done
It seems like using the -t option with -c results in inaccurate encoding lengths for mp4s (currently exports are coming out with extra frames). Will have to look into this. https://video.stackexchange.com/questions/23373/ffmpeg-not-creating-exact-duration-clip
for i in *; do duration="$(bc -l <<< "$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$i")-1.02")"; ffmpeg -i "$i" -t "$duration" -c copy "${i%.*}_1.${i#*.}"; done
for i in *; do ffmpeg -i "$i" "${i%.*}_1.jpg"; done
Batch
for i in *.png; do ffmpeg -y -i /usr/local/Cellar/ffmpeg/4.2.1/bin/generate_slate_data/Psyop_HD_Slate_23.976.mov -i "$i" -filter_complex "[0:v][1:v] overlay=25:25:enable='between(t,0,5)'" -pix_fmt yuv420p -c:a copy "${i%.*}.mov"; done
Batch (Just first frame)
for i in *.m*; do duration="$(bc -l <<< "$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$i")-.05")"; ffmpeg -i "$i" -ss 00:00:00 -i "$i" -map 0:v:0 -frames:v 1 "${i%.*}.jpeg"; done
Batch
for i in *.m*; do duration="$(bc -l <<< "$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$i")-.05")"; ffmpeg -i "$i" -ss 00:00:05 -i "$i" -ss 00:00:06.5 -i "$i" -ss 00:00:07 -i "$i" -ss "$(bc -l <<< "$duration*.99")" -i "$i" -map 0:v:0 -frames:v 1 "${i%.*}_1.jpeg" -map 1:v:0 -frames:v 1 "${i%.*}_2.jpeg" -map 2:v:0 -frames:v 1 "${i%.*}_3.jpeg" -map 3:v:0 -frames:v 1 "${i%.*}_4.jpeg" -map 4:v:0 -frames:v 1 "${i%.*}_5.jpeg"; done
Batch
for i in *.m*; do duration="$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$i")"; ffmpeg -ss "$(bc -l <<< "$duration*.25")" -i "$i" -ss "$(bc -l <<< "$duration*.5")" -i "$i" -ss "$(bc -l <<< "$duration*.75")" -i "$i" -map 0:v:0 -frames:v 1 "${i%.*}_1.jpeg" -map 1:v:0 -frames:v 1 "${i%.*}_2.jpeg" -map 2:v:0 -frames:v 1 "${i%.*}_3.jpeg"; done
ffmpeg -i in.mp4 out.avi
ffmpeg -framerate 23.976 -start_number 1001 -i image-%04d.png output.mp4
Single
ffmpeg -i input.mp4 -filter_complex "[0:v] fps=12,scale=480:-1,split [a][b];[a] palettegen [p];[b][p] paletteuse" output.gif
Batch
for i in *.m*; do ffmpeg -i "$i" -filter_complex "[0:v] fps=12,scale=720:-1,split [a][b];[a] palettegen [p];[b][p] paletteuse" "${i%.*}.gif"; done
Compress Gifs
for i in *.gif; do gifsicle -O3 --lossy=80 -o "${i%.*}_compressed.gif" "$i"; done
Taken from GIPHY
Single
ffmpeg -i input.mp4 -i /Volumes/Work/_DMG/_BuggedMasters/_4K/Psyop_3840x2160_WHT.tif -filter_complex "[1:v]scale=1920:1080 [ovrl], [0:v][ovrl]overlay=0:0" -codec:a copy output.mp4
Batch h.264
for i in *.m*; do ffmpeg -i "$i" -i /Volumes/Work/_DMG/_BuggedMasters/_4K/Psyop_3840x2160_WHT.tif -filter_complex "[1:v]scale=1920:1080 [ovrl], [0:v][ovrl]overlay=0:0" -codec:a copy "${i%.*}_psyop.mov"; done
Batch ProRes
for i in *.m*; do ffmpeg -i "$i" -i /Volumes/Work/_DMG/_BuggedMasters/_4K/Psyop_3840x2160_WHT.tif -filter_complex "[1:v]scale=1920:1080 [ovrl], [0:v][ovrl]overlay=0:0" -c:v prores_ks -profile:v 3 "${i%.*}_psyop.mov"; done
Batch ProRes Left Side
for i in *.m*; do ffmpeg -i "$i" -i /Volumes/Work/_DMG/_BuggedMasters/_4K/Psyop_3840x2160_WHT.tif -filter_complex "[1:v]scale=1920:1080 [ovrl], [0:v][ovrl]overlay=-1400:0" -c:v prores_ks -profile:v 3 "${i%.*}_psyop.mov"; done
Batch ProRes with slates removed
for i in *.m*; do ffmpeg -ss 00:00:07 -i "$i" -i /Volumes/Work/_DMG/_BuggedMasters/_4K/Psyop_3840x2160_WHT.tif -filter_complex "[1:v]scale=1920:1080 [ovrl], [0:v][ovrl]overlay=0:0" -c:v prores_ks -profile:v 3 "${i%.*}_psyop.mov"; done
ffplay -f lavfi "movie=input1.mov[a]; movie=input2.mov[b]; [a][b]blend=all_mode=difference"
Green (Recommmended)
ffmpeg -i input1.mov -i input2.mov -filter_complex "blend=all_mode=difference" -pix_fmt yuv420p -c:v libx264 -crf 18 -c:a copy output.mov
Grey
ffmpeg -y -i input1.mp4 -i input2.mp4 -filter_complex "[1:v]format=yuva444p, lut=c3=128, negate[video2withAlpha], [0:v][video2withAlpha]overlay[out]" -map [out] output.mov
Single
ffmpeg -i input.mov -vcodec copy -ac 2 -vol 425 output.mov
Batch
for i in *.m*; do ffmpeg -i "$i" -vcodec copy -ac 2 -vol 425 "${i%.*}_STEREO.mov"; done
for i in *.mov; do ffmpeg -i "$i" -vcodec libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 20M -minrate 20M -maxrate 20M -bufsize 40M -ac 2 "${i%.*}.mp4"; done
Single
ffmpeg -nostats -i input.mp4 -filter_complex ebur128 -f null - > log.txt 2>&1
Batch
for i in *.m*; do echo "${i%.*}" >> log.txt && ffmpeg -nostats -i "$i" -filter_complex ebur128 -f null - 2>&1 | grep "I:" | tail -1 | awk '{print "Integrated","Loudness:",$2, $3}' >> log.txt; done
Single
ffmpeg -ss 00:00:07.01 -i input.mov -c copy output.mov
Batch
for i in *.mov; do ffmpeg -ss 00:00:07.01 -i "$i" -c copy "${i%.*}_UNSLATED.mov"; done
Single
ffmpeg -i input.mov -c:v prores_ks -profile:v 3 output.mov
Batch
for i in *.mov; do ffmpeg -i "$i" -c:v prores_ks -profile:v 3 "${i%.*}_1.mov"; done
Single
ffmpeg -i input.mov -b:a 192k -vcodec libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 20M -minrate 20M -maxrate 20M -bufsize 40M output.mp4
Batch
for i in *.mov; do ffmpeg -i "$i" -b:a 192k -vcodec libx264 -pix_fmt yuv420p -x264-params "nal-hrd=cbr" -b:v 20M -minrate 20M -maxrate 20M -bufsize 40M "${i%.*}_1.mp4"; done
ffmpeg -i in.mkv -c:v copy -c:a copy out.mp4
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
or83
(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
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
- With -c copy the streams will be
stream copied
, not re-encoded, so there will be no quality loss. If you want to re-encode, see FFmpeg Wiki: H.264 Encoding Guide. - The
-shortest
option will cause the output duration to match the duration of the shortest input stream. - See the
-map
option documentation for more info.
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 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
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
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 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.
- Locate the playlist file, e.g. using Chrome > F12 > Network > Filter: m3u8
- 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
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
Deinterlacing using "yet another deinterlacing filter".
ffmpeg -i in.mp4 -vf yadif out.mp4
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
- Automating delivery for networks
- AdStream
- 2s of pre-black, 5s of Slate, 2s of black, SPOT, 1s of black
- Extreme Reach
- 5s of Slate, 2s of black, SPOT
- Tylie
- 5s of Slate, 2s of black, SPOT, 1s of black
- AdStream
- Converting from 23.976 to 29.97
- Converting from HD to SD
- Automatic Generation of Slates
- Comparing two video files
- QC order of 5.1 mix
- Check for interlacing, frame rate, resolution, codec, audio bit rate, audio bit depth, audio codec
- Automate file naming