Video Processing and Encoding
For a couple of years there have been a number of great open-source programs around for encoding video, both in Windows and (Ubuntu) Linux. Some of them provide a nice graphical user interface, but the best ones are still commandline tools, such as ffmpeg and MEncoder. They are extremely flexible, but unfortunately also have a bewildering number of commandline options. This page lists a few invocations I regularly use.
Extracting DVD titles
To extract a single title from a DVD, first copy the DVD to harddisk:
dvdbackup -M
Next, use totem or vlc (under Plackback->Title) to find out the number of the title you want. For our example we’ll assume that the DVD files are in a directory called DVD_VOLUME/ and that we want the second title. Finally, copy the title to a separate file using mencoder:
mencoder -dvd-device DVD_VOLUME/ "dvd://2" -ovc copy -oac copy -of mpeg -o title_2.mpeg
This will create an MPEG2 file containing just the title you specified.
You can of course select a different container format with the -of
parameter, or a codec other than copy
to transcode the file. To leave
out audio, use -nosound
instead of -oac copy
.
Cutting/selecting part of a video
With the options -ss
and -endpos
you can tell mencoder to
process only a part of the input file. Note that mencoder can currently
only split streams on keyframes, and the position used with -endpos
is
relative to the start of the output, not the input (so it’s perhaps more
logical to think of it as “duration”). Here’s an example:
mencoder -ss 05:30 -endpos 12:45 -oac copy -ovc copy input.avi -o output.avi
You may want to consider avidemux for a more user-friendly alternative (which is also more flexible when it comes to cutting frames) .
Fast MPEG-4 encoding with FFmpeg
I recently needed to rapidly transcode a HDTV-quality H.264 file into MPEG4, so I could play it decently on an ancient Xbox. The following worked very well, and finished the job in no-time on my multi-core machine:
ffmpeg -i input.mp4 -vcodec mpeg4 -threads 2 -b 1500k -acodec libmp3lame -ab 160k output.avi
Or if the audio was already fine:
ffmpeg -i input.mp4 -vcodec mpeg4 -threads 2 -b 1500k -acodec copy output.avi
Encoding DVD-compliant MPEG-2 video
Check out Eric Olson’s page on this subject, and his automated encoding script. I could not get it to encode MP2 audio under Ubuntu Lucid out-of-the-box, so I used twolame to encode the audio separately. For authoring a DVD, I found DVDStyler to work quite nicely, at least once you figure out the somewhat awkward user-interface… But at least it doesn’t try to re-encode your videos when they’re already in the right format.
See also:
Extracting audio from a video file
You can do this with FFMPEG by specifying -vn
to disable video. You
can use any output format and codec, but for best results don’t reencode
(-acodec copy
) and choose an output file-format that matches the audio
codec used in the video file. You can use e.g. mplayer
or ffprobe
to
check whether the audio track is AAC (use .aac / .m4a / .mp4 for
output), MP3 (use .mp3), MP2 (use .mp2), PCM (use .wav or .flac) or
something else. If in doubt, use FLAC output for lossless encoding
without huge files. Use -acodec pcm_s16le
if you want uncompressed
.wav files. Some examples:
ffmpeg -i input.flv -vn -acodec copy output.m4a
ffmpeg -i input.avi -vn output.flac
Note that you can tag MPEG-4 files using neroAacTag.
Encoding interlaced PAL DV to H.264
If you want to archive interlaced 4:3 PAL DV material without wasting too much disk-space or losing too much quality, try encoding it to interlaced H.264. Use a recent version of x264, e.g. from ppa:jon-severinsson/ffmpeg or ppa:motumedia/mplayer-daily. If quality is important, try the following:
x264 --bff --sar 12:11 --threads auto --preset veryslow --crf 20 -o output.mp4 input.avi
Increase the CRF to 23-25 for smaller but slightly lower-quality files,
and change the preset to slower
, slow
or medium
to increase
the encoding speed at the cost of some quality and/or size.
x264 does not encode audio, so you’ll need to encode it separately (e.g.
ffmpeg -i input.avi -vn output.flac
)
and then multiplex. For audio encoding, you could also use an external
encoder, such as the Nero AAC encoder or LAME (for mp3).
Multiplexing with ffmpeg is easy, for example:
ffmpeg -i video.mp4 -i audio.m4a/mp3/flac/wav -vcodec copy -acodec copy output.mp4
You’ll probably want to combine the entire operation into a shell-script. Something like:
#!/bin/bash
in=$1
out=$2
subdir=
if [ -z "$1" ]; then
echo "Usage: $0 infile [outfile]"
exit
fi
if [ -z "$out" ]; then
out="${in%avi}mp4"
fi
if [ "$subdir" ]; then
if [ ! -d $subdir ]
then mkdir -p $subdir
fi
out=$subdir/$out
fi
if [ -e $out ]; then
echo "Error: outfile $out already exists (or is same as infile)"
exit
fi
echo Encoding $in to $out
x264 --bff --sar 12:11 --threads auto --preset slow --crf 21 -o tmp-video.m4v $in
ffmpeg -i $in -vn tmp-audio.wav
neroAacEnc -q 0.75 -if tmp-audio.wav -of tmp-audio.m4a
ffmpeg -i tmp-video.m4v -i tmp-audio.m4a -acodec copy -vcodec copy $out
rm tmp-video.m4v tmp-audio.wav tmp-audio.m4a
Generating black video to match an audio track
FFMpeg is capable of adding a silent audio track to a video, or if
you provide an audio track that is shorter than the video, FFMpeg allows
you to pad the audio with silence to match the video length (using
-apad -shortest
). Sometimes however, you may need to do it the other
way around: generate blank video to match a longer audio track.
Unfortunately this can not be easily accomplished with FFMpeg. So far,
the only method I’ve found is to manually split the audio track into two
parts, generate a blank video sequence for the additional audio, and
concatenate the two. This is far from ideal. Nonetheless, this is how
you can generate a blank video sequence to match an audio track:
ffmpeg -i audio.m4a -f lavfi -i color=black:1280x720 -r 30 -vcodec libx264 -preset slow -crf 24 -acodec copy -shortest output.mp4
The above example will generate a 30fps 1280x720 black video sequence, encode it as H.264 and multiplex it with the audio.
Concatenating video files
This is another operation that is easy with MEncoder but quite hard with
FFMpeg (depending on the version you’re using). As of FFMpeg 1.1, there
are several official ways to concatenate videos. To concatenate
MPEG4-files (or any MPEG-format) on Linux, you can also use cat
, as
long as you convert the files to MPEG Transport Streams before
concatenating. This example works for H.264 video with AAC audio in an
MPEG4-container:
ffmpeg -i video1.mp4 -acodec copy -vcodec copy -vbsf h264_mp4toannexb video1.ts
ffmpeg -i video2.mp4 -acodec copy -vcodec copy -vbsf h264_mp4toannexb video2.ts
cat video1.ts video2.ts >videofull.ts
ffmpeg -i videofull.ts -isync -acodec copy -vcodec copy -absf aac_adtstoasc videofull.mp4
Encoding PAL DV to MPEG-4 video
Note: The below is a bit outdated, it needs to be updated…
I use Kino to capture DV video from my camcorder over FireWire. As I have a rather cheap camcorder, the result tends to be somewhat noisy. I compress it using MEncoder, and I usually set it co constant quality (vqscale=4, use a value of 3 or 2 for better quality), switch on noise reduction (nr=600) and some high-quality options (mbd=2:trell=yes:v4mv=yes), and I apply a deinterlacing filter to the source (-vf-add kerndeint). I force the fourcc identifier to MP4V, because not all players recognise the default FMP4 identifier. Also, you have to explicitly provide the aspect ratio (4:3 for PAL) for it to be stored in the AVI output header.
mencoder -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell=yes:v4mv=yes:nr=600:vqscale=4:aspect=4/3 -oac mp3lame -lameopts vbr=3 -vf-add kerndeint -ffourcc MP4V -o mpeg4-output.avi dv-input.avi
Kino usually splits the DV stream into multiple files, so after compression I join them together again using:
mencoder -oac copy -ovc copy -of avi -force-avi-aspect 4/3 -o merged-output.avi fragment1.avi fragment2.avi fragment3.avi
Note that of course you can already join multiple fragments during the
encoding step. Also, use of variable bitrate (VBR or ABR) in the MP3
audio stream may sometimes cause your audio and video to go out of sync.
To prevent that you can use something like -lameopts cbr:br=160:mode=0
to force stereo audio with a constant bitrate (128, 160 or 192 kbps
should be fine) instead of a variable one.
To get a smaller file, you could consider using either multipass encoding or encoding with a more advanced codec such as H.264. For multipass encoding, leave out the vqscale option and run mencoder several times, providing the options vpass=1:turbo, vpass=2, etc. for each pass.
To encode as an H.264 AVI file with AAC audio, you should be able to use something like:
mencoder -ovc x264 -x264encopts threads=auto:subq=5:8x8dct:frameref=2:bframes=3:weight_b:crf=24 -force-avi-aspect 4/3 -vf hqdn3d,kerndeint,scale -oac faac -o output-h264.avi input-dv.avi
Increase the crf value to get a smaller file, or decrease it for higher quality. It’s probably a good idea to convert the AVI file to an IsoMedia (MPEG-4 part 14) stream afterwards, e.g. using MP4Box from the Ubuntu gpac package.:
mplayer -dumpvideo -dumpfile output-h264.h264 output-h264.avi
mplayer -dumpaudio -dumpfile output-h264.aac output-h264.avi
MP4Box -add output-h264.avi -new output-h264.mp4
Unfortunately MP4Box complains about the video stream (Cannot find H264 start code), I’m not sure why.
Update (2012-09-08):
Recent versions of ffmpeg
can also be used to
convert (or encode directly to) mp4.
If it does work, the result should play fine using something like MPlayer or VLC, but unfortunately not with Quicktime 7. To make the file playable by Quicktime 7, reduce the encoding options in the mplayer commandline to:
-x264encopts threads=auto:subq=5:frameref=2:crf=24