Creating good quality h264 video for the upcoming Flash Player and Flash Media Server

Important

This tutorial has been updated (and improved) a lot, for the new version please follow this link.

UPDATE: I realized that when i read a tutorial about anything, in most cases, i want to first see what result im going to get so then i can decide if the tutorial is worth reading (or not), so here is a head by head comparison: 

This is an h264 file encoded by the guys at apple.com, it’s the TV Commercial for the brand new iMac: ORIGINAL VIDEO

This is the same file re-encoded using the steps on this tutorial: RE-ENCODED VIDEO

Obviouisly, there is an small quality degradation, but keep in mind that apple’s original movie is 14MB in size, while mine is 1.5MB ;).
You can play my MP4 video with almost any video player out there, but remember that not all video players out there support HE-AAC audio (or aacPlus) and b-frames, so if you play the file with a player like QuickTime, it is NOT going to work.
I recommend mPlayer or VLC media player to play this kind of video, and obviously, Flash Player will play the file perfectly too.

Update for Macintosh users:

I updated the bash script on this post so it can be used also by Macintosh users, so instead of using the NERO Digital AAC Encoder, Macintosh users can take advantage of the native 3GPP AAC Plus V2 encoder that i just compiled. Visit this post for more information about it.

Like a lot of people out there, i was really happy when i found the press release from Adobe, stating the addition of h.264 video support and HE-AAC Plus audio to their upcoming Flash Player versions, and also, to the upcoming Flash Media Server.
After following several “Tutorials” all over the web, i found that there was not any single one that gave me the results that i wanted; that is, good video quality, with the less possible file size, so after a lot of trial and error and after a lot of help and optimizations by the guys at the ffmpeg and x264 IRC channels, i decided to create this tutorial that will most probably help you a lot to encode good quality h264 video, with HE-AAC Plus Audio, and all this inside an MP4 container with tags and all ready to deliver to your visitors.

There are several things that you will need in order to do this:

Some friendly bookmarks:
SVN checkout for x264:
svn checkout svn://svn.videolan.org/vlc/trunk vlc-trunk
SVN checkout for ffmpeg:
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg

First of all, I’m assuming that you are running Linux, Mac-OS X or any other UNIX variant. I never tried this on windows because I am pretty sure that there are lot of really nice programs that you could buy to do the job.

Step 1: Configuring, compiling and installing all the stuff.

I am assuming that you have some basic skills with Linux / Unix / Mac OS, so i won’t really digg into the details of how to compile from sources all the tools. In most cases just taking a look at the readme file for each piece of software will tell you all you need to know, so i will just explain here some basical tips that you need to know.
After configuring, building and installing the x264 codec, this is the configure line that i used for ffmpeg in my paticular case:

./configure --enable-libx264 --enable-libfaac --enable-gpl --prefix=/usr --enable-libfaad --enable-swscaler --enable-pp

All the settings there are self-explanatory, the only thing you could need to change is the prefix to something like –prefix=/home/yourusername/ if you prefer to install the software just for your own user account.
After you have ffmpeg installed and running, we need to install two more things, the GPAC utilities and the Nero Digital AAC Audio Encoder.
Go grab the latest sources for GPAC, do the usual:

./configure && make && make install

After that you are ready to go, then go and download the latest version of the Nero encoder, and you will notice a directory called “linux” inside it, you should copy all the files there to any location in your path, usually /usr/bin (if you are installing everything as root) or /home/yourusername/bin (if you are installing just for your user account).

Step 2: Checking that everything is working as supposed.

To check that everything is ok, you should type:

ffmpeg -formats

and you will get a LONG list of supported encoders and decoders, if you have the following line, you are ready to go:

EV libx264

Step 3: Doing the video encoding (or transcoding).

So everthing looks great so far, except for one little detail, there is actually no support for any HE-AAC encoder directly from inside ffmpeg, so we will do the encode in 2 phrases, first the video, and then the audio.

From now on, i will assume that we have a video called “movie.avi” that we want to convert to a Flash Ready h264 file, so lets start encoding the video.
I am a person who likes quality, so for this example I am going to use a 2 pass encoding process.

This is the command line to perform the first pass of the video encoding:

ffmpeg -y -i movie.avi -an -pass 1 -vcodec libx264 -b 384k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me umh -subq 5 -trellis 1 -refs 3 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 384k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.8 -qmin 10 -qmax 51 -qdiff 4 movie_temp.mp4

