Log in

View Full Version : How to fix the syntax for this script?


sonic41592
14th November 2020, 01:04
I'm trying to write a script that will output a 24/30/60 fps vfr video and frame timestamp text file. The process uses the two pass TIVTC mode to make a lossless 24/30 fps vfr video, but leaves interlaced frames untouched through TFM PP=1.

Pass 1
ffmpegsource2("S01E01.vob",rffmode=1)

TFM(PP=1,output="TFM.txt",slow=2)
TDecimate(mode=4,output="TDecimate.txt")

Pass 2
ffmpegsource2("S01E01.vob",rffmode=1)

TFM(PP=1,input="TFM.txt",slow=2)
TDecimate(mode=5,hybrid=2,vfrDec=1,input="TDecimate.txt",tfmin="TFM.txt",mkvOut="Timecodes.txt",tcfv1=false)


The script I'm trying to write will take the lossless output from the second pass and the Timecodes.txt to check what the "single frame" frame rate is for each frame, check if it's combed, and deinterlace it if it is leaving two frames for interlaced 30 fps sections (TFM leaves interlaced frames in 24 fps sections as well, but those fields can be discarded). It will then write the timestamp for the frame in a text file. Here's the mockup code I have written so far:

LWLibavVideoSource("out.mkv",Repeat=true)
SSS="""
frames = FrameCount #Find number of frames
frametime = 0 #Set initial frame time
writefile("newtimes.txt","frametime")
tcds = RT_ReadTxtFromFile("Timecodes.txt")
for (i=0, frames-2) {
t0 = RT_TxtGetLine(tcds, Line = i+4)
t1 = RT_TxtGetLine(tcds, Line = i+5)

instfr = 1/(0.001*(t1-t0)) #Find instantaneous frame rate

if (instfr > 23 && instfr < 25) { #Check for 24fps frame
if (iscombedTIVTC() = true) {
QTGMC( SourceMatch=3, TR0=2, TR1=2, TR2=0, Lossless=2 ).SelectEven() #Deinterlace combed 24fps frame
}
else { #passthrough noncombed 24fps frames
}
frametime = frametime + 1001/24000
writefile("newtimes.txt",frametime)
}
else if (instfr > 17 && instfr < 19) { #Check for 18fps frame
if (iscombedTIVTC = true) {
QTGMC( SourceMatch=3, TR0=2, TR1=2, TR2=0, Lossless=2 ).SelectEven() #Deinterlace combed 18fps frame
}
else { #passthrough noncombed 18fps frames
}
frametime = frametime + 1001/18000
writefile("newtimes.txt",frametime)
}
else if (instfr > 29 && instfr < 31) { #Check for 30fps frame
if (iscombedTIVTC = true) {
QTGMC( SourceMatch=3, TR0=2, TR1=2, TR2=0, Lossless=2 ) #Deinterlace combed 30fps frame into two 60fps frames
frametime = frametime + 1001/60000 #Add frame times
writefile("newtimes.txt",frametime)
frametime = frametime + 1001/60000
writefile("newtimes.txt",frametime)
}
else { #passthrough noncombed 30fps frames
frametime = frametime + 1001/30000
writefile("newtimes.txt",frametime)
}
}
else { #Passthrough for other framerates
if (iscombedTIVTC = true) {
QTGMC( SourceMatch=3, TR0=2, TR1=2, TR2=0, Lossless=2 ).SelectEven()
}
else{ #passthrough
}
frametime = frametime + 1/instfr
writefile("newtimes.txt",frametime)
}

}
"""
ScriptClip(SSS)

Here are a couple samples with telecine and normal interlacing:

