gnaggnoyil
gnaggnoyil

在綫視頻不被拉伸的視頻Resize方法(H264向)(32位win平臺,linux用戶請自行改變對應設置)

①編寫AVS腳本函數,把視頻自動加黑邊之後再將視頻resize至4:3或者16:9的分辨率,比如512*288或者512*384神馬的.


裡提供一個AutoAddBoader()腳本函數,有三個參數,視頻片段clip,目標寬度w和目標高度h.這個函數可以在給定的resize分辨率下
將視頻自動保持比例resize然後加黑邊,類似于MC的expand to fit.目前只對YV12,YUY2顏色空間的視頻有效.

#AutoAddBorders

function AutoAddBorders(clip clip, int "w", int "h")
{
#默认值
w = Default(w, 512)
h = Default(h, 384)
#检测用
clip_w = clip.width()
clip_h = clip.height()
FC = clip.Framecount()
FN = clip.Frameratenumerator()
FD = clip.Frameratedenominator()
pixel_type =
\ clip.EPCS == "YV12" ? "YV12" :
\ clip.EPCS == "YUY2" ? "YUY2" :
\ MessageClip("目前只支持YV12,YUY2", text_color=$ff0000)
#计算resize宽高
rh = Round(Float(w)/Float(clip_w)*clip_h)
rhh = (rh%2 == 0) ? rh : rh + 1
rw = Round(Float(h)/Float(clip_h)*clip_w)
rww = (rw%2 == 0) ? rw : rw +1
#resize判断
clip_rs =
\ (Float(clip_w)/Float(clip_h) > Float(w)/Float(h)) ? clip.Spline64Resize(w,rhh) :
\ (Float(clip_w)/Float(clip_h) < Float(w)/Float(h)) ? clip.Spline64Resize(rww,h) :
\ (Float(clip_w)/Float(clip_h) == Float(w)/Float(h)) ? clip.Spline64Resize(w,h) :
\ MessageClip("unknow error(clip_rs)", text_color=$ff0000)
#垫底用黑边
blank = blankclip(length=FC,width=w,height=h,pixel_type=pixel_type,fps=FN,fps_denominator=FD).KillAudio
#检测用
rsw = clip_rs.width()
rsh = clip_rs.height()
#定位判断
x = Round((w-rsw)/2)
y = Round((h-rsh)/2)
#overlay
over =
\ (Float(clip_w)/Float(clip_h) > Float(w)/Float(h)) ? Overlay(blank,clip_rs,x=0,y=y) :
\ (Float(clip_w)/Float(clip_h) < Float(w)/Float(h)) ? Overlay(blank,clip_rs,x=x,y=0) :
\ (Float(clip_w)/Float(clip_h) == Float(w)/Float(h)) ? clip_rs :
\ MessageClip("unknow error(over)", text_color=$ff0000)
return over
}
#EPColor_Space
function EPCS(clip clip)
{
WTCS =
\ (clip.IsYV12() == true ? "YV12" :
\ (clip.IsYUY2() == true ? "YUY2" :
\ (clip.IsRGB24() == true ? "RGB24" :
\ (clip.IsRGB32() == true ? "RGB32" :
\ "unkonw"))))
return WTCS
}

使用的時候將這段代碼保存為一個avsi文件,然後寫腳本的時候import下這個avsi文件就行……

使用示例:

Import("E:\Program Files\Video Files\AutoAddBorders.avsi")
DirectShowSource("E:\Program Files\Video Files\sm15744657.mp4", fps=21, convertfps=true)
width() % 2 == 1 ? AddBorders(0, 0, 1 ,0) : NOP()
height() % 2 == 1 ? AddBorders(0, 0, 0 ,1) : NOP()
ConvertToYV12()
AutoAddBorders(512,384)

順便說下由於VY12和YUY2要求寬和高必須是偶數,所以在ConvertToYV12()必須先預處理一下,在視頻寬和高是奇數的時候給視頻預先在邊緣加一道一像素寬的很細的黑邊.

之後就可以把這個avs喂給megui或者直接喂給x264了.壓制后封裝flv,上傳渣浪沒被拉伸(廢話),例子:http://video.sina.com.cn/v/b/62404736-1741909842.html

②使用x264自帶濾鏡功能

x264自帶濾鏡功能應該是09年暑假時候的事情了.應該現在流行的x264版本應該都支持使用x264自帶的resize濾鏡.

調用--fullhelp參數可以查看x264幫助文檔,這裡截取x264關於--vf中對resize濾鏡的介紹:

resize:[width,height][,sar][,fittobox][,csp][,method]
resizes frames based on the given criteria:
- resolution only: resizes and adapts sar to avoid stretching
- sar only: sets the sar and resizes to avoid stretching
- resolution and sar: resizes to given resolution and sets the sar
- fittobox: resizes the video based on the desired constraints
- width, height, both
- fittobox and sar: same as above except with specified sar
- csp: convert to the given csp. syntax: [name][:depth]
- valid csp names [keep current]: i420, yv12, nv12, i444, yv24, b
gr, bgra, rgb, i422
- depth: 8 or 16 bits per pixel [keep current]
note: not all depths are supported by all csps.
- method: use resizer method ["bicubic"]
- fastbilinear, bilinear, bicubic, experimental, point,
- area, bicublin, gauss, sinc, lanczos, spline


如我們可以使用--vf
resize:512,384,1:1,width,,lanczaos參數,在強制SAR為1:1(爲了避免上傳后在綫看時被拉伸)的情況下使用
lanczaos算法強制把寬度resize至512
pixels.第三個參數fittobox選擇width還是height取決於你原視頻的分辨率和你目標視頻的分辨率,但是無論如何,SAR設定為
1:1是肯定的.

例如,我們寫一個a.bat,內容為

x264.exe --pass 1 --preset medium
--tune animation --bitrate 500 --vf resize:512,384,1:1,width,,lanczaos
--min-keyint 1 --non-deterministic --ssim --stats
"sm15744657.mp4.1pass.states" --output NUL "sm15744657.mp4"
x264.exe
--pass 2 --preset medium --tune animation --bitrate 500 --vf
resize:512,384,1:1,width,,lanczaos --min-keyint 1 --non-deterministic
--ssim --stats "sm15744657.mp4.1pass.states" --output sm15744657-1.mp4
"sm15744657.mp4"

然後E:\Program Files\MeGUI\tools\x264>a執行這個bat.


會成功壓制.②法生成的視頻和①法生成的視頻在名義分辨率上不一樣.具體到這個例子,①法的縱向分辨率為384,②法的縱向分辨率為342.不過兩法生成
的視頻上傳后均不會被在綫播放器拉伸.②法的例子:http://video.sina.com.cn/v/b
/62405446-1741909842.html



這兩種方法目前還難說那種更好.有些工作必須,或者說常常需要經過
AVS來干.比如AVS腳本是現在內嵌字幕的最常用方法——當然不少神牛也在用direct264.因此使用AVS方法你可以在AVS腳本中干這些事情同
時resize.當然了,如果你的x264比較新(也不是需要特別新,我的x264用的是今年暑假里更新的2074版本表示木有問題)的話,x264會在
面對VFR(可變幀率)視頻的時候優先嘗試dms或者ffms方式來解,保證進去的是VFR出來的還是VFR.MC面對VFR會Error
19,AVS要想正常工作必須保證輸出是CFR(恒定幀率).這兩種情況下要是硬壓制硬上去封裝flv的話結果就是視頻和音頻的不同步.此時需要
resize的話毫無疑問需要使用x264的自帶濾鏡.