Depending on how long is your video source and how powerful is your computer, after some minutes it should finish, so it is time to make the second pass of the video encoding:

ffmpeg -y -i movie.avi -an -pass 2 -vcodec libx264 -b 384k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me umh -subq 5 -trellis 1 -refs 3 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 384k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.8 -qmin 10 -qmax 51 -qdiff 4 movie_temp.mp4

This pass is gonna take more time than the first one, because the first one just analyzes the video while the 2nd pass does the actual encoding.

IF everything went as supposed, after some time you should have a new file called “movie_temp.mp4” and you will notice that it is just your movie, but without sound…. dont alarm! we are going to make the sound part right now.

Step 4: Doing the audio encoding.

This part is pretty simple, we will use ffmpeg to create a simple wav file because the nero encoder only accepts a wav file as input, so we will do:

ffmpeg -i movie.avi -ar 48000 -ac 2 movie_temp_audio.wav

After this finishes, you will have a wav file called “movie_temp_audio.wav” that should be playable in any audio player of your choice, it basically contains the audio of your movie, so let’s transform this to a shiny HE-AAC Plus audio file.

To convert the wav audio file into an HE-AAC Plus file, we will use the Nero Encoder (neroAacEnc) and we will tell it to use our recently created wav file as source and output it to a new audio only mp4 file called “movie_temp_audio.mp4” like this:

neroAacEnc -br 48000 -he -if movie_temp_audio.wav -of movie_temp_audio.mp4

So ok, we have at this point one MP4 file with just video, and another MP4 file with just audio, lets mux all this into our final flash ready MP4.

Step 5: Muxing everything into our final MP4 file ready for Flash broadcast.

At this point we are going to use a program called “MP4Box” that is part of the GPAC utilities that you have already installed if you followed my instructions.

First, we will command MP4Box to add ONLY the video track of our first video only MP4 into our final MP4:

MP4Box -add movie_temp.mp4#video final_movie.mp4

This will create a new MP4 file called “final_movie.mp4”, and it will add our video track inside it. Now we need to add the audio track into our final movie file, to do that we do as follows:

MP4Box -add movie_temp_audio.mp4#audio final_movie.mp4

After this step, if you open your “final_movie.mp4” file with some video player like QuickTime, mPlayer or VLC, you should have a brand new h264 file with both video and audio, and with perfect sync between the two.
We need now to do some extra steps to optimize the file for progressive HTTP streaming so the flash player doesn’t needs to download the whole file before starting to play it, so lets interleave our file:

MP4Box -inter 500 final_movie.mp4

This line will interleave meta information to the file every 500 msec, that way, the flash player will be able to play the file as soon as it gets the first 500msec of video data.

After you are satisfied with your result, you can simply type:

rm movie_temp* -f

to get rid of all the temporal files that you created.

Obviously, this involves a LOT of steps in order to create the final file, and it is good to make them one by one so you get an idea of what are you doing…. after all, the idea is to learn…. isn’t it ?
But as you may suppose, the logical step after doing the “manual” way, is to create a bash script that is gonna do everything for us, so i give you below, an example of how this script could look:

#! /bin/bash
# ${foo%.*} to remove the extension
# FIRST PASS
echo "Starting Pass 1 ! ! !"

ffmpeg -y -i $1 -an -pass 1 -vcodec libx264 -b 384k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me umh -subq 5 -trellis 1 -refs 3 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 384k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.8 -qmin 10 -qmax 51 -qdiff 4 ${1%.*}_temp.mp4

# SECOND PASS
echo "Starting pass 2 ! ! !"

ffmpeg -y -i $1 -an -pass 2 -vcodec libx264 -b 384k -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +mixed_refs -me umh -subq 5 -trellis 1 -refs 3 -bf 3 -b_strategy 1 -coder 1 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 384k -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.8 -qmin 10 -qmax 51 -qdiff 4 ${1%.*}_temp.mp4

# Exporting audio to a temporal 48k WAVE file
ffmpeg -y -i $1 -ar 48000 -ac 2 ${1%.*}_temp_audio.wav

# Encoding audio to HE-AAC V2 (aacPlus SBR + PS) -- UNCOMMENT THE FOLLOWING LINE on LINUX / UNIX with the NERO encoder
neroAacEnc -br 48000 -he -if ${1%.*}_temp_audio.wav -of ${1%.*}_temp_audio.mp4

