Encoding Smooth Streaming videos

back


GUI

Commandline

Do it yourself

If you like to DIY then you probably want to read the previous FFmpeg article. The remaining of this article was written when FFmpeg didn't yet support the no-mbtree flag for X264.

The ins & outs

Our demo video is Blender's Big Buck Bunny. Using the original 1080p HD source file (big_buck_bunny_1080p_h264.mov) we need to create the following list of files for Smooth Streaming:

FilenameDescription
bbb.ismThe server manifest file
bbb.ismcThe client manifest file
bbb_4500.ismvThe video/audio track in fragmented MP4 format
bbb_2008.ismvThe video track in fragmented MP4 format
bbb_896.ismvThe video track in fragmented MP4 format
bbb_400.ismvThe video track in fragmented MP4 format

To achieve this we will be using the following tools:

ProgramDownload link
X264http://x264.nl/
AVISynthhttp://sourceforge.net/projects/avisynth2/files/
mencoderhttp://www.mplayerhq.hu/design7/dload.html
MP4Creatorhttp://mp4creator.sourceforge.net/
mp4splithttp://smoothstreaming.code-shop.com

Encoding multi bit rate H264 video with X264

The important part when generating multiple bit rate video files is that the chunks need to be aligned on exactly the same (key-)frames. The X264 encoder provides a two-pass encoding option. The output of the first pass is used for all the second pass encodings, this way we make sure that the keyframes are aligned.

A good balance between efficiency and switching latency is to insert keyframes every 2 seconds (--min-keyint) with a maximum of 4 seconds (--keyint).

The original movie is 1920 x 1080 (1080p / full HD) and using the Smooth Streaming Multi-Bitrate Calculator gives us the following table:

Bit rate (Kbps)Resolution
45001920 x 1080
20081096 x 616
896624 x 352
400356 x 200

The example below generates 4 encodings in 4500, 2008, 896 and 400 Kbps.

set X264_OPTIONS=--threads auto --min-keyint 50 --keyint 100 --bframes 3 --ref 3 --no-mbtree
x264 %X264_OPTIONS -o bbb_4500.mp4 --pass 1 --bitrate 4500 bbb0.avs
x264 %X264_OPTIONS -o bbb_4500.mp4 --pass 2 --bitrate 4500 bbb0.avs
x264 %X264_OPTIONS -o bbb_2008.mp4 --pass 2 --bitrate 2008 bbb1.avs
x264 %X264_OPTIONS -o bbb_896.mp4 --pass 2 --bitrate 896 bbb2.avs
x264 %X264_OPTIONS -o bbb_400.mp4 --pass 2 --bitrate 400 bbb3.avs

The input files are AVISynth scripts. The first bbb0.avs script loads the video, the second bbb.avs script rescales the video to a lower resolution, the third bbb.avs rescales the video even further, etc...

bbb1.avs

QTInput("big_buck_bunny_1080p_h264.mov", audio=false)
BicubicResize(1096, 616)
ConvertToYV12()

Thanks to Dark Shikari for the two pass idea.

Encoding AAC audio

mencoder "big_buck_bunny_1080p_h264.mov" -ovc frameno -oac faac -faacopts br=192:mpeg=4:object=2 -channels 2 -srate 48000 -of lavf -o bbb.aac

Mux the AAC audio with one of the video streams

MP4Creator -create=bbb.aac bbb_4500.mp4
MP4Creator -optimize bbb_4500.mp4

Pre-fragmenting the MP4 file

The transcoded MP4 files need to be pre-processed to Fragmented MPEG4 to allow for fast random access to the fragments.

mp4split -o "bbb_4500.ismv" "bbb_4500.mp4"
mp4split -o "bbb_2008.ismv" "bbb_2008.mp4"
mp4split -o "bbb_896.ismv" "bbb_896.mp4" 
mp4split -o "bbb_400.ismv" "bbb_400.mp4"

Generating the server and client manifest

mp4split -o "bbb.ism" "bbb_4500.ismv" "bbb_2008.ismv" "bbb_896.ismv" "bbb_400.ismv"
mp4split -o "bbb.ismc" "bbb_4500.ismv" "bbb_2008.ismv" "bbb_896.ismv" "bbb_400.ismv"

Publishing / Deploying

DEPLOY_DIR=$(DOCUMENT_DIR)/bbb.ssm
mkdir $(DEPLOY_DIR)
cp bbb_*.ismv $(DEPLOY_DIR)
cp bbb.ism $(DEPLOY_DIR)
cp bbb.ismc $(DEPLOY_DIR)