[笔记]低码率H.264视频心得
从86那接了点私活,大体上就是帮某些有需求的客户做些适合于streaming的视频。由于Target platform是flash v10搭载的电脑,于是那个老掉牙恶心死人的VP6/7就被我直接pass了,由于有文件大小的要求这个问题最终演化成了一个低码率H.264视频的实践问题。由于组里的480p双兼容mp4也算是典型的低码率应用,所以略作些整理吧。对我而言,perferred的toolchain是avisynth+x264+ffmpeg,当然我不用ffmpeg编码,只是拿来mux flv而已。
首先来看Video部分,avisynth+x264的黄金搭档也正是我最熟悉的两个工具。考虑到处理的视频大多都是实写(PAL),因此avisynth中只需要稍微做点降噪,再来点锐化就好了。我选择的方案是dfttest+LSFmod,dfttest用默认参数轻轻一抹,LSFmod的参数上也尽量做到柔和即可。此处值得注意的是由于最终目标码率很低(<250k@CIF),因此任何锐化(High Emphasis)的操作都可能会导致最终产品的画面布满玻璃渣,所以锐化滤镜的选择和参数的使用需要特别注意。我的LSFmod里strength只用了55。
源滤镜是处理这种千奇百怪视频的重要绊脚石,好在有ffmpegsource2这种通吃滤镜,什么VFR我才不管呢,反正都是PAL的实写,统统喂给它就能搞定了。只是要注意有时候源是yuv444的,所以出现奇数分辨率也一点都不奇怪了。
下面来看x264的参数,我的理念是在bitrate budgets下获得最好的(主观)质量,因此基本的rc方案毫无疑问的使用了1pass CRF+2pass Bitrate的方法。这样既能控制最终码率,又不至于被码率限死而影响质量。好在这个任务没有对播放端的解码延迟有什么要求,于是可以尽情的用些容易导致latency的参数了。
在确定rc方案之后,下面就是挑出一些参数来做优化了。我把参数的优化分成五个部分:ME、降码率、除块、帧类型、兼容性。
//顺便一说,我用的--crf 20的1pass。
首先是me,由于低码率的限制,精确的me(与之相对是更小的误差值)是必不可少的,相反在码率很充足的情况下me的精确性到来的不是那么重要了。我使用的是--me tesa --subme 10 --trellis 2 --merange 48的方案,tesa保证了尽可能精确的ME,subme 10保证了子块预测/细化时的准确性,merange 48相对于CIF来说也足够大了。
其次是码率的控制,开大mbtree的lookahead和降低qcomp数值是一个好方法,我是用的是--rc-lookahead 100 --qcomp 0.5的配置。有人可能会提到aq-mode 2,但我实际的感觉,aq-mode 2在这种极低的码率环境下会出现恼人的mosaic effect,所以aq-mode还是坚持使用mode 1,strength=1.0的默认设置吧。
然后是除块的参数,在前面avisynth的参数选择上我就说了锐化参数必须小心,x264里关于锐化/除块的参数有二,psy-rd和deblock。psy-rd的strength越高,玻璃渣就越明显(低码率下),deblock的负值则被认为有助于恢复锐利的线条和texture。所以对我这种环境,两者的效果都应该降低。我选择的是--psy-rd 0.2:0 --deblock 1:1的配置。
最后是帧类型和兼容性,这两个分类间相互的依赖性比较大,因此联合起来考虑。对流媒体而言,考虑到分辨率的大小,--profile main --level 3.0的设置足矣。ref 3和bframes 8则完全是个人喜好,如果要ep的话bframes 16也是可以的。--partitions b8x8,p8x8,i4x4,i8x8也是个人喜好,而且在level=3.0时这也就等于all了,我没有考虑把i8x8排除在外,因为target platform是标准终端因此没有必要。
vbv-bufsize和maxrate完全是为了限制1pass crf可能的飚码率问题,我定在了1600和1200。keyint和min-keyint则是一如既往的fps*10和1的配置。
1pass完整参数如下:
x264 –profile main –level 3.0 –pass 1 –crf 20 –stats “proc.stats” –min-keyint 1 –keyint 250 –ref 3 –bframes 8 –b-adapt 2 –direct auto –partitions none –no-fast-pskip –no-dct-decimate –vbv-bufsize 1600 –vbv-maxrate 1200 –rc-lookahead 100 –qcomp 0.5 –psy-rd 0.2:0 –deblock 1:1 –me tesa –merange 48 –subme 10 –trellis 2 –sar 1:1 –thread-input –threads 6 -o NUL proc.avs
2pass的完整参数如下:
x264 --profile main --level 3.0 --pass 2 --bitrate 340 --stats "proc.stats" --min-keyint 1 --keyint 250 --ref 3 --bframes 8 --b-adapt 2 --direct auto --partitions b8x8,p8x8,i8x8,i4x4 --no-fast-pskip --no-dct-decimate --vbv-bufsize 1600 --vbv-maxrate 1200 --rc-lookahead 100 --qcomp 0.5 --psy-rd 0.2:0 --deblock 1:1 --me tesa --merange 48 --subme 10 --trellis 2 --sar 1:1 --thread-input --threads 6 -o proc.264 proc.avs
在x264 rev.1376下实际跑的结果,crf 20的1pass在上述参数下基本码率不会超过400k,于是2pass的bitrate模式限制就比较宽松了。基本*0.75就能得到适合的2pass码率。
音频:
音频部分用ffmpeg处理,通用格式就是
ffmpeg -i somefile.ext -acodec libfaac -ab 64k oputfile.aac
有时ffmpeg的编译没有开启外部libfaac.dll的支持,解决方法要不就自己configure然后make要不就去找其他人编译的带libfaac支持的binary咯。
另外此处用的是average bitrate模式,也可以用-q这种质量模式,目标64kbps的音频q的数大约是0.25。
Mux:
继续ffmpeg:
ffmpeg -i somefile.mp4 -vcodec copy -acodec copy oputfile.flv
于是就大功告成了。