# Encoding audio to HE-AAC V2 (aacPlus SBR + PS) -- UNCOMMENT THE FOLLOWING LINE on Mac OS X and remember to comment the LINUX one:
# enhAacPlusEnc ${1%.*}_temp_audio.wav ${1%.*}_temp_audio.aac 48000 s

#Creates final MP4 container and adds video track...
MP4Box -add "${1%.*}_temp.mp4#video" ${1%.*}_flash_ready.mp4

#Adds audio track...
# IMPORTANT: If running this script on LINUX, UNCOMMENT THIS line:
MP4Box -add "${1%.*}_temp_audio.mp4#audio" ${1%.*}_flash_ready.mp4

# IMPORTANT:if running this script on a MAC, UNCOMMENT THIS line and remember to comment the LINUX one:
#MP4Box -add "${1%.*}_temp_audio.aac" ${1%.*}_flash_ready.mp4 

#Sets MetaData...
MP4Box -lang English ${1%.*}_flash_ready.mp4

#Interleaving (For HTTP Streming... this should be removed if using FMS / RTMP )
MP4Box -inter 500 ${1%.*}_flash_ready.mp4

echo "Deleting Temporary Files..."
rm ${1%.*}_temp* *.log -f

echo "DONE!"
echo "Your file has been encoded as ${1%.*}_flash_ready.mp4"

You should make a file called, for example, mkmp4.sh and paste the script inside it, then chmod +x the file and move it to /usr/bin , after that, you should be able to run for example:

mkmp4 mymovie.avi

and the bash script will create a new file called mymovie_flash_ready.mp4 in the same directory, that assuming that you have all the needed tools in the path.

So happy encoding! if you have any questions or any problem, please post a comment here and i will try to help you as soon as i can. Please avoid to post questions about how to build / configure / compile software because i don’t really have the time to help you with that and there are a lot of tutorials for that on the web, and like i said, this tutorial assumes that you have the basic linux skills already inside your little brain.


