A couple of weeks ago I needed to trim an MP4 file. I didn’t necessarily want to re-encode besides I was on a machine without a media encoding application. I thought I’d try out FFmpeg which is a command line video and audio transcoder.
$ brew install ffmpeg
It takes a while but once it’s installed we can start trimming or transcoding video and audio.
I have a file on my Desktop folder and used
$ cd ~/Desktop
to navigate to it in Terminal. I’m just going to leave my inputs and outputs here for demonstration. In a real world situation I’d hope that I would be a little more organised (stress on the hope).
To change the format of the video to, say a WMV (presumably to send to someone in 2010), it’s just:
$ ffmpeg -i "input-vid.mp4" "output-vid.wmv"
(The inverted commas are optional but do a better job at breaking up the syntax.)
Now we have WMV transcoding on a Mac for free.
The -i option denotes that the next value is the input file name (and path if we were in a different directory) and after that comes the output file. Note that all I’ve supplied is a file extension and FFmpeg has used that as the basis for the file type it will transcode to.
If we wanted to just take the audio and convert it to an MP3 then it’s
$ ffmpeg -i "input-vid.mp4 "output-audio.mp3"
The file we are using is an MP4 H.264 and we can convert this to a .avi which is just a container format without encoding again using -c copy:
$ ffmpeg -i "input-vid.mp4" -c copy "output-vid.avi"
Same goes for Quicktime .mov files which are also just containers:
$ ffmpeg -i "input-vid.mp4" -c copy "output-vid.mov"
To resize video just use the -s option followed by the required dimensions:
$ ffmpeg -i "input-vid.mp4" -t 00:00:30 -s 640x360 "cut-vid.mp4"
To alter the video bitrate just use -a:v [bitrate amount]
$ ffmpeg -i "input-vid.mp4" -b:v 500k "output-vid.mp4"
Here the output file will have an Average Bit Rate (ABR) of 500kb
A Constant Bit Rate (CBR) can be set by explicitly stating the same maximum and minimum bit rate:
$ ffmpeg -i "input-vid.mp4" -b:v 500k -minrate 4000k -maxrate 4000k "cut-vid.mp4"
Audio bit rates are set the same:
$ ffmpeg -i "input-vid.mp4" -b:a 500k "cut-vid.mp4"
To trim the video extracting just a section from 10 seconds in to 30:
$ ffmpeg -i "input-vid.mp4" -ss 00:00:10 -to 00:00:30 -c copy "cut-vid.mp4"
The first part of this -ss is the seek command which will start the video at 10 seconds (HH:MM:SS:xxx(milliseconds)). The -to command should be pretty self- explanatory.
Need just the first 30 seconds?
$ ffmpeg -i "input-vid.mp4" -t 00:00:30 -c copy "cut-vid.mp4"
The -t command is the duration.
Problems can arise when we don’t land on an I-frame. In short, file formats like MPEG-4 use a compression algorithm which means that only certain frames are ‘real frames’ (I-frames) while the rest are based on the previous I-Frame, a guess of what the next one will look like or a combination of both. Not landing on an I-frame can resul in a stalled image or no image at all. In order to ensure accurate video and audio syncing we may need to re-encode by just omitting the -c copy:
$ ffmpeg -i "input-vid.mp4" -t 00:00:30 "cut-vid.mp4"
However if we want to re-encode the video but just copy the audio we can use:
$ ffmpeg -i "input-vid.mp4" -c:a copy "cut-vid.mp4"
More complex scenarios like multiple audio and subtitle streams can use the -map option.
If we wanted to create a JPEG screen grab from the tenth second:
$ ffmpeg -i "input-vid.mp4" -ss 00:00:10 -frames:v 1 "grab-1.jpg"
Since formats like .mov are just containers we can specify the codec we want to use as well as the library that will do the encoding. Each have different options that are available here.
To see that encoders that are available:
$ ffmpeg -encoders
This lists all available encoders:
$ ffmpeg -i "big_buck_bunny_480p_surround-fix.avi" -c:v wmv1 "output-video.wmv"
If you don’t like working in lossy formats we can even encode to Apple’s ProRes format.
HTML5 fast start
When encoding HTML5 video it’s advisable to have the file’s header information at the start of the file to aid progressive download. This ensures that since all data about the file is contained at the start it starts playing quickly.
This is achieved with the moov atom. For an MP4 encoded using the libx264 library:
$ ffmpeg -i "input-file.mp4" -c v:libx264 -movflags faststart -c v:lib264 "output-file.mp4"
FFmpeg is a quick and relatively easy way to encode video an worth an install. You can also check out the repo on GitHub here.