论坛风格切换切换到宽版
» 您尚未 登錄  注冊
  • 3715阅读
  • 1回复

如何处理120FPS的AVI片源 与 VFR的制作 [复制链接]

上一主题 下一主题
 
只看楼主 倒序阅读 0 发表于: 2010-08-14
首先是处理120FPS的AVI RAWS




  在内嵌的时候,经常会遇到一些很奇怪的片源。这些片源大小和普通片源看起来没什么差别,可是压缩的时候几个小时都完不成,好不容易等死等活地等完了,发现播放的时候不是卡卡的就是CPU吃了100%甚至就来“发送错误报告”了。究其原因,在打开片源的时候多留一个心眼儿,发现这个片源的FPS有点诡异(注:FPS指的是帧速率,就是每秒钟显示几张图)。
  看到了吗?这个FPS是119.88,也就是所谓的120fps了。事实上,这个视频文件不是真的每秒钟播放120张图,也是和普通的片源一样每秒钟播放24或30张图。不同之处在于这个AVI文件里面有一种帧,叫做“D帧”。作用是占时间,播放的时候会被忽略。这样说可能还是不好理解,还是还是排列出来就一目了然了:用K表示普通帧,D表示D帧:
 24fps的:K    K    K    K    K    K
120fps的:KDDDDKDDDDKDDDDKDDDDKDDDDKDDDD
会发现都是一样的。24fps的有6帧,播放需要0.25秒。而120fps的有30帧,播放也是0.25秒。而实际上,120fps那里只有6帧是K,也就是说两个都是一样的。
  那这样用24不就好了,为什么要弄一个120出来呢?是因为,还有一种常见的帧速率是30fps。当动画片种既出现30fps又出现24fps,AVI是不能一个文件拥有多种fps的。那么,就用120fps,既可以包含30fps的部分,又可以包含24fps的部分。
  在压制的时候,我们压制的都是K帧,如果你就这样把120fps的东西送去压制,出来的结果就是全部的D都变成K,这样怎么行?不仅播放的时候暴耗CPU,浪费压制的时间,还无意义地增大了文件地体积。在压制之前,要先把D帧去掉。
  本节新出现的AVS语句:
  selectevery(n)      每n帧取一帧。比如原来是123456789,那么用了selectevery(3)以后就会变成147。
  import("文件名")     导入另一个AVS文件,效果和把这个AVS文件的代码粘贴进来一样。
  assumefps(目标帧速率) 更改帧速率,不改变帧数(改变时间)。比如原来有30帧,fps由30改为24后,播放时间变为1.25秒。
  原理很简单,在30fps的片段用selectevery(4),在24fps的片段用selectevery(5)。那么如何判断哪些地方是24fps,那些地方是30fps呢?从AVI中可以导出一个文件叫做timecodes,这个文件里面记录了每一个K帧出现的时间。通过这个文件,我们可以判断出哪里是帧交替点。这里介绍一个我写的自动判断的工具,把timecodes送进去它会出来一个AVS文件,里面就是刚才介绍的selectevery()语句之类的东西。在对片源加载好字幕以后,导入这个AVS即可去除所有D帧,接下来就是送去压制。
例:这个是片源AVS:
loadplugin("c:\program files\avisynth 2.5\plugins\vsfilter.dll")
avisource("[dmhy][fmp2][dvdrip][01].avi")
textsub("[dmhy][fmp2][dvdrip][01].ssa")
import("[dmhy][fmp2][dvdrip][01].deldf.avs")

这是[dmhy][fmp2][dvdrip][01].deldf.avs
a0=trim(0,206).selectevery(5).assumefps(29.97)
a1=trim(209,535).selectevery(4).assumefps(29.97)
a2=trim(538,1983).selectevery(5).assumefps(29.97)
a3=trim(1987,10833).selectevery(4).assumefps(29.97)
a4=trim(10836,11891).selectevery(5).assumefps(29.97)
a5=trim(11895,12253).selectevery(4).assumefps(29.97)
a6=trim(12256,15622).selectevery(5).assumefps(29.97)
a7=trim(15625,16584).selectevery(4).assumefps(29.97)
a8=trim(16586,39557).selectevery(5).assumefps(29.97)
a9=trim(39560,40007).selectevery(4).assumefps(29.97)
a10=trim(40009,67039).selectevery(5).assumefps(29.97)
a11=trim(67043,67361).selectevery(4).assumefps(29.97)
a12=trim(67364,71610).selectevery(5).assumefps(29.97)
a13=trim(71613,71875).selectevery(4).assumefps(29.97)
a14=trim(71878,74128).selectevery(5).assumefps(29.97)
a15=trim(74132,75650).selectevery(4).assumefps(29.97)
a16=trim(75653,84143).selectevery(5).assumefps(29.97)
a17=trim(84147,85105).selectevery(4).assumefps(29.97)
a18=trim(85108,158948).selectevery(5).assumefps(29.97)
a19=trim(158952,166138).selectevery(4).assumefps(29.97)
a20=trim(166141,167496).selectevery(5).assumefps(29.97)
a21=trim(167500,167795).selectevery(4).assumefps(29.97)
a22=trim(167797,169696).selectevery(5).assumefps(29.97)
a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15+a16+a17+a18+a19+a20+a21+a22

  虽然这个看起来复杂,但是是没有奇怪的语句,而且是程序自动生成,不用自己写。
  为什么要先挂字幕,而不先去除D帧呢?因为D帧是用来提供24fps和30fps混合的,去掉D帧fps会混乱,字幕的时间就不准了。
  这里介绍一下这个删除D帧的AVS的取得办法:
  首先用附带的工具取得timecodes。方法是把AVI文件拖动到avi2timecode的图标上,一个TXT就会出来。然后把这个TXT拖到120tcv2toavs图标上,这个AVS就会出来了。
  最后压制完时间还是不准的,要进行处理。这里推荐封装成MKV格式。压制出来有一个视频文件,片源中解出来音频文件,然后和timecodes一块儿封装到MKV里面。
  封装MKV用的是MKVToolnix,封装方法:
  首先启动mkvmerge GUI(这个软件启动比较慢,耐心点),然后加载压制成品和音频,在轨道那里选中视频:
  下方找到这个:
  把一开始用avi2timecode生成的那个TXT文件弄到这里,然后和平时一样照常封装即可。
