View Full Version : How to duplicate a frame after scene change?
coolgit
6th October 2024, 16:44
I badly need to add duplicate frame for the first frame after each scene change.
I can not find anything that does it.
My starting point is using https://forum.doom9.org/showthread.php?t=182392
There is a line in the code else if(pDf>pTh) { SC = 0 Start S_Frames!=""?RT_WriteFile(S_Frames,"%d",n,Append=true):NOP} # SOS
Tried to use duplicateframe() or insertframex from https://forum.videohelp.com/threads/407293-ReplaceFrameX-InsertFrameX or trim() in the above code.
The problem is none will work as i can't get it to use the current frame number after a scene change.
As far as i know the above 3 examples requires me to physically put a frame number in.
Is there any other way of doing this?
johnmeyer
6th October 2024, 17:14
I had this code lying around from something I wrote years ago. It's pretty close to what you want and all you should have to do is change the parameters of the ConditionalFilter call. It's scene detection (YDifferenceToNext) is pretty primitive, but may be sufficient for what you are doing.
#Script to replace frames at scene changes
global scenethreshold=15
source=AVISource("E:\fs.avi").killaudio().convertTOYV12()
# Temporarily un-comment next line to display the average luma value on screen to help determine threshold value
#ScriptClip(source,"Subtitle(String(YDifferenceToNext(source) ))" )
fixed = ConditionalFilter(source, trim(source,1,0), source, "YDifferenceToNext()>scenethreshold", "greaterthan", "0")
return fixed
johnmeyer
6th October 2024, 19:43
BTW, the code in my previous post will replace the frame. You said you wanted to add a frame. If that is really what you meant, how will you deal with the audio? Adding frames will cause the audio to drift out of sync.
coolgit
6th October 2024, 20:38
Tried many variation and doesn't work as intended. It will duplicate a frame but the frame after is missing.
Yes I need to add frames and audio isn't an issue as pal and ntsc audio are already different. My issue is two files, one has thousands of random exact duplicates and makes for jerky viewing but good quality video and file 2 is frame accurate with no duplicate but crap quality video. I am importing frames from file 1 to file 2 but need the frames from file 1 to match file 2 because of the audio in file 2.
I used ExactDedup to remove the duplicates from file 1 but that also removed duplicates from beginning of scene change and end of scene change. Therefore a block of 5000 frames in file 2 is correct but file 1 has 4980 ish. Hence inserting back a frame after scene change by duplicating the first frame would fix it.
In my first post there is a line n = current_frame and I trying to use n to duplicate a frame but all duplicate method I've seen requires a number (int) as n gives invalid argument error.
johnmeyer
6th October 2024, 20:59
... one has thousands of random exact duplicates and makes for jerky viewing but good quality video ...Gosh, if that's your problem you might find my old FillDropsI() function useful. It detects exact duplicate frames (or near-exact, depending on settings) and replaces them with a motion-estimated frame. The results are usually quite satisfactory.
However, you do need to make sure you don't also have jumps (i.e., missing frames). If you do, all your work will not help you and you'll need to use something like this script I created years ago:
Automatically fix dups followed (eventually) by drops (https://forum.doom9.org/showthread.php?t=161758)
So, just run FillDrops() on your good capture and you may not have to do any other work.
johnmeyer
6th October 2024, 21:00
Oops. Forgot to provide the FillDropsI() code.
#This script finds exact duplicate frames and then interpolates a new frame in place of the duplicate.
#It works on interlaced video.
loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")
setMTMode(5)
source=AVISource("e:\frameserver.avi").ConvertToYV12.killaudio()
setMTMode(2,0)
output=filldropsI(source)
#stackvertical(source,output)
return source
#-------------------
function filldropsI (clip c, float "thresh")
{
thresh = Default(thresh, 0.1)
even = c.SeparateFields().SelectEven()
super_even=MSuper(even,pel=2)
vfe=manalyse(super_even,truemotion=true,isb=false,delta=1)
vbe=manalyse(super_even,truemotion=true,isb=true,delta=1)
filldrops_e = mflowinter(even,super_even,vbe,vfe,time=50)
odd = c.SeparateFields().SelectOdd()
super_odd=MSuper(odd,pel=2)
vfo=manalyse(super_odd,truemotion=true,isb=false,delta=1)
vbo=manalyse(super_odd,truemotion=true,isb=true,delta=1)
filldrops_o = mflowinter(odd,super_odd,vbo,vfo,time=50)
evenfixed = ConditionalFilter(even, filldrops_e, even, "YDifferenceFromPrevious()", "lessthan", String(thresh))
oddfixed = ConditionalFilter(odd, filldrops_o, odd, "YDifferenceFromPrevious()", "lessthan", String(thresh))
Interleave(evenfixed,oddfixed)
Weave()
}
Even though it is designed for interlaced, you can use it without modification on progressive video.
coolgit
6th October 2024, 21:19
I don't want to replace duplicates. I'll try to be clearer. eg.
file 1 and file 2 have different amount of frames. file 1 would have 5050ish frames and file 2 5000. After exactdedup file 1 goes down to 4980ish therefore i need to put back 20ish frames to match file 2 5000 frames.
My original attempt was to change else if(pDf>pTh) { SC = 0 Start S_Frames!=""?RT_WriteFile(S_Frames,"%d",n,Append=true):NOP} # SOS
toelse if(pDf>pTh) { SC = 0 Start S_Frames!=""?duplicateframe(n).RT_WriteFile(S_Frames,"%d",n,Append=true):NOP} # SOS
n = current_frame but duplicateframe won't accept n
Frank62
7th October 2024, 16:46
Don't think you won't realise the added frames. I tried similar things long ago for other reasons, and i remember I always realized added frames at the end or beginning of a scene as jerky. Very annoying, if you once realise, you always do - 500 times...
I'd therefore suggest to improve the ExactDedup before. Why, by the way, does this delete frames at scenechanges? Is it meant to do so? and if, why? Isn't that an error?
Edit: I just remembered, that I had some good results in the past with MULTIDECIMATE, in the naive mode. But you have to handle longer black screens separately.
johnmeyer
7th October 2024, 22:20
I'll bet that if you post 25-30 seconds of the better quality, but jerky video, it will show not only duplicates, but also drops. This is almost always the case because duplicates are usually inserted to make up for a dropped frame that happens during streaming or capture. If I am right, you are dealing with a lot more than you think you are.
The problem is so common that I created a script to deal with it. Although I never completely perfected the script, it still usually does a very good job of dealing with this very common problem:
Automatically fix dups followed (eventually) by drops (https://forum.doom9.org/showthread.php?t=161758)
The title is actually incorrect because in most situations the dropped frame happens first and then the duplicate is inserted in order to keep the audio in sync. My script actually doesn't care, but I point that out only to make sure you understand why duplicates happen.
I did later try to perfect the script, but wasn't able to overcome a basic limitation in TDecimate, a limitation that is inherent in the problem of decimating unwanted frames, not necessarily in the TDecimate code.
Need help "perfecting" script to delete drops and dups (https://forum.doom9.org/showthread.php?t=183351)
If I am correct -- and I bet that I am -- even if you get rid of duplicates, your video is still going to look jerky because of the drops.
RetsimLegin
8th October 2024, 09:05
I have encountered a similar situation and have never found a reliable way to "automatically" resolve what you describe. If it's important enough a project, I'd resort to a wholly manual process to find and fix missing and duplicated frames. If you have a frame-accurate source as a reference it is made somewhat easier.
I use a fairly old version of Adobe Premiere Elements as a video editor. I suspect that many similar apps will enable much the same process.
I'd place the "faulty" but otherwise good quality video on the bottom layer, and the frame-accurate one above it. I'd set the frame accurate file to 50% opacity and then apply an invert filter to make it a negative. And then find a spot such as an easily identifiable hard scene change near the start where I can synchronise the two such that, as that point (only, for now) the one file is exactly above the other. So now, assuming the two are approximately the same size, colour balance and contrast, any synchronised frames should appear (almost) plain grey. That makes differences easy to spot and thereby fix.
And then I'd play it and watch for the (now easily seen) drifts in synchronisation. The frame-accurate layer is left untouched as a reference. Differences are fixed in the "faulty" file, either by interpolating* any missing frames mid-scene, adding a simple duplicate at a scene change to maintan sync, and/or deleting any duplicates. Such that, after possibly several hours of work, the "faulty" file is a frame-accurate match for the other one. And then, hide or remove the transparent inverted content and render what's left.
Long, slow job. But, it works.
========
* Simple way: mix the frame before and frame after. Better, but more complex way: use an AI based tool to make a version of the faulty file with double the frame rate (i.e. every pair of frames is interpolated to produce an extra frame that is midway between the two) and using those extra frames to fill in gaps.
takla
9th October 2024, 10:56
I don't want to replace duplicates. I'll try to be clearer. eg.
file 1 and file 2 have different amount of frames. file 1 would have 5050ish frames and file 2 5000.
At only 5000 frames I'd cut all scenes manually by hand and insert the wanted frames. Could probably do it in under an hour in adobe premier, which is probably less time then what you have already spent on finding some magical auto-script.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.