Home‎ > ‎Tom's Ideas And Notes‎ > ‎

Transcoding HD Video to h264 MP4

posted Jan 24, 2010, 11:56 AM by Tom Gutwin   [ updated Feb 24, 2010, 8:33 AM ]
I have been doing this for quite a few years and I always come back to ffmpeg. I have tried x264, gstreamer, transcode and others....

I recently started capturing HD video TV shows and needed to save space, so I wrote a small script to work specifically on HD video - 1920x1080.
It re-sizes to 1/2 size - 960x540 and encodes it with h264 video codec and aac audio.  I also have a Theora/ogg conversion script but the mp4 one is a bit more stable. 
It reduces a 8GB HD files to 500-600MB with Very good quality.

I also use Winff it is an ffmpeg gui wrapper that works really well!  Try it out.

Convert to Theora Vorbis

hd2ogv

#!/bin/bash
#  High Def'n to Theora/Vorbis concersion
#
#  This script requires 2 parameters on the commandline
#    1 - is the file to convert
#    2 - is the output filename (without the ogv extension)
#
#  NOTES:
#   - the result size and bitrates are hardcoded into the commands below
#   - the vframes 500 option specifies how many frames to do (ie do 500 to test)
#      leave it out to do all
#
OUTPUT_DIR=/home/tgutwin/Videos
#
# see http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
/usr/bin/ffmpeg -threads 4 -i "$1" -deinterlace -threads 0 -r 29.97 \
                -vcodec libtheora  -s 960x540 -b 1000kb -aspect 16:9 \
                -flags +loop -cmp +chroma \
                -deblockalpha 0 -deblockbeta 0 \
                -b 3000k -maxrate 5000k -bufsize 4M -bt 256k -refs 1 -bf 3 \
                -coder 1 -me_method umh -me_range 16 -subq 7 \
                -partitions +parti4x4+parti8x8+partp8x8+partb8x8 \
                -g 250 -keyint_min 25 -level 30 -qmin 10 -qmax 51 -qcomp 0.6 \
                -b_strategy 2 \
                -trellis 2 -sc_threshold 40 -i_qfactor 0.71 \
                -acodec libvorbis -ab 160kb -ar 44100 -ac 2 \
                "$OUTPUT_DIR/$2.ogv"
echo "Completed... results file saved to $OUTPUT_DIR/$2.ogv"
echo "Press Enter to Continue"
read dumbyvar


Convert to MP4/AAC

hd2mp4 script

#!/bin/bash
#
#  This script requires 2 parameters on the commandline
#    1 - is the file to convert
#    2 - is the output filename (without the mp4 extension)
#
#  NOTES:
#   - It is a 2-pass conversion (SLOW but VERY good quality)
#   - the result size and bitrates are hardcoded into the commands below
#   - AUDIO line can also be     -acodec libfaac -ab 152kb -ar 48000 -ac 2 -an \
#       OR -acodec copy
#   - the -an option specifies NO audio   to be used only on 1st pass
#   - the vframes 500 option specifies how many frames to do (ie do 500 to test)
#      leave it out to do all
#   - a -ss 245 starts at 245 seconds  so with ss and vframses  you can crop the video
#     **** I had troubles with the placement of the  -vframes 500
#     I got it working if it is on the last line as follows:
#          -acodec libfaac -ab 152kb -ar 48000 -ac 2 \
#          -ss 245 -vframes 500 -passlogfile "$1.log" -pass 2  "$OUTPUT_DIR/$2.mp4"
#   - if the size stays at 1920x1080 , the quantized can't get enough info with -qscale 1
#      use  -qmin 2 -qmax 31 instead
#
# Check these links:
#     http://www.itbroadcastanddigitalcinema.com/ffmpeg_howto.html
#     http://help.encoding.com/idx.php/16/126/article/libx264.html
#     http://rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide/
#
HD_SIZE=1920x1080
HALF_SIZE=960x540
HI_BITRATE=7000k
MID_BITRATE=5800k
HALF_BITRATE=3500k
#
OUTPUT_DIR=/home/tgutwin/Videos
SIZE=$HALF_SIZE
BITRATE=$HI_BITRATE
#
# see http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
#
#     -threads 0 casues a seg fault (use something else)
/usr/bin/ffmpeg -threads 4 -y -i "$1" \
                -deinterlace -f mp4 -r 29.97 \
                -vcodec libx264  -s $SIZE  -aspect 16:9 \
                -flags +loop -cmp +chroma \
                -deblockalpha 0 -deblockbeta 0 \
                -b $BITRATE -minrate 2500k -maxrate 25000k -bufsize 4M -bt 256k -refs 1 -bf 3 \
                -coder 1  -subq 7 \
                -partitions +parti4x4+parti8x8+partp8x8+partb8x8 \
                -me_method umh -me_range 20 -mbd rd \
                -g 250 -keyint_min 25 -level 30 -qmin 2 -qmax 26 -qcomp 0.6 \
                -b_strategy 2 \
                -trellis 2 -sc_threshold 40 -i_qfactor 0.71 \
                -acodec libfaac -ab 152kb -ar 48000 -ac 2 -an \
                -passlogfile "$1.log" -pass 1  -y /dev/null
