Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
29th June 2011, 23:30 | #1 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,695
|
Automatically fix dups followed (eventually) by drops
Overview
A friend wanted a portion of this video of his son placing third in the state 3200 M track race: 2011 CIF Track & Field Championships Keepvid wasn’t an option; WMRecorder and similar tools didn’t work. So, I had to use Camtasia (or SnagIt) which records screen video. Unfortunately, despite reading all the hints, I didn’t get smooth video. Here’s a link to a really bad section of the video: 10 Second Problem Clip If you want to try the script, download this clip. If you want to suggest a better way to capture the video, click on the first link above. The first sixty frames (of the downloadable clip) has a huge number of problems, and then things settle down. Problem I Tried To Solve In a nutshell, the video randomly (i.e., not periodically) drops frames and then, to restore sync, duplicates a frame, usually within about five frames of the dup. So, here's the statement of the problem: I want to delete the dups and simultaneously synthesize a frame to insert at the point where the video jumps. Prior art This has been discussed before, both here: Filter to remove duplicate frames and here: Inverse of Decimate Also, MugFunky, a long time ago wrote a script for detecting and replacing exact duplicates: FillDrops However, his problem only included duplicates: apparently the capture mechanism did not drop frames to make up for the dups. Solution Didée created a nifty script for interpolating missing frames. This can be found in the "Inverse of Decimate" link above. However, there were three things missing in that script that I needed for my situation:
[edit]Click on the following link to go to updated script later in this thread: Later version of script Code:
# Based on script created by Didée # Modified by John Meyer on June 29, 2011 # # Script overview # # Create interpolated frames a 2x original frame rate using MVTools2 # Detect jumps # Create white mask at each jump point; black mask for all other frames # Repeat each frame of original video and use mask to "choose" between original video, or motion estimated video # Decimate exactly 50% to get back to original frame rate. # This decimation removes the dup frames from the original video and also the dups created by repeating each frame of original video. # However, at each point where motion-estimated frame is inserted, no decimation occurs. Thus, if dups=drops, and the drop happens # within < "cycle" (TDecimate parameter) of the dup, the dup will be removed and the drop will be filled. # If no drops or dups occur within "cycle," then no motion estimation happens, and decimation merely gets back to original, # unchanged video. loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll") #Threshold for detecting jumps. Increase to catch more jumps. Should always be less than 1.0 JumpThresh = 0.74 showdot = true # true for troubleshooting; otherwise, false #SetMTMode(5,4) global source=AVISource( "E:\CIF Track\3200-Complete (edited).avi" ).ConvertToYV12 #SetMTMode(2) global BlackFrame = BlankClip( source, Color=$000000 ) global WhiteFrame = BlankClip( source, Color=$FFFFFF ) super = showdot ? source.subtitle("***").MSuper(pel=2) : source.MSuper(pel=2) bvec = MAnalyse(super, overlap=4, isb = true, search=4, dct=5) fvec = MAnalyse(super, overlap=4, isb = false, search=4, dct=5) double = source.MFlowFps(super, bvec, fvec, num=60, den=1, blend=false) #Remove comment from ShowMetrics, and change "return final" to "return test" to look at metrics in order to determine proper JumpThresh #test=ShowMetrics(source) #Generate a white or black frame, depending on frame difference BWMask=GenerateMask(source) #Generate the 2x framerate mask needed to choose the motion-estimated frames themask = interleave(BlackFrame,trim(BWMask,1,0)) #Merge double framerate from original with motion-esimated frames, but only where there are jumps #(i.e., original frames are used except at jump points) interleave(source,source).mt_merge(double,themask,luma=true,U=3,V=3) #Decimate RequestLinear final=tdecimate(display=false,mode=1,cycleR=10,cycle=20) # Decimate half of all frames (set to twice the length of "normal" dup/drop cycle) #--------------------- #Alternate two-pass approach to decimation #Pass 1 #RequestLinear(debug=false) #final=tdecimate(display=false,mode=4,output="e:\metrics.txt") #Pass 2 (remember to un-comment "requestlinear") #RequestLinear #final=tdecimate(display=false,mode=2,rate=30,input="e:\metrics.txt",maxndl=20) #--------------------- return final #return stackvertical(source,final) #---------------- #This function displays the YDiff value that will be used for detecting big jumps function ShowMetrics (clip c) { fixed=source.ScriptClip("Subtitle(String( \ ((YDifferenceFromPrevious(selectevery(source, 1, 2)) + \ YDifferenceFromPrevious(selectevery(source, 1, 1)) + \ YDifferenceFromPrevious(selectevery(source, 1,-1)) + \ YDifferenceFromPrevious(selectevery(source, 1,-2)) ) / 4 ) / \ (YDifferenceFromPrevious(source) + 0.01) \ ))") return fixed } #---------------- #This function returns a white clip whenever a big jump is detected; otherwise a black clip is returned function GenerateMask (clip c) { MyMask=c.ScriptClip(""" \ ((YDifferenceFromPrevious(selectevery(source, 1, 2)) + \ YDifferenceFromPrevious(selectevery(source, 1, 1)) + \ YDifferenceFromPrevious(selectevery(source, 1,-1)) + \ YDifferenceFromPrevious(selectevery(source, 1,-2)) ) / 4 ) / \ (YDifferenceFromPrevious(source) + 0.01) <= JumpThresh \ ? WhiteFrame : BlackFrame """) return MyMask } Last edited by johnmeyer; 30th June 2011 at 08:28. Reason: Fixed wrong explanation of dups & drops (under "Problem ..." heading); Added link to later script |
Thread Tools | Search this Thread |
Display Modes | |
|
|