Last Thursday, I discussed youtube-dl
, a tool that allows you to
easily download various kinds of media from the web. What happens once you have
that media? Or what happens if you want to do something with media you already
have?
ffmpeg
is almost always the answer. It can take nearly any form of audio
or video media and convert it to almost any other form. It can extract clips,
transcode media, rotate it, crop it, downsample, upsample, etc. ffmpeg
is truly omnivorous.
In fact, many media players and/or transcoders that you may know and love are
actually just graphical front-ends for ffmpeg
. Handbrake and Plex
are two examples that spring to mind.
I’ve spoken about ffmpeg
many times in the past, and I’ve often been asked to
write a primer on how to use it. To cover every nook and cranny of ffmpeg
would
take forever, so instead I’ll just cover a handful of examples I find myself
using often.
Installation
The easiest way to install ffmpeg
is to use Homebrew:
brew install ffmpeg
There are some nuances to installation if you want support for certain sub-sets of functionality, but the above will at least get you started.
Basic Usage
Let’s say you downloaded a file using youtube-dl
and it ended up in a format
you didn’t expect:
youtube-dl "https://www.youtube.com/watch?v=s64RnXSwn-A"
The resulting file is of type .mkv
; let’s say the full filename is
input.mkv
just to make things easier. MKV files are not a format that
Apple OSes tends to like. Let’s suppose you want to convert that into something
more Apple-friendly, like a .mp4
. That’s simple to do:
ffmpeg -i input.mkv output.mp4
We’re using the -i
parameter to specify the input file to ffmpeg
, and then
we’re simply specifying the output file. By virtue of the .mp4
extension,
ffmpeg
is smart enough to divine what to do.
Similarly, if we wanted to extract the audio from this video after we’ve already downloaded it, we could do so as such:
ffmpeg -i input.mkv output.mp3
Again, the presence of .mp3
will tell ffmpeg
all it needs to know.
Trimming
If you actually watch the video, there’s an intro section and an outro section
that we really don’t need. The intro ends at 46 seconds. We can
instruct ffmpeg
to start the output at that point:
ffmpeg -i input.mkv -ss 00:00:46 output.mp3
Here, we’re using the oddly-named -ss
parameter to set the hours:minutes:seconds
into the input we wish to seek before we start “recording”, so to speak.
However, we haven’t gotten rid of our outro yet, which lasts for the last six
seconds of the video. We can handle that using the -to
option, which sets when
to stop processing the input file, in the time system of the input file. Since
output.mp3
is 4:34 seconds, then we need to subtract 6 from that, to land on
00:04:28
:
ffmpeg -i output.mp3 -to 00:04:28 trimmed.mp3
What if we wanted to do both at once? We can use the -to
parameter to set
the end point (again, in terms of the input), in addition to the -ss
to set
the start time. Note, though, we’re using the original file as the input again.
Thus, we have to change the end point for the -to
since we’re starting from
the full file, not the one with the intro clipped. Finally, we land on this
“compound” command:
ffmpeg -i input.mkv -ss 00:00:46 -to 00:05:13 trimed.mp3
In one shot, we’ve:
- Stripped the audio
- Transcoded the video
- Trimmed the beginning
- Trimmed the end
Pretty cool stuff, and pretty easy, once you learn to speak ffmpeg
.
Cropping
What if you download a different file, but it has bars on the top/bottom or left/right?
youtube-dl "https://www.youtube.com/watch?v=tTiiDQ03eSQ"
In this case, we’d like to remove the small black bars on the left and right sides of the video. We know we need to take off about 10 pixels total; 5 on both the left and right sides. We can do so by using a video filter:
ffmpeg -i input.mp4 -vf "crop=in_w-10:in_h" cropped.mp4
The crop
parameter to the -vf
(video filter) parameter indicates what the
resolution of the width and then height of the output video should be. We use
the in_w
and in_h
macros to indicate the source width and height; then we
subtract 10
from the width.
Codecs
Continuing with the above example, we can make this ever-so-slightly faster. We
know that we want the final file to be in the same format—.mp4
—as
the source was. Since we’re not doing any sort of modifications to the audio, we
can tell ffmpeg
to copy the audio codec:
ffmpeg -i input.mp4 -vf "crop=in_w-10" -acodec copy cropped.mp4
Since the audio is far easier to process than the video, this isn’t the best
example, as the time savings are marginal. However, in some cases, you may be
able to get away with copying the video codec using -vcodec copy
. In those
cases, that is a big time savings.
It’s beyond the scope of this article, but a nice way to figure out if you can
leverage -vcodec copy
is to run a command with no output:
ffmpeg -i input.mp4
That will tell you what the video and audio streams are:
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 819 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
In our case, we know that the video is h264
, which means that we can
use -vcodec copy
is possible if we’re converting to .mp4
.
Variable Bit Rates
Related to codecs, when left to its own devices, ffmpeg
will encode mp3
s at
a constant 128kbps. That’s sufficient, but I prefer to use a variable bit rate.
To do so, we use a less intuitive incantation:
ffmpeg -i input.mkv -codec:a libmp3lame -qscale:a 2 output.mp3
This is… completely bonkers. Ridiculous incantations like these—if not the
ones that preceded it—are why ffmpeg
gets a bad name. However, the sheer
versatility of ffmpeg
makes it an indispensible tool that I can’t imagine living
without.
I’ve set up a folder in the Apple Notes app with a series of “recipes” for ffmpeg
.
As I find a new task I want to accomplish, I determine what the recipe is, and then
write it down as a new note in that folder. You may find the same tactic is useful
for you. Regardless, most of that “recipe book” has been recreated above.
I know the command line is scary, but ffmpeg
is worth getting over it. Everything
you do in ffmpeg
is non-destructive, so the only harm in playing around is
wasting time and listening to your computer’s fans scream. At first I never did
anything more than transcoding using ffmpeg, but over time, I’ve gotten to be
pretty confident with it.