/usr/bin/ffmpeg -threads 4 -y -i "$1"  \
                -deinterlace -f mp4 -r 29.97 \
                -vcodec libx264  -s $SIZE -aspect 16:9 \
                -flags +loop -cmp +chroma \
                -deblockalpha 0 -deblockbeta 0 \
                -b $BITRATE -minrate 2500k -maxrate 25000k -bufsize 4M -bt 256k -refs 1 -bf 3 \
                -coder 1 -subq 7 \
                -partitions +parti4x4+parti8x8+partp8x8+partb8x8 \
                -me_method umh -me_range 20  -mbd rd \
                -g 250 -keyint_min 25 -level 30 -qmin 2 -qmax 26 -qcomp 0.6 \
                -b_strategy 2 \
                -trellis 2 -sc_threshold 40 -i_qfactor 0.71 \
                -acodec libfaac -ab 152kb -ar 48000 -ac 2 \
                -passlogfile "$1.log" -pass 2  "$OUTPUT_DIR/$2.mp4"
echo "Completed... results file saved to $OUTPUT_DIR/$2.mp4"
echo "Press Enter to Continue"
read dumbyvar


By the way, I had to build ffmpeg from source because the Ubuntu binary did not have all the codecs compiled in.
If you don't have the lib files for some of the codecs, the configure command will tell you and you will have to compile them before the below ffmpeg configure will complete without errors.

svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk trunk
cd trunk

This configure line worked for me on my i7 64 bit computer...
    ./configure --prefix=/usr --enable-libfaac --enable-runtime-cpudetect --enable-nonfree --enable-avfilter  --enable-pthreads --enable-x11grab  --enable-libmp3lame  --enable-libopenjpeg   --enable-libspeex  --enable-libtheora --enable-libvorbis   --enable-libx264  --enable-libxvid --enable-zlib  --disable-armv6 --disable-armv5te  --disable-armvfp  --enable-sram --enable-gpl --enable-libfaad --arch=ia64

    make -j 4
    sudo make install
If you get a compiler seg fault  try the make without the -j 4 (wich means how many concurrent trheads to build with)
I found sometimes the multi-threaded build was not stable.

You will also need to 1st build the x264 codec.
Go to a nice new clean directory and get the latest version of the source

Get git first:
     sudo apt-get install git-core

Then get to code:
     git clone git://git.videolan.org/x264.git


You will also need these first (and maybe some others):
     sudo apt-get install libavcodec-dev yasm  libavutil-dev libpostproc-dev libbz2-dev libgpac-dev libxvidcore4-dev

Then build x264 with:
    ./configure --enable-pthread --enable-avs-input --enable-mp4-output --enable-ffms-input --enable-lavf-input --prefix=/usr --enable-shared
    make -j 4
    sudo make install


Comments