附:封装MKV的方法
  MKV类似于AVI,是一种封装格式,说白了就是给音频流和视频流提供放的地方。MKV要比AVI先进,比如AVI的120fps是为了使24fps和30fps的得以混合,而MKV自身就是可以支持24fps和30fps混合的,不需要借助什么120fps。MKV还有很多比AVI先进的地方,大家还是慢慢体会吧。如果没有什么视频基础知识,要播放MKV我推荐使用MediaPlayerClassic,播放方法和播放普通的视频没什么区别。这里介绍一下MKV的制作方法。
  制作MKV通常是借助一个叫做MKVToolnix的工具。首先下载下来安装,运行那个mkvmerge GUI就会出现如下窗口:
  按照上面说的操作就可以了……







下面是VFR的制作


  在上一节,讲了关于如何处理120fps片源的问题。还记得最后是怎么做的吗?和Timecodes一起,把压制出来的东西封装成MKV。这里MKV是作为真正支持VFR的媒体容器使用。这样的话,片源也就可能使用MKV封装,里面混合着24fps和30fps(甚至还有60fps)的片段。AVS是不支持VFR(注:VFR就是指可变帧速率,播放的时候fps可以改变),如果还像原来那样内嵌,那么时间轴就会有困难。因为如果全部AssumeFPS(还记得这个AVS语句么?)成24或30,都会导致时间轴变得不准,那么怎么办呢?方法还是有的,上一节的片源是用D帧来占时间,那么我们人为地造出D帧来用于内嵌,内嵌好以后再把这些多出来的帧删除,问题就解决了。
  本节新用到的AVS语句:
Directshowsource("文件名",fps=帧速率) 使用类似Windows自带的媒体播放器打开文件的方式调用片源,效率远远低于AviSource。不到万不得已请不要使用。
Selectevery(n,n1,n2,n3……) 这个是Selectevery的一个新语法,意思是以n为周期,取每一个周期里的第n1 n2 n3……帧。这可能不太好理解,举例:
片源的帧是123456789,执行了selectevery(4,1,4)就会变成1458。如果用了selectevery(1,1,1,1,1)就会变成111122223333444455556666777788889999(就是这个,变成120fps的方法)。
1 、片源的加载
  因为这次的片源是MKV,就不能像原来那样加载了。当然,把MKV里面的AVI(如果封装的时候加入的是AVI)解出来处理是可以的,效率很高。如果解出来是其他什么格式(比如x264压制出来的MP4被封装在里面),可以考虑使用AVS的Directshowsource语句。
  DirectshowSource语句是加载视频的语句,与AVISource不同的是,Directshowsource使用Directshow方式加载视频(也就是WindowsMediaPlayer使用的那种加载方式)。使用Directshowsource语句加载视频最好要指定fps,比如fps=29.97。事实上,WindowsMediaPlayer配合各种Splitter(就是把封装格式解来播放用的,比如Windows自带AVISplitter)可以播放各种格式,甚至RMVB也可以。
  使用方法也是很简单,就像这样:directshowsource("c:\1.mp4",fps=29.97)
2 、VFR的还原
  上一节介绍的封装MKV法,在封装MKV的时候还一起进去了个Timecodes。现在我们要利用这个Timecodes在AVS里把片源处理成120fps的,然后就和处理120fpsAVI片源一样的方法处理就可以了。
  首先要把这个Timecodes解出来。我考虑到很多人可能到现在还不会使用命令行,所以就写了一个小工具SMEG,专门用来解MKV(功能很弱,各位高手不要见笑)。把这个工具放在当时安装MKVToolnix的地方,然后运行即可。界面是中文的,我想我也不用多说什么,把里面的Timecodes解出来即可。
  利用已经讲过的语句,就可以把没有D帧的片源处理成120fps的了。首先用Trim取一段,然后用Selectevery把这一段处理成120fps,然后Assumefps到120。这个如果手工来的话也是有很大工作量,所以我也写了一个程序自动生成AVS。同样用Import命令即可。加载时片源的fps可以随意指定,在这一步片源的fps就失效了。