这个是压缩视频大小的教材么?果然很专业,我一般就用几个格式相互转换的傻瓜型工具…
[回复]
关于锐化和低码率的关系的说明让我有不少收获
降噪我都用FFT3DGPU,觉得dfttest好像慢很多
[回复]
Aki 回复:
二月 9th, 2010 at 2:07 下午
fft3dgpu/filter在某些texture比较重的画面上有奇怪的效果,所以我一般用都是2pass
这种实写的话觉得随便抹抹就行了,所以直接用默认参数的dfttest
速度一直不是我考虑的问题,我家的Q9550压这个CIF的东西单pass的速度也不会超过20fps
[回复]
先回LS:dfttest的多线程支持比fft3dfilter好很多(ncpu开到core数,dfttest在我的i7上比fft3dfilter快多了,但在本本上速度差不多);当然只要你显卡还行的话,dfttest比fft3dgpu还是慢的(不过,在我的i7+9800GT上,fft3dgpu优势并不是很明显,或许是9800GT还不够强吧)。
不过我倒觉得默认参数的dfttest很强啊,默认我记得是1.7吧,应该是比较强的降噪了。秋月姐姐如果只是想随便打打的话我觉得RemoveGrain+Repair这种就够了……
顺便一提,faac在64k码率上应一塌糊涂才对啊……我以前给VOD做的时候都是用NDAAC或者CTAAC的。64k即使Lame也能干掉faac。再一提,faac的q=0.25应该不是64k(我印象中大概是q=50吧),倒是NDAAC的q=0.25是64k……
[回复]
ssnake 回复:
二月 10th, 2010 at 2:41 上午
@ssnake, 第二段 默认->默认sigma
[回复]
admin 回复:
二月 10th, 2010 at 1:08 下午
广告这种东西一塌糊涂就行了-.-
dfttest我觉得同样sigma下比fft3d系列要弱,所以就用了。
[回复]
ssnake 回复:
二月 10th, 2010 at 1:49 下午
@admin, 弱降噪在我的理解里是dfttest的sigma=1.0以下= =
顺便为啥验证码永远是FIREHOOH。。
[回复]
admin 回复:
二月 10th, 2010 at 1:52 下午
custom spam keyword而已 完全是自己输入的pseudorandom序列