Page 1 of 2

FPS Converter unable to convert 300p source to 50i

Posted: Sun Mar 07, 2021 9:52 am
by Silicon
Hi
I have a workflow with FPS Converter processor involved to convert video content, captured by mobile devices (like iPhones etc.) with higher framerates in progressive mode into XDCAM HD422 1080/50i.
I FPS conversion of a videoclip in 240 fps VFR, captured by iPhone 11 Pro, has failed with error message "Validate: ConvertFPS: New frame rate too small. Must be greater than 400.0000 Increase or use 'zone='."

Video props:
Width: : 1 920pixely
Hight : 1 080pixely
Aspect Ratio : 16:9
FrameRate Mode : VFR
Frame rate : 240,341 FPS
Minimum frame rate : 200,000 FPS
Maximum frame rate : 300,000 FPS

Are there some limits in FPS Converter processor in terms of maximum input video Framerate or FPS conversion ratio?
Thank for advice.

P.S. Thanks for new version of FFAStrans and WebInterface.

Re: FPS Converter unable to convert 300p source to 50i

Posted: Sun Mar 07, 2021 11:04 am
by admin
Hi Silicon,

Yes there is an (inbuilt AviSynth) limit but I'll take a look at a better way to deal with the larges fps conversions steps. In the mean time you can try and add a "Custom AviSynth script" node before fps conversion with:

m_clip = SelectOdd(m_clip)
Return m_clip


This will effectively halve your framerate and thus reduce the gap. However, if framerate conversion is the only filter you use then you can try and remove the "A/V Media" decoder all together and go straight to the encoder. This way you should be able to bypass AviSynths fps conversion limitation.

-steinar

Re: FPS Converter unable to convert 300p source to 50i

Posted: Mon Mar 08, 2021 9:26 am
by Silicon
Hi Steinar
Thanks for advice. I'll give a try.
BR,

Re: FPS Converter unable to convert 300p source to 50i

Posted: Tue Mar 09, 2021 2:03 pm
by FranceBB
The problem is not the frame rate conversion per se, but rather the type of conversion that is going on here.
I'm pretty sure you're using blending, which means that the input is indexed and then Avisynth tries to "blend" together frames, namely the frame immediately after the current frame and the one immediately before and "overlaps" them to reduce the framerate. Of course, Avisynth is telling you "hey, I can't do that, mate, 'cause there aren't enough frames, I would have to do the blending of the blending, so overlap more than two frames".
Blending (overlapping) more than two frames leads to a pretty bad frame rate conversion as it's going to produce something that looks like a ghosting artifact sort of speak.
If you use a custom Avisynth Script, you can see what I mean by doing:

Code: Select all

m_clip=ConvertFPS(m_clip, 200).ConvertFPS(134).ConvertFPS(90).ConvertFPS(60).ConvertFPS(50)
return m_clip
The output is gonna be awful.
On the other hand, "ChangeFPS" will just drop frames to 50p so that the encoder can then detect 50p and divide in fields to get a 25i:

Code: Select all

m_clip=ChangeFPS(m_clip, 50)
which is the same as just setting the GUI without flagging the "blend" option, however... we have a problem here.
What ChangeFPS() does is just to either duplicate or drop frames, so in this case it seems ok to say "ok, we have lots of frames, we can drop some to get to 50p without any issues, right?"
WRONG!
If they really were 300fps, sure, but that's not the case here, 'cause our source is VFR!
VFR, Variable Frame Rate, means that the phone captured a certain amount of FPS depending on the motion of the scene, so there can be as many as 300fps but there could also be as little as 24fps in some scenes (no, mediainfo can't be trusted for max/min VFR info).
So... what happens is that Avisynth can only handle CFR, therefore indexers like ffms2 find the AVERAGE framerate and index it as such with the relative fpsnum and fpsden to create a constant frame rate A/V stream.
The problem with this is that the scenes in which there are less FPS than the average are gonna be duplicated and the scenes in which there are more FPS than the average, those are gonna be dropped.
In other words, we have a stuttering mess and if we add ChangeFPS() we might end up taking the dups and discarding the good frames or vice versa, it's totally random and out of luck, which can't be the case.
Since extracting the VFR stats and finding a way to feed Avisynth with the stats and work with them is complicated and gets even worse if you're trying to do this automatically, the thing to do here is using TDecimate and force our way out with the desired framerate.

Code: Select all

m_clip=TDecimate(m_clip, mode=2, rate=50)
return m_clip
What TDecimate is gonna do is find all the input frames, divide each one of them in blocks and macroblocks, assign a number to each one of them and then compare each frame with the next one and with the next one etc. Then, it will drop those with the lowest value, so with the lowest motion, which means that it's hopefully gonna drop the dups and, when there are no dups, it's going to drop those with less motion, to make the overall experience smooth.

Side note: please note that TDecimate is part of the TIVTC package and if you don't have Avisynth installed, you'll need to manually load it after downloading it, like:

Code: Select all

LoadPlugin("C:\example\TIVTC.dll")
and then use the command I wrote.

I hope it helps.

Cheers,
Frank

Re: FPS Converter unable to convert 300p source to 50i

Posted: Wed Mar 10, 2021 8:41 am
by Ghtais
ohh , very helpfull !!! thank you for sharing France BB :)

Re: FPS Converter unable to convert 300p source to 50i

Posted: Thu Mar 11, 2021 10:05 am
by Silicon
@FranceBB
Thanks for excellent explanation! It is clear that you're AviSynth expert 8-)

Your assumption is correct - I'm using blending in FPS Converter processor.

We will evalute the solution you've proposed.
Thnak you"

Re: FPS Converter unable to convert 300p source to 50i

Posted: Tue Jun 01, 2021 9:28 pm
by Ghtais
Hi there,

I played a little bit with Tdecimate to transcode some VFR iphone footage into 25p CFR. It works great when the video is above 25 FPS but when frame rate drop down below 25 it stop working.
Do you know if there is a filter that could do the job for this case ? decimate when there is too much frame and recreate when there is not enough frame with an intelligent algorithm that select only very similar frame.

Thank you

Re: FPS Converter unable to convert 300p source to 50i

Posted: Wed Jun 02, 2021 6:41 am
by FranceBB
Well you could first duplicate everything to the average framerate or higher and then use this to detect the previously duplicated frames and replace them with interpolated ones automatically.

Code: Select all

super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=2, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
forward_vectors = MAnalyse(super, isb = false, delta=2, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70)
ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", ".001")


Disclaimer: written on my phone while I'm on the bed during a national holiday before going to work and having coffee. Not compiled and untested but I'm fairly confident it's gonna work. ;)

Re: FPS Converter unable to convert 300p source to 50i

Posted: Wed Jun 02, 2021 3:18 pm
by Ghtais
ok thank you for your help :)
I will study that and try to do something with it :)

Many thanks !!

Re: FPS Converter unable to convert 300p source to 50i

Posted: Thu Jun 03, 2021 6:46 am
by FranceBB
No worries. :)
Oh and of course in FFAStrans you would still need the m_clip thing as return so it would be something like this:

Code: Select all

#First we duplicate
ChangeFPS(m_clip, 50)

#Then we use motion compensation to detect which ones are dups
super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=2, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))
forward_vectors = MAnalyse(super, isb = false, delta=2, blksize=16, blksizev=16, searchparam=3, plevel=0, search=3, badrange=(-24))

#Now we apply linear interpolation to replace the duplicate with interpolated frames
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70)
ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", ".001")

#we return the result
m_clip=last
return m_clip


It should work.
Alright, time to get my coffee. ;)