例:生成的AVS像这样:
b0=trim(0,40).selectevery(1,1,1,1,1,1).assumefps(119.88)
b1=trim(41,122).selectevery(1,1,1,1,1).assumefps(119.88)
b2=trim(123,412).selectevery(1,1,1,1,1,1).assumefps(119.88)
b3=trim(413,2624).selectevery(1,1,1,1,1).assumefps(119.88)
b4=trim(2625,2836).selectevery(1,1,1,1,1,1).assumefps(119.88)
b5=trim(2837,2926).selectevery(1,1,1,1,1).assumefps(119.88)
b6=trim(2927,3600).selectevery(1,1,1,1,1,1).assumefps(119.88)
b7=trim(3601,3840).selectevery(1,1,1,1,1).assumefps(119.88)
b8=trim(3841,8435).selectevery(1,1,1,1,1,1).assumefps(119.88)
b9=trim(8436,8547).selectevery(1,1,1,1,1).assumefps(119.88)
b10=trim(8548,13954).selectevery(1,1,1,1,1,1).assumefps(119.88)
b11=trim(13955,14034).selectevery(1,1,1,1,1).assumefps(119.88)
b12=trim(14035,14884).selectevery(1,1,1,1,1,1).assumefps(119.88)
b13=trim(14885,14950).selectevery(1,1,1,1,1).assumefps(119.88)
b14=trim(14951,15401).selectevery(1,1,1,1,1,1).assumefps(119.88)
b15=trim(15402,15781).selectevery(1,1,1,1,1).assumefps(119.88)
b16=trim(15782,17480).selectevery(1,1,1,1,1,1).assumefps(119.88)
b17=trim(17481,17720).selectevery(1,1,1,1,1).assumefps(119.88)
b18=trim(17721,32489).selectevery(1,1,1,1,1,1).assumefps(119.88)
b19=trim(32490,34286).selectevery(1,1,1,1,1).assumefps(119.88)
b20=trim(34287,34558).selectevery(1,1,1,1,1,1).assumefps(119.88)
b21=trim(34559,34632).selectevery(1,1,1,1,1).assumefps(119.88)
b22=trim(34633,35013).selectevery(1,1,1,1,1,1).assumefps(119.88)
b0+b1+b2+b3+b4+b5+b6+b7+b8+b9+b10+b11+b12+b13+b14+b15+b16+b17+b18+b19+b20+b21+b22

3 、挂字幕
  之前已经说了好多遍了,不重复了。
4 、去D帧
  和处理120fpsAVI的片源没有两样,通过Timecodes生成一个AVS然后Import。
5 、压制
  这个是你自己的事了……
6 、封装
  和Timecodes一起,封装进MKV。
7 、附录:如何拆MKV
  AVI的音频可以使用VDM来解,那么MKV里面的音频呢?
  为了解决这些问题,本节多了这个附录……
  首先是分析MKV里面哪一个流是什么。安装MKVToolnix以后,会有一个mkvinfo GUI在开始菜单里。这个是用来查看MKV信息的。运行这个,会弹出一个窗口,点击File->Open,选择你要拆封的MKV文件,打开以后,MKV的信息就显示出来:
  信息很多,而且比较杂。只要从里面找出关键信息,其他可以不要管他。
  首先是“Segment tracks at 4296”,数字可能有所不同。意思是这里开始是轨道信息。
  然后是“A track at 4302”,数字可能有所不同,意思是这里开始是一个轨道。
  轨道号在这里,一定要记住。这个“Track number:1 at 4305”,1是轨道号。
  编码决定了这个轨道是否可以解出来和解出来用的扩展名。找到“Codec ID”。这里显示的是“V_MPEG_4/ISO/AVC”。如果你看到的也是这个,就说明要解成.264文件,封装成MP4,用Directshowsource加载。最开始的“V_”表示这个是视频,如果是“A_”就说明这个是音频。
  找好你要解的轨道以后,运行SMEG,在“拆指定流”后面输入轨道号,然后点击“拆”,会叫你保存拆出来的文件。这里输入文件名以后,还要输入扩展名。扩展名很重要,决定扩展名要根据“Codec ID”,如果是XVID等等之类的就是AVI,文件名就像这样输入:"c:\1.avi"。如果是MPEG-1 Layer3就是MP3,AAC就是AAC……凭经验吧,不会了还可以把Codec ID贴出来,拿到论坛问。
附录2:.264文件封装成MP4的方法
  搜索,然后下载MP4Creator。使用方法也很简单,还是怕有人不会,写了GUI……放在一起,运行,选择.264文件,OK……

只看该作者 1 发表于: 2015-10-31
好複雜高深啊~這是高手才能懂的~
謝謝樓主分享~
快速回复
限1000 字节
 
上一个 下一个