There was a period of time where I forced myself to learn video editing on terminal with ffmpeg. No, it’s not that I was some go-getter hotshot. It’s just that when I switched to a niche CPU architecture, the non-linear graphical video editors that were in my distro’s repository at the time didn’t want to play nicely.
But, even though the GUI editors are now working well on my system, I still often use ffmpeg to this day to edit moderately simple clips because it’s just faster and cleaner. I want to share some of the more common edits that I find myself using. The learning curve really isn’t so bad.
ffmpeg -i video.mp4 -ss 00:03:10 -t 00:00:15 -c copy output.mp4
-i specifies the source file. -ss specifies the start time. -t sets the duration (this example ending 15 seconds after the start time). -c copy instructs ffmpeg to write that segment of the file without rendering anything. It’s incredibly fast but can leave some paused frames at the end of the clip.
ffmpeg -i video.mp4 -ss 00:00:07 -t 00:00:03 -f gif output.gif
This example will create a 3 second long gif from a source video starting 7 seconds in. It is simple but can be a bit grainy.
ffmpeg -i video.mp4 -ss 00:00:42 -t 00:00:10 -filter_complex "[0:v] fps=12,scale=480:-1" -f gif output.gif
-filter_complex allows us to add trailing parameters which, in this example, specify to edit only the video and set it to 12 fps at a width of 480 pixels. The trailing -1 just keeps the aspect ratio.
You can also use -filter_complex to crop a region by passing parameters like crop=400:400:100:0,fps=15,scale=360:-1. The crop inputs are ordered as =width:height:pixels from left:pixels from top.
Or to just crop video you can use the simpler -filter:v.
ffmpeg -i video.mp4 -filter:v "crop=360:240:70:200" output.mp4
ffmpeg -i video.mp4 -vf scale=480:-2 output.mp4
Like with gif making, the trailing -2 maintains aspect ratio. Otherwise you can specify custom width:height.
Start by creating a control file and populate it with the names of the desired clips like so.
file 'clip_1.mp4' file 'clip_2.mp4' file 'clip_3.mp4'
Then feed the file list like you normally would a video source.
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4
-f concat instructs ffmpeg to merge the files together. They generally need to be the same type of encoding, framerate and resolution as all the others so remember to adjust these ahead of time.
This could be useful if you want to present something on-screen momentarily or throughout the clip. I recommend images that have transparency if it’s an irregular shape.
ffmpeg -i video.mp4 -i image.png -filter_complex "[0:v][1:v] overlay=35:35:enable='between(t,0,48.5)'" -pix_fmt yuv420p -c:a copy output.mp4
Stream [ :v] is passed twice, one for the source video and one for the image. overlay= positions the image by distance from left:top and between(t,,) declares the start and end time in seconds for the image to appear.
ffmpeg -i video.mp4 -vn output.ogg
-vn blocks all video streams. Or to keep the raw audio without encoding (maybe you want to preserve song quality?).
ffmpeg -i video.mp4 -vn -acodec copy output.mp3
-acodec instructs copy to only handle the audio.
There are tons of other things ffmpeg can do. They refer to it as the swiss army knife of media conversion. It might be worth making some scripts out of these if there is some edit pass that you do a lot of. Maybe in a future post I’ll share some audio handling one liners.