版面规则
提问时请注意:尽量详细描述操作过程、AVS脚本内容等,最好能写出片名,只贴图有时无法看出问题原因。
提示:发布原创内容请尽量使用附件上传。使用网盘会出现过期失效的问题,请注意。
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

DTDecimate - 删除24d重复帧并保持音画同步脚本

某DVD为混合片源,有100+集,做了20集终于蛋碎了 {:cat_5}

用于解决混合片源分N段后,帧数不为5的倍数的24d删除重复帧,合并之后音画不同步的问题

具体方法是将帧数不为5的倍数的24d视频分为两段处理,
第一部分的帧数是5的倍数,第二部分的是 第一部分的尾帧+剩余帧
第一部分用TDecimate(或自定义),
第二部分用FDecimate(一个循环没有重复帧时,FDecimate是删去最后一帧(TDecimate则是删去最像重复帧的那帧))
除去第二部分的首帧然后再把尾帧(也许是重复帧,也许不是)补上,再修正帧率,
然后输出timecode

感谢全语种制霸比利的指点,修改了之前的脚本
如果脚本有问题,还请大家帮忙修正
需要:
TIVTC
FDecimate
BillyTC


参数说明:
DTDecimate(clip c1, clip c2, string dec, string pp, bool first, string tc){

dec,删除重复帧的方法,默认为TDecimate()
pp,对24d部分删帧之后的处理,默认不处理
first,是否对首个clip进行删帧处理,默认不处理,如果有两个clip,强制不处理
tc,timecode文件名,默认timecodes_v1.txt
具体用法:

比如,clip1是30p,clip2是24d,clip3是60p,clip4是24d

代码: 全选

clip1.BillyTC()
\.	 DTDecimate(clip2)
\.	 BillyTC(clip3)
\.	 DTDecimate(clip4)
如果首个clip为24d的情况,
clip1是24d,clip2是60p,clip3是30p,clip4是24d

代码: 全选

clip1.DTDecimate(first=true)
\.	 BillyTC(clip2)
\.	 BillyTC(clip3)
\.	 DTDecimate(clip4)
如果这样:

代码: 全选

v0=BlankClip(length=100, width=640, height=480, pixel_type="yv12", fps=30000, fps_denominator=1001,color=$000000).killaudio()
v1=BlankClip(length=101, width=640, height=480, pixel_type="yv12", fps=30000, fps_denominator=1001,color=$000000).killaudio()
v2=BlankClip(length=102, width=640, height=480, pixel_type="yv12", fps=30000, fps_denominator=1001,color=$FFFFFF).killaudio()
v3=BlankClip(length=103, width=640, height=480, pixel_type="yv12", fps=30000, fps_denominator=1001,color=$000000).killaudio()
v4=BlankClip(length=104, width=640, height=480, pixel_type="yv12", fps=30000, fps_denominator=1001,color=$000000).killaudio()


v0.	DTDecimate(first=true)
\. 	DTDecimate(v1)
\.	DTDecimate(v2)
\.	DTDecimate(v3)
\.	DTDecimate(v4)
输出的timecode则为

代码: 全选

# timecode format v1
Assume 23.976024
0,79,23.976024
80,159,23.976024
160,160,29.970030
161,241,23.976024
242,242,39.960040
243,324,23.976024
325,325,59.940060
326,408,23.976024
409,409,119.880120
Download: [syntax lang="avisynth" lines="f" filename="DTDecimate.avsi"]
###############################################################################################################
### Requirements:
### "TIVTC"
### "FDecimate"
### "BillyTC" http://www.nmm-hd.org/newbbs/viewtopic.php?f=7&t=1071
###############################################################################################################

Function DTDecimate(clip c1, clip "c2", string "dec", string "pp", bool "first", string "tc"){

dec = Default(dec, "TDecimate()")
pp = Default(pp, "")
tc = Default(tc, "timecodes_v1.txt")
first = Default(first, false)
b2 = Defined(c2)

first = b2 ? false : first

########################

f1 = c1.framecount
f2 = b2 ? c2.framecount : NOP

L1 = c1.trim(f1-1,-1).AssumeFps(24000,1001)
L2 = b2 ? c2.trim(f2-1,-1).AssumeFps(24000,1001) : NOP

d1 = (b2 == True)
\? c1
\: (first == False)
\? c1
\: (f1 % 5 == 0)
\? Eval("c1.TD(dec)" + chr(10) + pp)
\: (f1 % 5 == 1)
\? Eval("c1.TD(dec) + L1" + chr(10) + pp)
\: Eval("c1.TD(dec) + c1.FD() + L1" + chr(10) + pp)

d2 = (b2 == false)
\? NOP
\: (f2 % 5 == 0)
\? Eval("c2.TD(dec)" + chr(10) + pp)
\: (f2 % 5 == 1)
\? Eval("c2.TD(dec) + L2" + chr(10) + pp)
\: Eval("c2.TD(dec) + c2.FD() + L2"+ chr(10) + pp)

f_d1 = d1.framecount
f_d2 = isclip(d2) ? d2.framecount : NOP

########################

a1 = (f1 % 5 ==0)
\? NOP
\: String(f_d1-1) + "," + String(f_d1-1) + "," + String(last_fps(c1))
a2 = (b2 == False)
\? NOP
\: (f2 % 5 == 0)
\? NOP
\: String(f_d1-1+f_d2) + "," + String(f_d1-1+f_d2) + "," + String(last_fps(c2))

o1 = "first ? d1.trim(0,f_d1-2).BillyTC(tc=tc) + d1.trim(f_d1-1,-1).AssumeFps(24000,1001) : c1.BillyTC(tc=tc)"
o2 = "d1.BillyTC(d2.trim(0,f_d2-2),tc=tc) + d2.trim(f_d2-1,-1).AssumeFps(d1.framerate)"

########################

return (b2 == False && f1 % 5 == 0)
\? d1.BillyTC(tc=tc)
\: (b2 == False)
\? Eval(o1).WriteFileStart(tc, "a1", append=True )
\: (f2 % 5 == 0)
\? d1.BillyTC(d2,tc=tc)
\: Eval(o2).WriteFileStart(tc, "a2", append=True )

}


Function TD(clip src,string "dec"){

fc = src.framecount

return Eval("src.trim(0,fc-1-fc%5)." + dec)

}


Function FD(clip src){

fc = src.framecount

return src.trim(fc-1-fc%5,fc-1).FDecimate(23.976024).trim(1,0)

}


Function last_fps(clip src){

fc = src.framecount

return (fc % 5 == 1)
\? pFrac2Str(30000,1001,6)
\: (fc % 5 == 2)
\? pFrac2Str(40000,1001,6)
\: (fc % 5 == 3)
\? pFrac2Str(60000,1001,6)
\: (fc % 5 == 4)
\? pFrac2Str(120000,1001,6)
\: 0

}

[/syntax]
上次由 zhongpang 在 2013-08-08 21:20,总共编辑 5 次。
头像
Billy Herrington
帖子: 83
注册时间: 2013-01-09 9:54

Re: BillyTC mod - 删除24d重复帧并保持音画同步

Scripts are tl;dr, so what is the difference between your examples and the following:

代码: 全选

clip1.BillyTC()
\    .BillyTC(clip2.TDecimate.checkmate(tthr2=1))
\    .BillyTC(clip3)
\    .BillyTC(clip4.TDecimate)
and

代码: 全选

clip1.TDecimate.BillyTC()
\    .BillyTC(clip2)
\    .BillyTC(clip3)
\    .BillyTC(clip4.TDecimate)
And btw, checkmate was designed to be used on interlaced materials, thus normally one should use it before field matchers or deinterlacers, but not after IVTC/deint. Though it can still work, it is not guaranteed to work as expected. This is because dot crawls and rainbows are resulted from the transmission of composite video, while most of the materials in such transmissions are interlaced videos, either video type or already pulldowned film type. When one deals with it one should remove them first and then do ivtc/deint afterwards.

Generally, video processing should use exactly the reversed order that how the artefacts turned up. Normally the last few steps of problems are:
...
pulldown/interlacing
blocking(from transcoding)
dot crawl/rainbow(from transmitting)

so, to combat with them, we should follow such an order:
dedot/derainbow
deblock
IVTC/deint
...
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: BillyTC mod - 删除24d重复帧并保持音画同步

主要解决 帧数不为5的倍数的24d 删除重复帧后音画不同步的问题

代码: 全选

clip1=blankclip(101,pixel_type="yv12",fps=30000,fps_denominator=1001) #24d 用TDecimate后变为80帧 1001/30000*101-1001/24000*80  从此处视频约减少33毫秒
clip2=blankclip(100,pixel_type="yv12",fps=60000,fps_denominator=1001) #60p 
clip3=blankclip(102,pixel_type="yv12",fps=30000,fps_denominator=1001) #24d 用TDecimate后变为81帧 1001/30000*102-1001/24000*81 从此处视频约减少25毫秒
clip4=blankclip(100,pixel_type="yv12",fps=30000,fps_denominator=1001) #30p
clip5=blankclip(103,pixel_type="yv12",fps=30000,fps_denominator=1001) #24d 用TDecimate后变为82帧 1001/30000*103-1001/24000*82 从此处视频约减少167毫秒
clip6=blankclip(100,pixel_type="yv12",fps=60000,fps_denominator=1001) #60p
clip7=blankclip(104,pixel_type="yv12",fps=30000,fps_denominator=1001) #24d 用TDecimate后变为83帧 1001/30000*104-1001/24000*83 从此处视频约减少8毫秒
clip8=blankclip(100,pixel_type="yv12",fps=30000,fps_denominator=1001) #30p
clip9=blankclip(105,pixel_type="yv12",fps=30000,fps_denominator=1001) #24d 用TDecimate后变为84帧 1001/30000*105-1001/24000*84 = 0 视频时间不变
首先这样,获得每段的准确时间

代码: 全选

clip1.BillyTC() 
\    .BillyTC(clip2)
\    .BillyTC(clip3)  
\    .BillyTC(clip4)
\    .BillyTC(clip5)  
\    .BillyTC(clip6)
\    .BillyTC(clip7)  
\    .BillyTC(clip8)
\    .BillyTC(clip9) 
timecode为

代码: 全选

# timecode format v1
Assume 29.970030
0,100,29.970030
101,200,59.940060
201,302,29.970030
303,402,29.970030
403,505,29.970030
506,605,59.940060
606,709,29.970030
710,809,29.970030
810,914,29.970030
直接删去重复帧后用billytc

代码: 全选

clip1.TDecimate().BillyTC() 
\    .BillyTC(clip2)
\    .BillyTC(clip3.TDecimate())  
\    .BillyTC(clip4)
\    .BillyTC(clip5.TDecimate())  
\    .BillyTC(clip6)
\    .BillyTC(clip7.TDecimate())  
\    .BillyTC(clip8)
\    .BillyTC(clip9.TDecimate())  
得到timecode

代码: 全选

# timecode format v1
Assume 23.976024
0,79,23.976024
80,179,59.940060
180,260,23.976024
261,360,29.970030
361,442,23.976024
443,542,59.940060
543,625,23.976024
626,725,29.970030
726,809,23.976024
把两个timecode的时间相比较
左边为直接用TDecimate()后的时间,右边为原始视频时间,中间为时间差的累积
可见,如果帧数不为5的倍数的clip直接使用TDecimate()后,视频时间会发生变化
随着分段的增多,音画不同步可能会越来越明显(视RP而定)

代码: 全选

       TDecimate  		             ori
clip1	3.336667 	-0.033367 	3.370033 
clip2	1.668333 	-0.033367 	1.668333 
clip3	3.378375 	-0.058392 	3.403400 
clip4	3.336667 	-0.058392 	3.336667 
clip5	3.420083 	-0.075075 	3.436767 
clip6	1.668333 	-0.075075 	1.668333 
clip7	3.461792 	-0.083417 	3.470133 
clip8	3.336667 	-0.083417 	3.336667 
clip9	3.503500 	-0.083417 	3.503500 
如果用billytcmod

代码: 全选

clip1.BillyTCmod(c1_24d=true)
\    .BillyTCmod(clip2)
\    .BillyTCmod(clip3,true)
\    .BillyTCmod(clip4)
\    .BillyTCmod(clip5,true)
\    .BillyTCmod(clip6)
\    .BillyTCmod(clip7,true)
\    .BillyTCmod(clip8)
\    .BillyTCmod(clip9,true)
得到如下timecode,保持每段视频时间不变,保持音画同步

代码: 全选

# timecode format v1
Assume 23.976024
0,79,23.976024
80,80,29.970030
81,180,59.940060
181,260,23.976024
261,262,29.970030
263,362,29.970030
363,442,23.976024
443,445,29.970030
446,545,59.940060
546,625,23.976024
626,629,29.970030
630,729,29.970030
730,813,23.976024
主要步骤是把帧数不为5的倍数的24d拆成两部分,
第一部分帧数是5的倍数,删去重复帧帧率变成24000\1001;
第二部分帧数是除以5的余数,帧率保持30000/10001不变

关于复合视频的处理,感谢指点
关于checkmate,
我觉得如果DVD是hard pulldown,要用在IVTC之前
如您所说,制作顺序为
pulldown
dot crawl/rainbow(from transmitting)

但如果DVD是soft pulldown,要用在IVTC之后,因为源本来就是24p
制作顺序为
dot crawl/rainbow(from transmitting)
pulldown
头像
Billy Herrington
帖子: 83
注册时间: 2013-01-09 9:54

Re: BillyTC mod - 删除24d重复帧并保持音画同步

About dedot/derainbow:

If source is soft pulldown and dot crawl/rainbow lays on the pre-transcoded pictures, you should either force film to skip useless telecine+IVTC and directly use 24p contents, or do dedot/derainbow before apply RFF on raw contents if it is hybrid contents and you could not force film. It is a little bit hard to realize in avs, but can easily archived in vapoursynth via d2vsource, with which decoding and applying RFF can be used separately using bitstream flags. In avs it is possible to only decode raw streams but applying correct RFF flags on hybrid sources is really a pain....

And I really doubt if re-mastered soft pulldown with dot crawl/rainbow is mastered correctly. Because in a correct 24p mastering process, composite video transmission should never be invoked, so in some step the makers must have use the incorrect process which, AFAIK, usually are used for producing composite video, and most of composite video process works on interlaced materials, so there is very likely to be a film->telecined->film transforming, for which dot crawl/rainbow is still produced on interlaced raws and should be removed after before IVTC.

And more generally, those soft pulldown films with dot crawl/rainbow might not be re-mastered, but only contain old materials which suffer terrible artefacts before being used to create DVDs. In those cases, dot crawl and rainbow is still produced in interlaced forms before official IVTC, so you would like to apply RFF (using honor flags) to revert official IVTC, do dedot/derainbow, and play with following filters....

Actually, many derainbow/dedot filters follow the same way. They always assume the sources are interlaced materials, and internally use SeparateFields/Weave before/after processing. I didn't find source codes of checkmate, but with my limited experience I believe it works in the same or similar logic.

About TDecimate problem:

TDecimate problem for non-mod-5 frame numbers is not BillyTC's problem. BillyTC does what it should, but TDecimate's solution is not perfect (though it is what it can do best). And your solution is probably the worst. Because even if you're decimating from a 102 frames clip and you find the last 2 frames cannot be processed without changing to an accurate 4/5 PTS, the fact that those two frames are still 24p->telecine->30i materials does not change. If you want to keep them as 30fps, the correct method is using RFF flags for them and mark your encoded video as hybrid one.

Let's make it easier to understand. If we have only 7 frames in line after telecine and the frame sequence contains a moving object of a constant speed. Now after field matching, each interval between two different neighbour frames is exactly the same, so let's call it 1 distant unit. The accurate time for 1 distant unit is 1/24s. When we decimate the first 5 frames to 4, the repeat frame was removed and they move smoothly. After them we process the last 2 frames, they're either two same(repeated) pictures in which case your solution keeps they two as 30fps and you'll get the object staying too long (1/30*2s per distant unit instead of correct 1/24s distant unit) in that position, or they're two different pictures in which case your solution keeps they two as 30fps and you'll get the object moving too fast (1/30s per distant unit instead of 1/24s per distant unit). Would you like to call it correct? I wouldn't.

Yes. The problem is when film clips contains a non-mod-5 frame number, it cannot be decimated perfectly. When you keep all in 24p by either remain or decimate from all combinations of fields from different camara time, the video and audio is not synced correctly. But still, forcing the remains with 30000/1001 is much more inaccurate and people can be more sensitive to that, if it is a smoothly moving scene. I can even easily produce jerky three-frame sequence using this method. Perfection not only covers the timing in final result of each segment, but also the timing of every single frame. If you only count for the syncness regardless of the motion smooth, it is just a hacky trick, not a solution. I personally would rather accept the unsyncness than that.

And if you just want to prevent TDecimate's unsync error from accumulating to cause large unsyncness, I would like to recommand you to find some 24p scenes that the remain frames of frame_num/5 are all different, and use ovr of TDecimate to keep them all (or in other words, stop TDecimate from decimating one more frame by mistake in this case). If you get some scene in which you need to decimate more, and some scene you need to decimate less, generally video and audio will remain somehow synced, though not perfect.

If you want a perfect solution, you would probably want to take a try on interpolation of missing camara time. On such a scene change frame(last frame in the scene), use the motion vector from the previous frame and the current frame to generate one or even more pictures, compensating the shortened time while carefully keep the moving smooth. It is not a difficult mathematical problem, but you need to know some motion compensating.

Anyway, it should not be done in a timecodes creating filter. It must be used as a post-compensating filter of TDecimate. The correct way of using it might be:
decimated = TDecimate()
remain = TDCompensate(decimated, last) # for example, 8.341667ms was cut by TDecimate, TDCompensate generates a frame of 8.341667ms
decimated.BillyTC
\ .BillyTC(remain)

# timecodes v1
Assume 23.976023
0,79,23.976023
80,80,119.880120 # compensated frame of 8.341667ms generated by TDCompensate

And more generally, it should be a process within TDecimate. For example, adds an option in TDecimate to do such a compensation and in the same time outputs a timecodes file for such a vfr result. Though it will make it difficult to use with BillyTC, TDecimate or any post-decimate aid-filter with automatically timecodes outputing is the best role to deal with the timing error. Suppose you only want to decimate a 40001-frame 24d video without any further appending, you would never like to bother with BillyTC, but if you want a perfect result, you still want to do the compensation after the last frame after decimating, so it is absolutely not an option to always do it manually. The difference from this example and your example is that when not being appended, the unsyncness is negligible, but when being appended, the accumulated error is huge that you cannot endure.

So, fix it in TDecimate, or ovr to keep it in a negligible level. Do not try to touch it outside TDecimate's workshop when the error was generated there.
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: BillyTC mod - 删除24d重复帧并保持音画同步

感谢指点
如果不插帧,framecount%5>1的24d使用TDecimate之后,只调整最后1帧(SC帧)的帧率,以保持音画同步,这样副作用应该会小些?
大概对于SC帧时间的细微变化,人眼较难察觉,因为不涉及动态变化
比如,对于bad edit带来的无法场匹配的问题,tfm默认允许SC帧使用u\n匹配,而不是deint

确实这些功能应该加在TDecimate里,
或者让TFM能一条龙处理混合片源,比如30i可以bob成60p,而且对于24t,30i,30p可以分别进行后处理。当然,这可能需要ovr
这样就可以不分段了,免得又要对TDecimate生成的tc进行处理

但是战斗力<5,只会写简单的脚本,只有牛头人了(死
头像
Billy Herrington
帖子: 83
注册时间: 2013-01-09 9:54

Re: BillyTC mod - 删除24d重复帧并保持音画同步

Changing the duration of only the last frame does make things better, but still not perfect.

If the last frame duration is reduced, the duration of each position is default_duration, default_duration, ..., default_duration, default_duration, default_duration - x. People expect default_furation but it is shorter. Given it is the last frame in the scene, it is acceptable.

If the last frame duration is increased, the duration of each position is default_duration, default_duration, ..., default_duration, default_duration, default_duration + x. People expect default_furation but it is longer. At the point that default_duration is passed since last frame was displayed, people expect another frame to be insert with compensated object position, which will be displayed for min(default_duration, x). And if x is still larger than default_duration, again it needs to be splitted into two parts - default_duration and x'. The process is recursive. What if we don't do this and only makes the last frame stay longer? Suppose in an extremely ugly case, TDecimate did a 10000-in-100000 decimate on a 109999 frame clip, and lost 1000 frames in the last section. Now you make all the frames last 40ms, but to compensate the lost display time, force the last frame stay for 40*(9/10)*1000=36000ms. If the pictures contain constant moving object, how can you explain the terrible frame duration to others? Telling them they're watching Evangelion? Of cause such bad case would never take place in TDecimate, but it can easily explain why your solution is not good for the cases in which frame duration needs to be increased.

Sadly in most cases tdecimated scenes need compensated frames, because TDecimate usually removes more frames than expected. If it changed its logic to keeping more frames than expected, your thought of only changing the duration of last frame was good enough for me.

TFM's u/b matching on scenecut is totally different thing. Whether using u/b matching or not, in theory, does not depend on whether the p/c-matching incapable frame can be matched by u/b or not, but depends on whether the frame is film or video type. Being incapable for normally matching does not change whether it is supposed to have a right p/c matching if not cut in scene change or it is a real interlaced video type frame. Usually it is not a bad edit, but just a consequence of being cut on scene change so that the to-be-normally-matched half field is missing by cutting. It is still film type frame, so even if you might get more information of one more field by half field compensation, it is generally not a good way to do so. But if that single frame is really video type, it should be deinterlaced than using u/b matching, naturally. Actually from that we can see, it is better to do things correct than to use a trick to make things more attractive but incorrect.
头像
zhongpang
帖子: 93
注册时间: 2011-10-23 20:45

Re: BillyTC mod - 删除24d重复帧并保持音画同步

感谢,
尝试下修改脚本看看能否可以实现

回到 “AviSynth”