FFmpeg

From Segfault
Jump to: navigation, search

Installation

Installation

Usage

Transcoding

We want to convert a video to a smaller one, of constant size. Let's find out what we have:

$ ls -hgo file.mkv
-rw-r--r--. 1 2.5G Dec 29  2012 file.mkv

$ ffmpeg -i file.mkv 2>&1 | egrep 'Duration|Video|Audio'
 Duration: 01:29:31.28, start: 0.000000, bitrate: 3883 kb/s
   Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709), 1280x720, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1k tbn, 50 tbc (default)
   Stream #0:1(ger): Audio: ac3, 48000 Hz, stereo, fltp, 448 kb/s (default)

Let's see if can convert it to maybe 800 MB. First, calculate the duration of the video in seconds:

$ echo "01:29:31.28" | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
5371.28

Our 800 MB output file should contain a 160 kbps audio track too, so let's do some math here:

           800 MB = 819200   kB
5371.28 * 160 / 8 = 107425.6 kB                              ← audio
                    711774.4 kB / 5371.28 * 8 = 1060.1 kbps  ← video

With that information we can now begin the two-pass encoding[1] process. First we analyze the video track, ignore the audio and discard all output:

ffmpeg -i file.mkv -pass 1 -c:v libx264 -b:v 1060k -an -f rawvideo -y /dev/null 

While the output is discarded, two files are generated, ffmpeg2pass-0.log and ffmpeg2pass-0.log.mbtree:

$ ls -hgo ffmpeg2pass-0.log*
-rw-------. 1  16M Jan 20 09:15 ffmpeg2pass-0.log
-rw-------. 1 603M Jan 20 09:15 ffmpeg2pass-0.log.mbtree

Both will be used in the next step:

ffmpeg -i file.mkv -pass 2 -c:v libx264 -b:v 1060k -c:a libvorbis -b:a 160k -ac 2 file.mp4

The result is slightly below 800 MB:

$ ls -hgo file.mp4
-rw-------. 1 770M Jan 21 10:46 file.mp4

$ ffmpeg -i file.mp4 2>&1 | egrep 'Duration|Stream'
 Duration: 01:29:31.36, start: 0.002667, bitrate: 1201 kb/s
   Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1059 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
   Stream #0:1(ger): Audio: vorbis (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 133 kb/s (default)

Apparently our audio track encoded by libvorbis is using VBR by default[2].

Results (on a very slow machine, throttled to 800 MHz):

One Pass Encoding
$ ffmpeg -i file.mkv -c:v libx264 -b:v 1060k -c:a libvorbis -b:a 160k -ac 2 file.mp4
=> finished after 29h, 768 MB file

Tow Pass Encoding
$ ffmpeg -i file.mkv -pass 1 -c:v libx264 -b:v 1060k -an -f rawvideo -y /dev/null
$ ffmpeg -i file.mkv -pass 2 -c:v libx264 -b:v 1060k -c:a libvorbis -b:a 160k -ac 2 file.mp4
=> finished after 35h (10h for pass-1, 25h for pass-2), 770 MB file

On a more recent machine, converting a similar file should take no longer than 2-3 hours.

The files from both encoding jobs shared the same properties:

Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1059 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Stream #0:1(ger): Audio: vorbis (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 133 kb/s (default)

Merging

Here we wanted to speed up a video (25min15) so that it could be merged together with an MP3 file (4min22):

ffmpeg -i a.mov -i b.mp3 -acodec copy -ab 128k -ar 44100 -map 0:0 -map 1:0 -vf "setpts=(1/6)*PTS" c.mp4

The order of the arguments matter:

-i         video input, audio input
-acdodec   copy audio stream
-ab        audio bitrate (bps)
-ar        audio sampling rate (Hz)
-map 0:0   get video from the video file
-map 1:0   get audio from the audio file
-vf        apply a filter graph to the input video

The map and vf options are kinda advanced and the setpts parameter was kinda hard to get right. Basically it increases video speed by 6. The audio input is not affected by this, as it is located on a different (internal) stream, see the map option above. Increasing the video speed by 6 meant that the video would be ~4 minutes long, a bit shorter than the audio track. But for now this was good enough.

Container Formats

To change the container format (instead of re-encoding[3]), we can use:

ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4

Audio

Converting[4] audio files to another format, e.g. Vorbis[5]

ffmpeg -y -i file.wav -c:a libvorbis  -qscale:a 3 file.ogg     # qscale:a 3 is the default for libvorbis[6]
ffmpeg -y -i file.wav -c:a libmp3lame -qscale:a 2 file.mp3     # qscale:a 2 translates to a bitrate of ~170-210 kbps[7]
ffmpeg -y -i file.wav -c:a libopus    -vbr on     file.opus    # ?

Notes:

  • To get a list of all supported encoders, use ffmpeg -encoders.
  • When used in a script, ffmpeg sometimes attempts to read stdin[8][9]:
Press [q] to stop, [?] for help
Enter command: <target>|all 

Use -nostdin or read from /dev/null to prevent that, e.g.:

ls wav/ | while read f; do ffmpeg -y -vn -i wav/"$f" -c:a libvorbis -qscale:a 3 ogg/"${f/%wav/ogg}" < /dev/null; done

Encode to MP3 with ffmpeg[7][10]

ffmpeg -i file.flac -c:a libmp3lame -qscale:a 3 file.mp3

Slideshow

Make a slideshow video from images:

ffmpeg -pattern_type glob -i 'image*.jpg' -c:v libx264 slideshow.mp4

The single quotes are important, as ffmpeg will do the globbing, not the shell.

DVD Rip

Let the DVD play once, then select all the parts containing the movie (i.e. skipping VTS_01_0.VOB):

cat VTS_01_[1-8].VOB | ffmpeg -i - -codec:a libvorbis -b:a 128k -codec:v libx264 -b:v 1024k out.mp4

Links

References