Video Encoding for Online HD

Posted: May 21st, 2011 | Author: | Filed under: computing | Tags: , , , , | No Comments »

Goal: To emulate the YouTube 720p HD video encoding settings to use as a baseline for encoding my own HD vids for use with a player on my own site. YouTube’s 720p encoding seems to be a good balance between filesize and quality. The various built-in render profiles I tested in kdenlive (v0.8) did not seem to have the same efficiency.

NOTE: This is not a guide to the best settings for uploading video to YouTube, this a guide for emulating the encoding process YouTube uses in creating HD video.

YouTube testing process:
1) Uploaded a 441M mp4 (960×720 H.264 8000k) to YouTube. Original source mp4 was from GoPro HD at 960p (1280×960) then spliced, edited and scaled to 960×720 using kdenlive.

2) Downloaded the “720p HD” mp4 file that YouTube created from rendering my video.

3) Used mediainfo to analyze the downloaded 170.4M mp4 file:

$ mediainfo videofile.mp4
General
Complete name : videofile.mp4
Format : MPEG-4
Format profile : Base Media / Version 2
Codec ID : mp42
File size : 170 MiB
Duration : 7mn 34s
Overall bit rate : 3 144 Kbps
Encoded date :
Tagged date :
gsst :
gstd :
gssd :
gshh :

Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High@L3.1
Format settings, CABAC : Yes
Format settings, ReFrames : 1 frame
Format settings, GOP : M=1, N=60
Codec ID : avc1
Codec ID/Info : Advanced Video Coding
Duration : 7mn 34s
Bit rate mode : Variable
Bit rate : 2 986 Kbps
Maximum bit rate : 4 670 Kbps
Width : 960 pixels
Height : 720 pixels
Display aspect ratio : 4:3
Frame rate mode : Variable
Frame rate : 30.000 fps
Minimum frame rate : 29.412 fps
Maximum frame rate : 55.556 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.144
Stream size : 162 MiB (95%)
Tagged date :

Audio
ID : 2
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 40
Duration : 7mn 34s
Bit rate mode : Variable
Bit rate : 152 Kbps
Maximum bit rate : 178 Kbps
Channel(s) : 2 channels
Channel positions : Front: L R
Sampling rate : 44.1 KHz
Compression mode : Lossy
Stream size : 8.24 MiB (5%)
Title : (C) 2007 Google Inc. v08.13.2007.
Encoded date :
Tagged date :

Recreating:
1) After much tinkering I’ve found the following kdenlive options seem to provide nearly identical results. Use these to create a custom render profile:

Profile Name: Custom Web 960x720 3k (4:3) 2pass
Extension: mp4
Parameters: f=mp4 acodec=aac ab=160k ar=44100 vcodec=libx264 vpre=hq minrate=0 maxrate=5000k b=3000k coder=1 refs=1 g=60 s=920x720 aspect=%dar mbd=2 trellis=1 mv4=1 subq=7 qmin=10 qcomp=0.6 qdiff=4 qmax=51 pass=2

2) The resulting rendered video (using the same 441M source file) is nearly identical in size (170.5M for the kdenlive file vs 170.4M for the YouTube file) and in visual quality.

$ mediainfo kdenlivevideo.mp4
General
Complete name : kdenlivevideo.mp4
Format : MPEG-4
Format profile : Base Media
Codec ID : isom
File size : 170 MiB
Duration : 7mn 34s
Overall bit rate : 3 146 Kbps
Writing application : Lavf52.64.2

Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High@L3.1
Format settings, CABAC : Yes
Format settings, ReFrames : 2 frames
Format settings, GOP : M=1, N=60
Codec ID : avc1
Codec ID/Info : Advanced Video Coding
Duration : 7mn 34s
Bit rate mode : Variable
Bit rate : 3 000 Kbps
Width : 920 pixels
Height : 720 pixels
Display aspect ratio : 4:3
Frame rate mode : Constant
Frame rate : 30.000 fps
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.151
Stream size : 162 MiB (95%)
Writing library : x264 core 106 Ubuntu_2:0.106.1741-3
Encoding settings : cabac=1 / ref=1 / deblock=1:0:0 / analyse=0x3:0x113 / me=umh / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=0 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / constrained_intra=0 / bframes=3 / b_pyramid=0 / b_adapt=2 / b_bias=0 / direct=3 / weightb=1 / open_gop=0 / weightp=2 / keyint=60 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=2pass / mbtree=1 / bitrate=3000 / ratetol=1.3 / qcomp=0.60 / qpmin=10 / qpmax=51 / qpstep=4 / cplxblur=20.0 / qblur=0.5 / ip_ratio=1.41 / aq=1:1.00

Audio
ID : 2
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 40
Duration : 7mn 34s
Bit rate mode : Variable
Bit rate : 144 Kbps
Channel(s) : 2 channels
Channel positions : Front: L R
Sampling rate : 44.1 KHz
Compression mode : Lossy
Stream size : 7.70 MiB (5%)

3) The mp4 rendered by kdenlive is still not quite ready for online streaming as the index remains at the video’s end (google “moov atom” for more info). This means the video will not start playing in an online player like JW Player until the entire file is downloaded into buffer. To fix this, I used a handy tool called MP4Box (apt-get install gpac) to interleave the index info through the video file. Note that this will operate directly on the file you specify so you may want to create a copy of the original first.

$ MP4Box -inter 500 kdenlivevideo.mp4

Thoughts:
* YouTube is either using some other encoder than ffmpeg or has hacked it to write custom metadata, but again, the video output is nearly identical.
* I’m not sure why YouTube’s encoder uses variable frame rates. The source file is a constant frame rate and ffmpeg retains this by default.
* The same thing can be accomplished using ffmpeg from the CLI without the kdenlive front end; just convert the parameters from the render profile to the ffmpeg switch format.

References:
* Kdenlive -- http://www.kdenlive.org/
* FFmpeg -- “man ffmpeg” and “ffmpeg -h”
* FFmpeg Docs -- http://ffmpeg.org/ffmpeg-doc.html
* FFmpeg / x264 mapping -- http://sites.google.com/site/linuxencoding/x264-ffmpeg-mapping
* FFmpeg preset profiles -- http://juliensimon.blogspot.com/2009/01/howto-ffmpeg-x264-presets.html
* MP4Box -- http://gpac.wp.mines-telecom.fr/mp4box/