====== FFmpeg ======
Super handy [[terminal_emulator|terminal]]-based tool for working with video.
===== Use =====
Some examples I use.
==== Converting ====
Most of the time I just use---
ffmpeg -i [input.ext] [output.ext]
---and it usually works fine leaving it to just use defaults.
This gives good results (and a smaller file size) converting MP3 to OGG though:
ffmpeg -i [input].mp3 -c:a libvorbis -q:a 4 [output].ogg
Fuck-off those .WEBMs:
ffmpeg -i [input].webm -acodec copy -vcodec copy [output].mkv
=== Multiple ===
For doing a whole directory I use this one-liner I got from Stack Exchange.
for i in *.[ext]; do ffmpeg -i "$i" "${i%.*}.[ext]"; done
For converting files for my [[m-u-s-u-c]] blog I also strip out the cover images: ''-map a'' tells it to take only the audio stream.
for i in *.mp3; do ffmpeg -i "$i" -c:a libvorbis -q:a 4 -map a "${i%.*}.ogg"; done
You can use the wildcard ''*'' in the file extension to, so if you've got a mix of .mkv and .mp4 files from Youtube you can do. say:
for i in *.m*; do ffmpeg -i "$i" "${i%.*}.ogv"; done
If you want to put the new videos into a subdirectory, first create it, then simply add it to the output part:
for i in *.[ext]; do ffmpeg -i "$i" "directory/${i%.*}.[ext]"; done
For converting a directory of .FLAC files to .MP3. ''[-q:a 0|-b:a 320k]'' is your choice between VBR with the best quality (0) or a CBR of 320k. VBR is generally just as good, though sometimes you need CBR.
for i in *.flac; do ffmpeg -i "$i" [-q:a 0|-b:a 320k] "${i%*}.mp3"; done
==== Editing ====
=== Concatenation ===
The main thing I use FFmpeg for is just stitching videos together. I make a list of the files inside a text document, each line looks like this:---
file '[file location]'
---then point FFmpeg at that and give the command and it runs through them all. Nice and easy.
ffmpeg -f concat -safe 0 -i "inputfile.txt" -c copy "inputfile.ext"
[[https://trac.ffmpeg.org/wiki/Concatenate#demuxer|FFmpeg's docs on generating the list]]:
# with a bash for loop
for f in *.wav; do echo "file '$f'" >> mylist.txt; done
# or with printf
printf "file '%s'\n" *.wav > mylist.txt
If you have a movie in two parts and want to stick them together with less fuss, or you just want to save yourself the trouble of making the file, you can use //process substitution//:
ffmpeg -f concat -safe 0 -i <(for f in ./*.avi; do echo "file '$PWD/$f'"; done) -c copy output.avi
NB: Some older codecs let you stick files together with just [[cat]]!: https://ffmpeg.org/faq.html#toc-Concatenating-using-the-concat-protocol-_0028file-level_0029
=== Cropping ===
To crop a 16:9 video to 4:3, add:
-filter:v "crop=ih/3*4:ih"
Full example, with copied audio stream:
ffmpeg -i [file] -filter:v "crop=ih/3*4:ih" -c:a copy [file]
=== Remove Audio ===
Add ''-an'' to your command.
=== Rotation ===
Rotate 90°.
ffmpeg -i inputfile.ext -vf "transpose=1" outputfile.ext
=== Trimming ===
You can pretty easily make a video shorter. The only caveat is that if you don't want to re-encode you're limited by where keyframes are placed.
ffmpeg -i inputfile.ext -ss HH:MM:SS -to HH:MM:SS -c copy outputfile.ext
* ''-ss'' is the point you want it to start
* ''-to'' is the point you want it to end
* ''-t'' is the length you want it to run from the start time
* Instead of using the format ''HH:MM:SS'' you can just give a number of seconds.
* You can also add milliseconds to either of those formats.
* Leaving out the ''-ss'' or ''-to''|''t'' will use the file's existing start or end time.
* If you leave out the ''-c copy'' it will re-encode the video
==== Images ====
=== Extract each frame as an image ===
ffmpeg -i [file] frame%03d.png
=== Create video from images ===
cat *.png | ffmpeg -framerate [framerate] -f image2pipe -i - [file]
== GIF ==
Default loops. Add ''-loop -1'' to only play once.
cat *.png | ffmpeg -framerate [framerate] -f image2pipe -i - [filename].gif
== APNG ==
Default doesn't loop. Add ''-plays 0'' to loop.
cat *.png | ffmpeg -framerate [framerate] -f image2pipe -i - -f apng [filename].png
==== Lowering the file size ====
Slow, but compresses better:
-preset veryslow
=== Bitrate ===
=== Dimensions ===
Scales 50%
ffmpeg -i "inputfile.ext" -vf "scale=iw/2:ih/2" "outputfile.ext"
Scales to set pixel dimensions (replace 'width' and 'height'):
ffmpeg -i "inputfile.ext" -vf scale=width:height "outputfile".ext
* https://trac.ffmpeg.org/wiki/Scaling
==== Repairing ====
Just had an .AVI file throwing error messages about a busted index. Copying the file seemed to fix it.
ffmpeg -i "inputfile.avi" -c:v copy -c:a copy "outputfile.avi"
===== Frontends =====
* [[https://ffmpeg.lav.io/|FFmpeg Explorer]] - Browser-based GUI with a node-based interface for changing parameters.
===== See Also =====
* [[https://www.ffmpeg.org/|www.ffmpeg.org]]
* [[https://trac.ffmpeg.org/wiki|FFmpeg Bug Tracker and Wiki]]
* [[gifsicle]] - Similar tool, specifically for working with [[gif|GIFs]]
{{tag>CLI guide software tool video}}