29 August 2013

Updated: 26 January 2014

Transcoding with FFmpeg

A basic transcode explained1

This will take input.mov and convert it to an MP4 containing a single H264 movie stream and a single AAC audio track:

ffmpeg -i input.mov \
       -c:v libx264 -filter:v yadif -crf 21 -level 3.1 -tune film \
       -c:a libfaac -q:a 100 \

Here's a breakdown of the switches in that command:

CRF defaults to 23, so I adjust to 21 (or 19) to improve the output quality 4.

Switch containers, but don't transcode anything

Sometimes you already have a perfectly fine movie and audio stream and just want to change the container from, say, MKV to MP4:

ffmpeg -i input.mkv -codec copy output.mp4

Transcoding to an intermediate format

This command transcodes to a lossless MPEG transport format, which is useful for importing into other video editing software, and for concat method 2 below.

ffmpeg -i movie_part1.mp4 \
       -c copy -bsf:v h264_mp4toannexb -f mpegts \

Joining several movies together

Method 1 - Concat Demuxer

Concatenating movies is easy. The contents of join.txt is a line-by-line list of the inputs in this format 5:

file 'movie_part1.mp4'
file 'movie_part2.mp4'

Then the concat function is enabled as follows - in this case I'm not converting anything, just joining together:

ffmpeg -f concat -i join.txt -c copy output.mp4

Or the smarty-pants way to do the above:

ffmpeg -f concat -i <(for F in movie_part*.mp4; do echo "file '$F'"; done) \
       -c copy \

Method 2 - Concat Protocol

Some files won't work with method 1 (ffmpeg will spit out errors). Try using an intermediate file for concatenation as shown above:

ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" \
       -c copy -bsf:a aac_adtstoasc \

Cropping out just a section of a movie

Creating a movie which is snippet of another is also easy. The -ss parameter is the start time from which to crop. The -t parameter is the length of the clip you're producing.

ffmpeg -i input.mp4 -ss 01:07:31.000 -t 00:28:15.000 -c copy output.mp4

A little bash wrapper

Transcode to 720p for all movies in a directory:

MOV=$(find ~/movies/Nexus -type f -name "*.mp4" -not -name "*-720*" | head -1)
ffmpeg -i $MOV \
       -s hd720 -c:v libx264 -filter:v yadif -crf 21 -level 3.1 -tune film \
       -c:a libfaac -q:a 100 \
rm $MOV;

Adding or removing streams from a container

It's possible to mux an existing video stream with audio streams of your choosing from multiple different files. Consider:

ffmpeg -i Goodfellas.mkv \
       -i Goodfellas.English.6ch.ac3 \
       -i Goodfellas.Commentary_with_Henry_Hill.m4a \
       -i Goodfellas.Commentary_with_cast_crew.m4a \
       -map 0:0 -map 0:1 -map 1:0 -map 2:0 -map 3:0 \
       -metadata:s:a:1 language=eng \
       -metadata:s:a:1 title="Commentary with Henry Hill" \
       -c copy \

Here there are four input streams, and the -map parameters define five output streams in the resulting mp4:

Finally it sets the metadata for the second audio channel to be English, with a title of "Commentary with Henry Hill". (Note that your output file has to be MKV format in order to add title metadata.)

Examining existing streams

Use the command ffprobe to figure out the stream number in each file:

> ffprobe -i Shaun_of_the_dead.mkv
ffprobe version 1.2.4 Copyright (c) 2007-2013 the FFmpeg developers
  built on Oct  7 2013 08:36:39 with Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/1.2.4 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=cc --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid
  libavutil      52. 18.100 / 52. 18.100
  libavcodec     54. 92.100 / 54. 92.100
  libavformat    54. 63.104 / 54. 63.104
  libavdevice    54.  3.103 / 54.  3.103
  libavfilter     3. 42.103 /  3. 42.103
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
Input #0, matroska,webm, from 'Shaun of the Dead (BDrip 1080p ENG-ITA-FRA-GER-SPA) Multisub x264 bluray (2004).mkv':
    creation_time   : 2010-12-16 14:12:31
  Duration: 01:39:20.19, start: 0.000000, bitrate: 6632 kb/s
    Stream #0:0: Video: h264 (High), yuv420p, 1872x820 [SAR 1:1 DAR 468:205], 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc
    Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 448 kb/s
      title           : English AC3 5.1 chnls 640 kbps
    Stream #0:2(ita): Audio: dts (DTS), 48000 Hz, 5.1(side), fltp, 768 kb/s
      title           : Italian DTS 5.1 chnls 768 kbps
    Stream #0:3(fre): Audio: aac, 48000 Hz, 5.1, fltp
      title           : French Aac 5.1 chnls 320 kbps
    Stream #0:4(ger): Audio: aac, 48000 Hz, 5.1, fltp


Tagged in tekkers