View Full Version : How to produce variable framerate output from a hybrid source?
bruno321
26th December 2019, 09:23
I'm loading a .d2v file into avisynth using MPEG2Source. It's at 25fps. Some sections are progressive, and some are purely interlaced. I'd like to manually discriminate them, and run QTGMC() in the ones of the second type, finishing with something with variable framerate. I looked around in this forum but only found really old information, so I'd like to know what's the best and most up-to-date method for doing this kind of thing.
In case it matters, I use the latest Avisynth+, together with avspmod and megui.
Thanks in advance.
Sharc
26th December 2019, 10:11
I would avoid to create VFR material. It may just cause playback issues or problems for future editing, depending on the device.
Do you want to keep it as mpeg2 or is changing to AVC or HEVC an option?
If you want progressive output I would deinterlace (or bob deinterlace) everything using QTGMC and encode with x264 (AVC) as progressive.
Or encode everything as interlaced using x264 (MBAFF).
I doubt whether a more sophisticated method would really show a benefit.
It's not an answer to your question though …….
bruno321
26th December 2019, 10:41
I want to encode it with x264.
But I wouldn't want to have 1 out of 2 frames being duplicates in the progressive parts (which would happen if I QTMGC them)... it bloats the file unnecessarily, and wouldn't it make it judder as well?
FranceBB
26th December 2019, 11:33
I want to encode it with x264.
But I wouldn't want to have 1 out of 2 frames being duplicates in the progressive parts (which would happen if I QTMGC them)... it bloats the file unnecessarily, and wouldn't it make it judder as well?
Side note:
With an high enough reframe, x264 motion compensation will work really well in compressing identical frames and it won't stutter more than it does when you watched it on air: for instance if you live in a PAL region and you get a mixed progressive flagged as interlaced and truly interlaced stream, they will both be blindly bobbed to 50p by your TV.
Encoding VFR:
If you wanna try to encode in VFR, though, you can try to write your Avisynth Script, bob-deinterlace everything to 50p and then open the .avs file as input in ffmpeg with something like:
FFmpeg.exe -i "AVS_Script.avs" -vsync 2
Followed by the libx264 parameters.
Vsync 2 will drop frames when necessary and will be perfect for your needs. I also suggest you to use mkv as a container for your VFR stream as it handles VFR nicely.
This is the description of the vsync parameter:
-vsync parameter
Video sync method.
0, passthrough
Each frame is passed with its timestamp from the demuxer to the muxer.
1, cfr
Frames will be duplicated and dropped to achieve exactly the requested constant frame rate.
2, vfr
Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp.
drop
As passthrough but destroys all timestamps, making the muxer generate fresh timestamps based on frame-rate.
-1, auto
Chooses between 1 and 2 depending on muxer capabilities. This is the default method.
Please note that players don't have to be VFR aware by H.264 specifications and may not be able to reproduce a file. I tested some VFR files on TV sets and I can tell you that not all of them are compatible. Just encode a minute or so as test wit trim() and check whether your TV plays the file or not and eventually choose what to do.
Cheers,
Frank.
Sharc
26th December 2019, 11:48
I want to encode it with x264.
But I wouldn't want to have 1 out of 2 frames being duplicates in the progressive parts (which would happen if I QTMGC them)... it bloats the file unnecessarily, and wouldn't it make it judder as well?
No bloating to be expected as x264 is very efficient in encoding duplicated frames. Almost nil overhead. Actually, the file might even become significantly smaller (for same crf) due to the cleaning/denoising effect of QTGMC. Just run a test and be surprised ;)
As I wrote I would expect much more problems with a variable frame rate (VFR) attempt and avoid it unless you have a very specific reason for it.
Overdrive80
26th December 2019, 15:51
http://avisynth.nl/index.php/VFR
This is a 2-pass mode. Add this to your script:
TFM(mode=1,output="tfm.txt")
TDecimate(mode=4,output="stats.txt")
Open this and play through it in VirtualDub. Then close it, comment those lines out (or start a second script) and add:
TFM(mode=1)
TDecimate(mode=5,hybrid=2,dupthresh=1.0,input="stats.txt",tfmin="tfm.txt",mkvout="timecodes.txt")
Load and encode.
It is automate mode, if you want manual mode then:
1. Setting sections, you should noted parts.
YourLoader(".\VideoFile1.d2v", info=3)
ColorMatrix(hints=true, threads=0,interlaced=true)
2. With noted sections [f.e.: material FILM (0-38811), material NTSC (38812,0)], deinterlacing:
YourLoader(".\VideoFile1.d2v", info=3)
ColorMatrix(hints=true, threads=0,interlaced=true)
part1=trim(0,38811).tfm().tdecimate()
part2_in=trim(38812,41089)
part2=part2_in.QTGMC( Preset="very Slow", EdiMode="EEDI2",fpsdivisor=2).assumefps(part1.framerate)
part1++part2
3. Generate timecodes:
YourLoader(".\VideoFile1.d2v", info=3)
ColorMatrix(hints=true, threads=0,interlaced=true)
part1=trim(0,38811).tfm().tdecimate()
part2_in=trim(38812,41089)
part2=part2_in.QTGMC( Preset="very Slow", EdiMode="EEDI2",fpsdivisor=2).assumefps(part1.framerate)
part1++part2
WriteFile(last, "timecodesv1.txt" ,""" "# assume 29.970029" """, append=false)
WriteFile(last, "timecodesv1.txt" ,""" "0," """, "part1.framecount", """ "," """, "part1.framerate")
WriteFile(last, "timecodesv1.txt" , "part1.framecount+1", """ "," """ , "part1.framecount+part2.framecount-1",\
""" "," """, "part2_in.framerate")
return last
4. Muxing on mkv.
Manual mode is generic example, you must modify according to your needs.
hello_hello
26th December 2019, 22:19
For PAL I don't think there's a way to automate the process (the TIVTC plugin can do it for NTSC as long as you only de-interlace to 29.970fps). I'll confess though, I don't fully understand how the method FranceBB suggested earlier works.
If there's only a small number of progressive sections I'd probably just run QTGMC on the whole thing, and sometimes even for the progressive sections I use QTGMC().SelectEven() or something similar to clean them up a bit, even when the output will be VFR, but my process is something like this, which can be fairly time consuming.
Create the initial script and open it with MeGUI's AVS Cutter. Use it's preview to find the interlaced and progressive sections and specify the start and end frames for each, then save the "cuts" as MeGUI calls them. From there you add the required de-interlacing to each section and the end result will be something like this.
For this example QTGMC() is used on it's own to de-interlace the interlaced sections. I've followed the progressive sections with AssumeFPS(50), as Avisynth requires a constant frame rate. Temporarily adding GreyScale() sometimes makes the next step a little easier.
film=Last
__t0 = film.trim(0, 25849).QTGMC()
__t1 = film.trim(25850, 52749).AssumeFPS(50).GreyScale()
__t2 = film.trim(52750, 58007).QTGMC()
__t3 = film.trim(58008, 66063).AssumeFPS(50).GreyScale()
__t4 = film.trim(66064, 67577).QTGMC()
__t5 = film.trim(67578, 70921).AssumeFPS(50).GreyScale()
__t6 = film.trim(70922, 73651).QTGMC()
__t0 ++ __t1 ++ __t2 ++ __t3 ++ __t4 ++ __t5 ++ __t6
# crop and/or resize or whatever else here as required.
When that's done you need to go through the process again to find the frame numbers for the timecodes file. They'll change, as for example, the first section now has twice the number of frames so it'll be frames 0 to 51699. I generally find the new frame numbers by opening the scrpt again with the AVS cutter and adding a second lot of trims. If stepping through the script is slow, you can temporarily replace QTGMC with Yadif(Mode=1).
Because the "film" sections are greyscale it makes it harder to mistake an interlaced section for progressive etc and end up with a mess. I'm roughly calculating frame numbers here, so they mightn't be exact, but the second lot of trims added to the script would look like this:
film=Last
__t0 = film.trim(0, 51699)
__t1 = film.trim(51700, 78598)
__t2 = film.trim(78599, 89112)
__t3 = film.trim(89113, 97167)
__t4 = film.trim(97168, 100193)
__t5 = film.trim(100194, 103536)
__t6 = film.trim(103537, 108994)
__t0 ++ __t1 ++ __t2 ++ __t3 ++ __t4 ++ __t5 ++ __t6
Next step is to create a timecodes file using the frame numbers from just the progressive (25fps) sections. It's a text file.
# timecode format v1
Assume 50
51700, 78598, 25
89113, 97167, 25
100194, 103536, 25
Or you can do it the other way around:
# timecode format v1
Assume 25
0, 51699, 50
78599, 89112, 50
97167, 100193, 50
103537, 108994, 50
Once you've created the timecodes file you can delete the second lot of trims from the script, remove GreyScale() from the progressive sections and supply x264 with the timecodes for VFR encoding by adding the following to the custom command line section in MeGUI's x264 encoder configuration (obviously with the appropriate file path and file name).
--tcfile-in "D:\Timecodes.txt"
If the encoder is writing directly to MKV there's no need to add the timecodes file again when muxing the audio etc with the encoded video. If the encoder is writing a raw h264 stream, I'm not sure.
It can be a lot of work when there's many interlaced and progressive sections, but that's how I do it when I'm really keen.
bruno321
28th December 2019, 07:07
Thank you all for the suggestions. I have some testing to do :)
kuchikirukia
31st December 2019, 02:50
The only time I had to deal with a hybrid progressive/interlaced source I went and doubled the progressive frames so the entire thing was 60fps. There should be a thread started by me where I was asking for help.
Here it is:
https://forum.doom9.org/showthread.php?t=173966
DeInt=QTGMC(preset="Very Slow")
A=ConditionalFilter(last,DeInt.SelectEven,last,"IsCombedTIVTC","=","true")
B=ConditionalFilter(last,DeInt.SelectOdd,last,"IsCombedTIVTC","=","true")
Interleave(A,B)
bruno321
9th November 2020, 14:14
I now have another kind of hybrid source. 29.97fps, some sections need tfm().tdecimate(), other sections need QTGMC(), so this would be a hybrid of some parts in 23.976fps and some parts in 59.94fps. Is there some way to achieve this automatically? And if not, what's the best manual way to do it?
EDIT: a better forum search led me to https://forum.doom9.org/showthread.php?p=1713315 or https://forum.doom9.org/showthread.php?t=173147, will dig into that.....
EDIT, some time later: Damn, is it really that hard? :D
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.