28 Responses to “Creating good quality h264 video for the upcoming Flash Player and Flash Media Server”

  1. *faps over Guide*

    by texta, September 29th, 2007 at 8:37 am


  2. *does also*

    by Fucktard, September 29th, 2007 at 8:39 am


  3. Awesome guide Diego! The bash script, commands and the links are much appreciated.

    :)

    by joe75, September 29th, 2007 at 10:15 am


  4. Hey thanks for the comments, im glad that you find this tutorial useful. :)

    by Diego Massanti, September 29th, 2007 at 11:45 am


  5. Hello. On my PC, your “new_imac_2007.mp4” always crash my QT player at 3 sec (last QT version).

    by jer, October 1st, 2007 at 4:16 am


  6. Yah i forgot to update the guide to reflect that, i changed some settings on the h264 encoding (specifically, the use of more than 1 b-frame), and quicktime doesn’t likes that. Since this guide is aimed at encoding video for flash broadcasting, i think its not important at all.
    Sadly, quicktime is a great player but comes with a really poor inplementation of the h264 / AVC standard :(. Try any compliant player like VLC or mPlayer and its gonna work ;).

    by Diego Massanti, October 1st, 2007 at 4:10 pm


  7. thx Diego for the greate article !

    i have one question
    i use only one pass ( without -pass option) is it possible to make this faster ? i have a 15 min video and to encode i takes 15 min :-( on a intel dual core 2,3GH 1GB RAM

    you know some options to make things faster ?
    i found the threads option in ffmpeg i user -threads 2 but i do not know this helps

    thx a lot

    by whwi, October 5th, 2007 at 10:17 am


  8. whwi:

    Encoding h.264 requries a lot of processing power by nature, im working on a different guide for the people who doesn’t cares at all about the final quality, but i need to try the settings before i release the guide. You could try a google serch too, there are lots of tutorials for x264.

    Regarding the threads issue, i assume that you enabled threading for bot ffmpeg and x264 when you compiled…. right ? :p

    Cheers!

    by Diego Massanti, October 6th, 2007 at 3:30 pm


  9. Thanks ALOT for this guide, I’ve been fiddling with mencoder forever just to read here that only nero is able to encode AAC-HE…

    However, for me it’s -vcodec h264 with ffmpeg (Compiled it with portage on gentoo).

    I compiled with both gcc3.4 and 4.1 and didn’t notice any difference in terms of encoding speed – it’s very slow with both binaries but the results are worth it.

    Anyway, thanks again! Exciting new technology.

    by Eric, October 18th, 2007 at 5:23 am


  10. It looks like this Nero codec is no longer available. I can find one for Windows but non for linux.

    by Martin, October 28th, 2007 at 8:04 am


  11. Diego, great tutorial, I am going through it right now. I am on mac, and ffmpeg configure complains that there faad test failed, so I am now downloading faad2.tar sources form audiocoding.com, let’s see how it goes ..

    but I am posting here to ask about a differnt thing: do you have any idea whether FinalCut Express will export mp4 suited to the h264-flashplayer ?

    by Roberto Saccon, November 22nd, 2007 at 11:52 pm


  12. commenting on my progress: faad2 can be installed via macports

    by Roberto Saccon, November 23rd, 2007 at 12:08 am


  13. bad, bad, bad, ffmpeg (on mac OS X 10.4.11) stopped compiling at:

    {standard input}:23693:symbol: “_put_vc1_mspel_mc00_mmx” can’t be undefined in a subtraction expression
    make[1]: *** [i386/dsputil_mmx.o] Error 1
    make: *** [lib] Error 2

    any tips on how to get ffmpeg compiling on mac OS X ???

    by Roberto Saccon, November 23rd, 2007 at 12:47 am


  14. and disabling mmx dosen’t help either, and ffmpeg from macports ha no libx264 and google today dosen’t help me either ..

    by Roberto Saccon, November 23rd, 2007 at 2:02 am


  15. I got a step further (just had forgotten to clean after ./configure without mmx …)

    I have now all the tools described here and in
    http://massanti.com/2007/09/30/he-aac-plus-encoder-mac-universal-binary/,
    all compiled from source on mac OS X 10.4.11

    Unfortunately I got stuck at step 5 part 2: here first what I did at step 4:

    > enhAacPlusEnc movie_temp_audio.wav movie_temp_audio.acc 48000 s

    *************************************************************
    * Enhanced aacPlus 3GPP Floating Point Reference Encoder
    * Build Sep 11 2007, 08:38:00
    *
    *************************************************************

    bDoIIR2Downsample = 1
    input file movie_temp_audio.wav:
    sr = 48000, nc = 2

    output file movie_temp_audio.acc:
    br = 48000 sr-OUT = 48000 nc-OUT = 2

    [100%]

    encoding finished

    then I did successfully step 5 part 1 and failed at part 2, adding the audio to the final movie:

    > /Users/rsaccon/opensource/gpac/bin/gcc/MP4Box -add movie_temp_audio.mp4#audio final_movie.mp4
    Unknown input file type
    Error importing movie_temp_audio.mp4#audio: End Of Stream / File

    here is how my media files look like:

    -rw-r–r– 1 rsaccon rsaccon 3941221 Nov 16 23:33 Original.mov
    -rw-r–r– 1 rsaccon rsaccon 0 Nov 23 14:28 ffmpeg2pass-0.log
    -rw-r–r– 1 rsaccon rsaccon 634632 Nov 23 14:57 final_movie.mp4
    -rw-r–r– 1 rsaccon rsaccon 636279 Nov 23 14:31 movie_temp.mp4
    -rw-r–r– 1 rsaccon rsaccon 340322 Nov 23 15:00 movie_temp_audio.mp4
    -rw-r–r– 1 rsaccon rsaccon 10592732 Nov 23 14:33 movie_temp_audio.wav
    -rw-r–r– 1 rsaccon rsaccon 50545 Nov 23 14:28 x264_2pass.log

    any idea what is wrong ?

    regards
    Roberto

    by Roberto Saccon, November 23rd, 2007 at 1:24 pm


  16. got it working ! Thanks again for thies great tutorial ! I just had a few little things by mistake different than in the script. There is just on question left: I am using this for screencasts and I want to loose as little quality as possible. With the current setting I get a four times smaller files, but also less video quality. Is it possible to get higher quality (at the price of higher filesize) ?

    by Roberto Saccon, November 24th, 2007 at 12:55 am


  17. Hello webmaster, I am glad I pressed harder enough until I found ac movie pass, because this post on ing good quality h264 video for the upcoming Flash Player and Flash Media Server was extremely helpful. Just last Friday I was pondering on this quite a bit.

    by Ac Movie Pass, December 14th, 2007 at 9:44 pm


  18. […] Creating good quality h264 video for the upcoming Flash Player and Flash Media Server i decided to create this tutorial that will most probably help you a lot to encode good quality h264 video, with HE-AAC Plus Audio, and all this inside an MP4 container with tags and all ready to deliver to your visitors. (tags: audio codec codecs compression document encoding ffmpeg flash video h264 mp4 tutorial flashplayer) […]

    by Federico Feroldi’s blog » Blog Archive » links for 2007-12-16, December 16th, 2007 at 4:21 pm


  19. I am planning to update this tutorial soon with better (and faster) settings that i have been trying in the last weeks, sorry for the lack of answers and updates, but my everyday work has been extreme in the past month.
    Keep an eye for a cool update soon.
    Diego.

    by Diego Massanti, December 17th, 2007 at 9:13 am


  20. Great! What if i would like to resize the video while encoding? is this possible?

    by armando, December 22nd, 2007 at 5:44 am


  21. @armando: yes it is possible, you need to use the -s parameter.
    For example, your command line would start like this:

    ffmpeg -y -i movie.avi -s 320×240 …..

    Just remember to put the -s command on both the first and second pass commands if you are using 2 pass encoding.
    Also, to everybody, a good way to get more speed with really little quality degradation is to use ” -subq 1 -trellis 0 “.
    Hope it helps.

    by Diego Massanti, December 22nd, 2007 at 1:09 pm


  22. […] was some months ago when I wrote a tutorial about how to encode good quality h.264 video with aacPlus audio in order to use the great capabilities of the new flash player version 9.0.115 (that in case you […]

    by Diego’s Rants » Encoding high quality h.264 / aacPlus v2 files for web streaming with Flash 9, version 2., January 1st, 2008 at 8:11 am


  23. Thanks. Great tutorial. I love the copy/paste bash script. Well done!

    by yure, January 13th, 2008 at 7:44 pm


  24. I’m getting FaacFaad failure on configure of ffmpeg

    ./configure –enable-libx264 –enable-libfaac –enable-gpl –prefix=/usr –enable-libfaad –enable-swscaler –enable-pp

    FAAD test failed.
    ERROR: libfaac not found

    So i have to first compile the AAC encoder and decoder seperately before compiling ffmpeg

    by MySchizoBuddy, February 5th, 2008 at 5:21 pm


  25. how would you compile x264 with build in support for gpac/mp4box

    by MySchizoBuddy, February 5th, 2008 at 11:28 pm


  26. Is there anyway to interleave the view with ffmpeg? — ffmpeg does all the other steps for me well enough except for interleaving and it would be great if there was some switch that does that not to depend on MP4box.

    by Bob, June 24th, 2008 at 12:18 am


  27. hai there,,
    anybody here know how to get input from TV turner with ffmpeg in windows? how can i get the device to define in ffmpeg?

    this is my configuration and example sintaks :
    1.Video codec MPEG-4, Simple Profile Level 1:
    Video Codec MPEG-4 SP
    Video Codec Level Automatic
    Video Mode Normal Motion Video
    Max Key Frame Distance 5000 ms
    Frame Rate 10 fps
    Picture Size (Frame Resolution) 176 x 220 pixel
    Packet Length 1000 Bytes
    Bit Rate 34 kbps, CBR
    2.Audio codec :
    Audio Codec AAC-LC
    Bit Rate (Sample Size) 16 kbps
    Channel Mode Mono
    Frekwensi Rate 22.050 kHz

    Input : TV Turner
    Max duration : 1 second
    Max File Size : 7 KB, 9 KB, 11 KB
    =====================

    ffmpeg -g 3 -i E:\wmvideo.wmv -vcodec mpeg4 -b 34k -r 10 -bf 2 -acodec libfaac -ar 8000 -ab 16k -ac 1 -s 176×220 -ss 0 -t 1 -y -fs 7000 -f 3gp tes0.3gp

    the problem is :
    -fs 7000 –> not work, can get output 7KB
    -i E:\wmvideo.wmv –> change this to TV turner source

    thank u for your help..
    best regard
    -adek aidi-

    by adek, July 20th, 2008 at 4:45 am


  28. mp4box 0.4.5 can compiled as a universal binary for osx leopard? I have not seen (or been able to accomplish) this.

    by chuck, December 15th, 2008 at 7:58 pm