Samples (https://mega.nz/folder/1Th2jJ6L#iIAK6gbWO553Dwk6E-_eNg)

It errors (unsurprisingly) around the iscombedTIVTC argument. Any help with syntax or how to get this working would be greatly appreciated. I also noticed that QTGMC uses the wrong field first when deinterlacing a single frame, causing out of order frames, so any suggestions there would be helpful too. Thanks!

Gavino
14th November 2020, 18:00
...
if (iscombedTIVTC() = true) {
...
if (iscombedTIVTC = true) {
...
if (iscombedTIVTC = true) {
...
if (iscombedTIVTC = true) {
...
...
It errors (unsurprisingly) around the iscombedTIVTC argument.

I haven't tried to understand your script, but those lines certainly look wrong.
They should all be:
if (iscombedTIVTC() == true) {
or, more simply,
if (iscombedTIVTC()) {

StainlessS
14th November 2020, 18:32
As Gavino said.
I'm currently looking at it.

StainlessS
15th November 2020, 01:50
I'm not 100% sure what you are tryin to do, and dont think you are gonna get there anyway.

but, something like this.

TIMECODES = "Timecodes.txt"
NEWTIMES = "Newtimes.txt"
START_DUMMY = 3 # 3 dummy lines at start
END_DUMMY = 4 # 4 dummy lines at end

##############
RT_DebugF("DBGVIEWCLEAR") # Clear DebugView Window

LWLibavVideoSource("out.mkv",Repeat=true)

QCLIP = QTGMC( SourceMatch=3, TR0=2, TR1=2, TR2=0, Lossless=2 ) #Deinterlace combed 24fps frame
ECLIP = QCLIP.SelectEven

frames = FrameCount #Find number of frames
frametime = 0 #Set initial frame time

RT_Writefile(NEWTIMES,"%f",frametime,Append=False)
RT_DebugF("FrameTime=%f\n",frametime)

Lines = RT_FileQueryLines(TIMECODES) - (START_DUMMY + END_DUMMY) # Line count excluding dummies

tcds = RT_ReadTxtFromFile(TIMECODES ,Lines=Lines,Start=START_DUMMY) # Start after initial 3 dummies

Duration = 1000000.0 # WE DONT KNOW YOUR DURATION, so 1000000.0 millisecs is dummy here. NEEDS fixing


SSS="""
n = current_frame
t0 = RT_TxtGetLine(tcds, Line = n+0).Value
t1 = (n+1==FrameCount) ? Duration : RT_TxtGetLine(tcds, Line = n+1).Value

instfr = 1.0/(0.001*(t1-t0)) # Find instantaneous frame rate

RT_DebugF("%d] t0=%f t1=%f instfr=%f",n,t0,t1,instfr)

if (instfr > 23 && instfr < 25) { # Check for 24fps frame
if (iscombedTIVTC) {
ECLIP # Deinterlace combed 24fps frame
} else { # passthrough noncombed 24fps frames
}
frametime = frametime + 1001.0/24000.0
} else if (instfr > 17 && instfr < 19) { # Check for 18fps frame
if (iscombedTIVTC) {
ECLIP # Deinterlace combed 18fps frame
} else { # passthrough noncombed 18fps frames
}
frametime = frametime + 1001.0/18000.0
} else if (instfr > 29 && instfr < 31) { # Check for 30fps frame
if (iscombedTIVTC) {
QCLIP # Deinterlace combed 30fps frame into two 60fps frames
frametime = frametime + 1001.0/60000.0 # Add frame times
RT_Writefile(NEWTIMES,"%f",frametime,Append=True)
RT_DebugF("%d] FrameTime=%f",n,frametime)

frametime = frametime + 1001.0/60000.0
}
else { # passthrough noncombed 30fps frames
frametime = frametime + 1001.0/30000.0
}
} else { # Passthrough for other framerates
if (iscombedTIVTC) {
ECLIP
} else{ # passthrough
}
frametime = frametime + 1.0/instfr
}
RT_Writefile(NEWTIMES,"%f",frametime,Append=True)
RT_DebugF("%d] FrameTime=%f\n",n,frametime)
Return Last
"""

Scriptclip(SSS)

Return Last

/*
NOTES.
ScriptClip CANNOT change width/height/FrameCount/FrameRate, Output is same as Input. [EDIT: Is fixed before frame serving starts]
In scriptclip, the Frame returned from eg QCLIP is frame n ie current_frame.
Avisynth internally Supports Constant Framerate Only.

As clip frame timestamp gets bigger, so precision when adding small instantaneous frame duration will suffer.
(only 24 bits for precision for single precision float)
*/



EDIT:
To ALL, what happened to the text edit box, its disappeared and havta click Reply To thread where you get that nasty narrow box which is pretty useless. [or does it only happen to me]

EDIT: My Fault, I had clicked and closed (somehow) Quick Reply

sonic41592
15th November 2020, 01:51
Thanks for pointing that out! To clarify things a little more, for each frame, it's supposed to take the corresponding line from the Timecodes.txt and the next line in order to calculate the frame rate for that single frame.
# timecode format v2
# TDecimate v1.0.6 by tritical
# Mode 5 - Auto-generated mkv timecodes file
0.000000
41.708333
83.416667
125.125000
166.833333
200.200000
233.566667
266.933333
300.300000
333.666667
375.375000
417.083333
458.791667
500.500000
542.208333
So the first frame will take 0.000000 and 41.708333 -> 1/(.001*(41.708333-0.000000))=23.976, the second frame would be 41.708333 and 83.416667 -> 1/(0.001*(83.416667-41.708333))=23.976 etc. Then it will check if the frame is interlaced. Interlaced 30fps frames need to be deinterlaced into two 60fps frames and write the newtimecodes.txt twice advancing the timestamp 1/60th of a second. Interlaced 24fps sections are mistakes from TIVTC, so they just need to be deinterlaced into one frame and write the timestamp file forward 1/24th of a second. Noninterlaced frames can be passed through and advance the timestamps the right amount. So the output video file will be muxed with the newtimestamps.txt to make noninterlaced 24/30/60 video. Can the string output from RT_ReadTxtFromFile be turned into a float by RT_NumberValue/1000000 to get the millisecond values back? It'll also have to use a deinterlacer that can choose the bottom field first, because QTGMC uses TFF causing out of order frames when testing a single interlaced frame.

EDIT: Reading StainlessS' notes, ScriptClip won't work for what I'm wanting because the number of frames will be larger on the output since interlaced 30fps secions are deinterlaced to 60 fps. Also 24 bit precision for float wouldn't be enough since the timestamps would be in the 1273313.708333 millisecond range. Could this work somehow in C++ as a dll plugin?

StainlessS
15th November 2020, 02:15
Could this work somehow in C++ as a dll plugin?
Avisynth supports only constant FrameRate, thats why they do that stuff in encoder.
[I've never touched VFR, others might(read probably will) be better informed].

EDIT: CPP plugin could calc and write newtimes, and also new framecount in constructor.
CPP GetFrame() could perhaps create clip using QCLip and EClip and the stuff created in the constructor.

Dont ask me for this, I have zero interest in VFR, and have no spare time in the foreseeable future,
I really should not have taken the time for this thread, I am mucho busy doing other stuff, sorry.

sonic41592
15th November 2020, 02:42
No worries! Your help was really appreciated, I'm sorry it didn't work out after you spent time on it. Good luck on your endeavors!