在上一节，讲了关于如何处理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像这样：[code] 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 [/code]3 、挂字幕之前已经说了好多遍了，不重复了。4 、去D帧和处理120fpsAVI的片源没有两样，通过Timecodes生成一个AVS然后Import。5 、压制这个是你自己的事了……6 、封装和Timecodes一起，封装进MKV。7 、附录：如何拆MKVAVI的音频可以使用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……
在内嵌的时候，经常会遇到一些很奇怪的片源。这些片源大小和普通片源看起来没什么差别，可是压缩的时候几个小时都完不成，好不容易等死等活地等完了，发现播放的时候不是卡卡的就是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：[code] 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") [/code]这是[dmhy][fmp2][dvdrip][01].deldf.avs[code] 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 [/code]虽然这个看起来复杂，但是是没有奇怪的语句，而且是程序自动生成，不用自己写。为什么要先挂字幕，而不先去除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就会出现如下窗口：按照上面说的操作就可以了……
1 、初识AVS首先必须明确，AVS是什么东西？AVS的全称是AviSynth。还记得用VDM内嵌字幕的时候是怎么做的吗？先打开片源，然后挂字幕，最后送到编码器压制。所以说到最后，VDM的工作就是给编码器提供带有字幕的视频。AVS的功能也是差不多，就是输入源视频，输出处理过的视频。AVS的处理过程全部保存在AVS文件里。对于AVS文件，我们可以把它当作是视频文件，因为安装好AviSynth以后，AVS文件可以像AVI那样被VDM打开，甚至能被播放器打开。AVS文件中包含的是处理信息。先举个简单的例子。比如之前的用VDM内嵌字幕，现在改用AVS内嵌字幕。VDM启动的时候自动加载字幕插件，先打开片源，然后添加字幕插件。用AVS的话就可以这样写：（文件名自己改）[code] loadplugin("c:\vsfilter.dll") avisource("c:\1.avi") textsub("c:\1.ssa") [/code]我来解释一下，第一句中的loadplugin()意思是加载插件，括号里面就是插件的名字。在VDM里面启动时会自动加载插件，AVS中要手动写这一句。vsfilter.dll是字幕插件的名字。然后是avisource()，这个是加载AVI的功能，就像VDM中的打开文件。textsub这个功能本来AVS没有，是加载完vsfilter.dll这个插件以后才有的。就像是VDM在没有加载字幕插件的情况下在Video->Filter里面不会出现textsub这个东西。textsub()括号里面的是字幕文件的名字。以上内容用记事本写好，保存的时候在文件名后面加上“.avs”。然后这个AVS文件拿去用播放器打开试试，播放出来有字幕的影片了吗？这样还只是出来一个AVS文件而已，字幕并没有真正跑到影片里面去。刚才看到的是AVS输出的画面，只要把这个画面拿去压制就可以出来有字幕的文件了。可以使用VDM进行压制。在VDM打开文件的时候，直接选择AVS文件，然后不要再挂字幕了，设置好以后送去压制就可以了。2 、特效的内嵌AVS强大的功能还不止这一点，现在再介绍复杂一点的AVS操作。比如特效，字幕组的人经常会把特效制作成AVI格式或者字幕格式。如果是字幕格式，那好办，用AVS就这样写：[code] loadplugin("c:\vsfilter.dll") avisource("c:\1.avi") textsub("c:\1.ssa") textsub("c:\tx.aas") [/code]和刚才相比，就多了一句，再加载一次字幕而已。如果是AVI的特效，比如是片头，就是去掉原来动画片的片头，把这个AVI塞进去充当片头。就是说用AVI里面的内容替换片源的内容。先要找到片源中要替换的部分的位置。这个用VDM操作。用VDM打开片源，拖动下面的滚动条找到片源中要替换部分的开头，这里的开始位置就是361，记住这个数字。然后用同样的方法找到结束位置，这里找到的是2519。再把滚动条移动到最后面，找到总帧数，这里是35963。然后找出那个AVI特效。这里假设片源是c:\py.avi，字幕是c:\zm.ssa，特效是c:\tx.avi。[code] loadplugin("c:\vsfilter.dll") py=avisource("c:\py.avi",audio=false).textsub("c:\zm.ssa") tx=avisource("c:\tx.avi",audio=false) py.trim(0,360)+tx+py.trim(2520,35963) [/code]这个AVS会相对比较复杂。解释一下：[code] loadplugin("c:\vsfilter.dll") #加载字幕插件 py=avisource("c:\py.avi",audio=false).textsub("c:\zm.ssa") #加载片源并挂字幕 tx=avisource("c:\tx.avi",audio=false) #加载特效 py.trim(0,360)+tx+py.trim(2520,35963) #用特效代替片源中的部分 [/code]和前面相比，又多了一些东西。在加载片源语句中，多了一个audio=false，这个的意思是加载片源的时候不加载音频。以此类推，加载特效的时候也没有加载音频。音频的话可以在最后压制好再混合。这样就直接在AVS里面禁掉了音频，不用在VDM里面选audio->No audio了。加载语句的后面跟了一个点，然后是加载字幕。点的作用是分割，意思是加载好片源以后紧跟着挂字幕。为的是写在同一行。写在同一行的理由在这一行的开头，就是那个py=。它的意思是这一整行出来的结果用py表示。下面的也是，特效加载好以后用tx表示。接下来是最后一句。py.trim(0,360)的意思是在py中截取第0帧到第360帧。因为片源要替换的部份是从361帧开始的，我们不能把要替换的部分截出来，py.trim(2520,35963)的意思是把片源的2520帧到35963帧截出来。加号表示连接。连起来，最后一行就是先把输出py的0-360帧输出，然后输出tx，tx输出完了就把py的2520-35963输出。这样看起来，就是py中361-2519的那部分没掉了，取而代之的是tx。这样，特效就用进去了，然后送到VDM压制。总结：这一次介绍的AVS内容归纳起来有以下几点：（中括号内表示可有可无）[code] loadplugin("插件文件的位置、文件名") #加载AVS的插件 avisource("文件名"[,audio=false]) #加载AVI文件，可以用audio=false禁止加载音频部分 trim(起始帧,终止帧) #截取片段 textsub("字幕文件名") #AVS插件VSFilter中的语句，加载字幕 [/code]