Log in

View Full Version : Help writing: Black Frame Insertion.


James Freeman
10th January 2014, 18:23
Any one can please write a small script to insert a black frame (or two) every movie frame in avisynth in "ffmpeg raw video filter".

I have a 72Hz monitor and typical 24fps MKV movies,
so I want to insert a 1 black frames after 2 movie frames.
or 2 black frames after 1 movie frame.

I have tried this, but no luck.
MPC-HC just freezes.
Original = Avisource("Yourmovie.avi")
Black=Original.Blankclip()
Interleave(Original,Black,Original,Black)


This script need to JUST WORK, no conversions, or encoding, or waiting.
Just enable avisyth and play the movie.
Just like Smooth Video Project.

Something like this:
TestUfo BFI Demo (http://www.testufo.com/#test=blackframes&count=3&equalizer=1)

Yes, I know it will flicker.
I want to see how a motion blur-less movie looks like.

Thanks you.

poisondeathray
10th January 2014, 19:13
One way is to use stickboy's applyevery.dll using InterleaveEvery()

eg. 1 black frame , 2 film frames, 1 black frame, 2film frames .... etc


WhateverSource()
AssumeFPS(24000,1001)
orig=last

#make a black clip the same characteristics of original
black=blankclip(orig)

#make a clip of the original with duplicates
orig
changefps(48000,1001)
double=last

InterleaveEvery(double, black, 3, 0)



This will give you 71.928 fps because of ~23.976 * 3. If you want 24.0fps and 72.0fps , change the AssumeFPS() line to 24




so I want to insert a 1 black frames after 2 movie frames.
or 2 black frames after 1 movie frame.

EDIT: maybe I'm not understanding the problem correctly ? Did you want sequential film frames or repeat pairs of the same frame? Then it would be easier to do 1 movie frame and 2 black frames


e.g. this will give 1 movie frame, 2 black frames, 1 movie frame, 2 balck frames....etc


WhateverSource()
AssumeFPS(24000,1001)
orig=last

#make a black clip with same characteristics, but 2x the length of original
black=blankclip(orig)
black2=black++black

InterleaveEvery(black2, orig, 3,0)
AssumeFPS(whatever) #set it to whatever speed

James Freeman
10th January 2014, 19:22
Thanks poisondeathray

Repeat pairs of the same frame.
Each letter is the same frame from the movie.

Like this:
(A,A,Black) (B,B,Black) (C,C,Black) etc...

Or:
(A,Black,Black) (B,Black,Black) (C,Black,Black) etc...


EDIT:

I get and error:
There is no function named: 'WhateverSource()'

poisondeathray
10th January 2014, 19:26
ok, I edited the post above - I think both cases are covered now, except the first example starts with a black frame (e.g. you can use trim(1,0) to start with film frames)

poisondeathray
10th January 2014, 19:31
I get and error:
There is no function named: 'WhateverSource()'



Change it to the appropriate source filter

e.g AVISource() for .avi movie

James Freeman
10th January 2014, 19:33
Its an MKV.

What do I write for that?

poisondeathray
10th January 2014, 19:35
DirectShowSource("video.mkv")

or

FFVideoSource("video.mkv")
ffms2.dll is required (external plugin)

oh wait, is this script only (are you playing the .avs in a media player) ? or is this the ffdshow avisynth box ?

James Freeman
10th January 2014, 19:39
I play my movies in MPC-HC.

I enable external filters: ffdshow raw video filter.
In ffdshow I engage the Avisynth box and enter your script.

Hope to see an actual BFI script that works.


DirectShowSource("video.mkv")

Do I need to type the filename of the movie?
Why, its already open by the MPC-HC player.

poisondeathray
10th January 2014, 19:48
I'm not sure how to use the ffdshow version for avisynth . I think there is an avisynth box where you can type the same code, minus that 1st line source filter (because video is already loaded through directshow and decoded with ffdshow)

EDIT: it won't work with this method playing through ffdshow and enabling the avisynth box - because "orig" references the original video (when creating the black clip for insertion) . It's basically using 2 clips as input - I don' t know how ffdshow will handle that unless there is a way to use the avisynth source filter in ffdshow


Alternatively, you can just play the .avs script . That works for sure

James Freeman
10th January 2014, 19:54
Ok I removed the WhateverSource() line.

Now there is an error with: AssumeFPS().
It says: Invalid arguments to function 'AssumeFPS'


EDIT:

I tried .avs with this:

DirectShowSource("E:\Videos\X.mkv")
AssumeFPS(24000,1001)
orig=last

#make a black clip with same characteristics, but 2x the length of original
black=blankclip(orig)
black2=black++black

InterleaveEvery(black2, orig, 3,0)
AssumeFPS(72) #set it to whatever speed

Error:
DirectShowSource: Could not open as Video or Audio.
DirectShowSource could not open file E:\Videos\X.mkv: Pins cannot connect due to not supporting the same transport

Any thoughts?

poisondeathray
10th January 2014, 19:59
If you manually enter and change the bankclip specs (dimensions, fps) , each time (it might change for different movies) , You should still be able to do it with ffdshow . Make the lenght very long (so you don't run out of black frames), or 2x the source frames at least . It's not as elegant as the other method which automatically makes the black frames the properties as the sourceclip

black = blankclip(length=big number , width=1920, height=1080, fps=23.976)

poisondeathray
10th January 2014, 20:00
Ok I removed the WhateverSource() line.

Now there is an error with: AssumeFPS().
It says: Invalid arguments to function 'AssumeFPS'


You have to enter the numerator and denominator

e.g
~23.976 would be AssumeFPS(24000,1001)
24.0 would be AssumeFPS(24,1)

turbojet
10th January 2014, 23:41
Change directshowsource() to ffdshow_source() or simply remove the line and check add ffdshow source.

Directshowsource() in this case would be loading an external file.

James Freeman
11th January 2014, 09:59
Change directshowsource() to ffdshow_source() or simply remove the line and check add ffdshow source.


PERFECT !!!!

Finally it works.

Many thanks.

:thanks:

James Freeman
11th January 2014, 11:04
Putting the flickering and epilepsy aside.


Results:

Watching a 24fps movie on a LCD (TV, Monitor) is a major problem to cinematic experience.
The key word is BLUR.

Because of the 24fps of the movie, in moving or panning scenes the distance between the previous frame and the next one is big,
LCD has a characteristics of retaining the previous image on screen, this resulting in two images far apart at the same time on screen.
Which looks like a HUGE BLUR when the camera moves.

I always thought it was the motion blur of the camera shutter (which is how movies are shot)....
NO, it is my LCD that causes this unnecessary motion blur.

For example:
In The Hobbit, there is a scene where the camera scrolls across the middle earth map with text on it.
Without the BFI script I see blurry text and its almost un-readable.
With the BFI scrips I can read the text perfectly as though is was static.

If anyone familiar with this site: http://www.blurbusters.com/
Its a great site to ready all about Motion Blur, Backlight Strobbing, Black Frame Insertion.

I didn't think this would be useful with 24 fps on a 72Hz LCD because frame rate is already slow.
I was mistaken, It actually worse because of the bigger distance between objects/text in moving frames resulting in a bigger/wider motion blur.

Now I need to buy a 120Hz strobing backlight monitor.

wonkey_monkey
11th January 2014, 16:06
How about inserting a darkened, but not completely black, frame? You might find a better balance between flicker and blur that way.

vampiredom
13th January 2014, 04:48
Perhaps I am way off the mark here, but have you considered trying InterFrame (with max. perf / min. quality kinds of settings) to simply convert it from 23.976 fps to 72 fps? It might not look that great ... but I have to imagine it would not look worse than inserted black frames.

James Freeman
7th November 2014, 13:55
Bump.
I have a great idea and a challenge which I could not do by myself.
I need your help.

Now I have a 60Hz monitor but I still like the black frame insertion trick for minimum motion blur.

The idea is to have the ability to choose how much frames of the original movie will be in a second and how much of a blackclip will be in the same second.

For example: 10/60 original 50/60 blackclip.
or 24/60 orig & 36/60 black.

The goal is to stay within the 60fps limit but have the ability to choose how much of the frames are the movie and how much are blackclip.
The output should be 60fps no matter what.

Any help will be very much appreciated.

johnmeyer
7th November 2014, 18:08
I understand the theory behind adding black frames, but it still seems like a bad idea because it is not at all the same thing that happens with projected film. With a real film projector, the film is advanced every 1/24 of a second. However, during the time the film is advanced, the shutter on the projector is closed, resulting in blackness being projected. However, depending on the "shutter angle" (the shutter is a rotating disk with holes, and the angle of the pie shaped shutter that blocks the light is the shutter angle), that blackness will last only a fraction of the 1/24 of a second.

By comparison, the method being discussed here produces blackness of much longer duration, equal to the entire period that a frame is projected. So the first problem with what is being done here is that the duration of the blackness will be way too long.

The second issue is that most movie projectors actually open and close the shutter two more times while each frame is being projected. This is done to increase the flicker rate above the frequency that the human eye can perceive. It turned out, in the early days of movies, that flicker at 16, or 18 or (eventually) 24 fps gave people headaches. Increasing the flicker to 72 fps (or 72 Hz, if you prefer), solved that problem.

However, it is an interesting AVISynth challenge to do this. I would have used RT_Stats for this project, but that's just me.

creaothceann
7th November 2014, 18:55
The easiest solution for black frame insertion:

Interleave(last , BlankClip(last )) # 60fps display, 30fps source
Interleave(SelectEven, BlankClip(SelectEven)) # 60fps display, 60fps source (halves effective framerate)

Each frame recorded by the camera is just one infinitely small point on the timeline. As johnmeyer said, ideally you'd show one source frame for one display frame and then only black frames for the remaining frames in an interval:

0_____1_____2_____3_____ 24fps source
012345678901234567890123 144fps display

This reduces the brightness though. Alternative:

0_0_0_1_1_1_2_2_2_3_3_3_ 24fps source
012345678901234567890123 144fps display

Interleave(last, last, last, last, last, last)
Interleave(SelectEven, BlankClip(SelectEven))

James Freeman
7th November 2014, 19:32
Thanks.

The problem is I can't use:
orig=last
black=blankclip(orig)
interleave(orig ,black)


because it creates a 48fps or 72fps clip.

I need to have control of how much of the 60fps are the original movie and how much are black frames.
A simple fraction is all I need.

For example:
12/60 orig + 48/60 black.

How do I create a blankclip 1.5 the lenght of the original?
Something like this: black=blankclip(orig, length=orig*1.5)

johnmeyer
7th November 2014, 20:07
I think you need to figure out how to create a variable frame rate result. You'd create a 72 fps movie, but have the variable frame rate show the blank frames for 1/72 of a second, and then each actual frame of movie for 2/72 of a second. The result would be one movie frame every 1/24 of a second, just like the original movie, but with a portion of the frame black.

Projector Shutter (http://en.wikipedia.org/wiki/Movie_projector#Shutter)

However, I have no idea how to deal with variable frame rates inside of AVISynth, or how to encode the result. I am not saying it cannot be done, only that I don't know how to do it. Perhaps others can help with this.

poisondeathray
7th November 2014, 22:39
Thanks.

The problem is I can't use:


because it creates a 48fps or 72fps clip.

I need to have control of how much of the 60fps are the original movie and how much are black frames.
A simple fraction is all I need.

For example:
12/60 orig + 48/60 black.




That's not the problem. You can use AssumeFPS() to assume any framerate

The problem is getting the distribution and ratio correct expressed as a variable.


How do I create a blankclip 1.5 the lenght of the original?
Something like this: black=blankclip(orig, length=orig*1.5)


One way to do it is just set the values expressed as the original framecount. This is not necessarily a good way to do it if your intention is to make a function later

e.g

l=orig.framecount+orig.framecount/2

blankclip(orig, length=l)

James Freeman
8th November 2014, 05:50
Will it be easier if the fraction is made of only twelves which are exactly half of the original fps?

for example:

12 Movie, 12+12+12 black = 60
12+12 movie, 12+12 black
12+12+12 movie, 12 black

The real problem is to maintain 60 fps in a second, 16.7ms each frame.

AssumeFPS(12) should play the movie half-speed?
If so, the AssumeFPS function does not work properly with ffdshaw+avisynth because the video stays in 24fps and plays normal speed.
Maybe its tied to the audio?

poisondeathray
8th November 2014, 05:58
AssumeFPS has an argument sync_audio. It works with avisynth, but I don't know if it will work with the way you are using ffdshow
AssumeFPS(12,true)

It changes the sample rate of audio, so you may want to use SSRC() to change it back (or you might not, depends what are doing)

Or if you don't need audio

KillAudio()

poisondeathray
8th November 2014, 06:02
Will it be easier if the fraction is made of only twelves which are exactly half of the original fps?

for example:

12 Movie, 12+12+12 black = 60
12+12 movie, 12+12 black
12+12+12 movie, 12 black

The real problem is to maintain 60 fps in a second, 16.7ms each frame.


But you don't want them consecutive like that right ? Didn't you want them interleaved?

I don't think you want 12 frames, then 48 black in a row ?

eg. You want 1 movie, 4 black, 1 movie, 4 black, etc..... or whatever ratio dependent on the value of the variable

AssumeFPS(60) will change it to 60FPS, but it will be a speedup or slowdown effect if you have the same framecount since no frames are added or deleted - so it will be 16.7ms per frame

ChangeFPS(60) will also change it to 60FPS, but will add duplicates. For example if you had 24p, you would get 3:2 duplicates . You probably want some variation on what ChangeFPS does, but with interleaved clips (black, normal)

James Freeman
8th November 2014, 06:18
You are right, 12 frames, then 48 black in a row is NOT what I want.
1 movie, 4 black, is the right way.

The movie needs to be converted to 60fps first, the a black clip should be created with 60fps, only then they should interleave.
AssumeFPS(60) does nothing, the movie still plays at 42ms (24fps).

http://www.mediafire.com/convkey/f10e/6hmqhivioh6takefg.jpg

I have a great pulldown script that creates 60fps from 24fps with a single blended frame in the middle which I will use instead of AssumeFPS(60) which does not work.
#Nees MaskTools2.
#Replacement for Smooth Motion in MadVR
a = SelectEvery(2, 0)
b = SelectEvery(2, 1)
ab = mt_average(a, b, u=3, v=3)
Interleave(a, a, ab, b, b)

Now its only a problem how to interleave the two 60fps videos so that I can control the Orig/Black frame ratios.

What I have Now:
#Nees MaskTools2.
#Replacement for Smooth Motion in MadVR
a = SelectEvery(2, 0)
b = SelectEvery(2, 1)
ab = mt_average(a, b, u=3, v=3)
Interleave(a, a, ab, b, b)

orig=last
black=blankclip(orig, black)

Interleave(orig)

The problem with "Interleave(black, orig)" with two 60fps videos is that it creates a 120fps video (8ms).

poisondeathray
8th November 2014, 06:23
AssumeFPS definitely works with avisynth. It's ffdshow that is the problem. What was the reason for using ffdshow ? You can play .avs scripts directly in mpchc

But your script doesn't look right in the screenshot either

Orig=last
AssumeFPS(60)

?


No clip is called
In "normal" avisynth , you have to call the clip . Normally "last" is assume with everything, including AssumeFPS(), but no clip was initiated so you would normally get an error .

Orig=last

Orig
AssumeFPS(60)

poisondeathray
8th November 2014, 06:35
The problem with a generic function is rounding math and odd numbers. If you have only a few set cases , then it's easier

e.g for your 12fps case


orig=colorbars(pixel_type="yv12").assumefps(12).showframenumber()

b=blankclip(orig)

interleave(orig,b,b,b,b)



That does exactly film, b,b,b,b, film, b,b,b,b .... and the FPS is 60.0 exactly . You can check it in vdub. The key to that is the AssumeFPS() function . If you can't get it working with ffdshow, then you can't do it this way or you have to use avs directly

James Freeman
8th November 2014, 06:42
The reason is that ffdshow includes the "Avisource" command using the currently playing file in mpc-hc.
Don't mind the orig=last, its a leftover. I does not work with simple AssumeFPS(60) neither.

Back to topic, I have two 60fps videos, one is original, one is black.
I need to create a blend of the two and maintain 60fps and speed.

Maybe this cadence (a, a, ab, b, b) can be played with?

poisondeathray
8th November 2014, 06:45
The reason is that ffdshow includes the "Avisource" command using the currently playing file in mpc-hc.
Don't mind the orig=last, its a leftover. I does not work with simple AssumeFPS(60) neither.

Back to topic, I have two 60fps videos, one is original, one is black.
I need to create a blend of the two and maintain 60fps and speed.

Maybe this cadence (a, a, ab, b, b) can be played with?

So you're giving up on the other approach ? If you just play the avs script it will work. Or maybe someone that uses ffdshow knows of a workaround. Bascially you need AssumeFPS to work in ffdshow if you want any of those to work

For this next one, do a better job of defining "blend" or what you want exactly; because it usually means something like 50% opacity so a mix of a, b . So each frame will be darker

James Freeman
8th November 2014, 06:54
So you're giving up on the other approach ? If you just play the avs script it will work. Or maybe someone that uses ffdshow knows of a workaround. Bascially you need AssumeFPS to work in ffdshow if you want any of those to work

For this next one, do a better job of defining "blend" or what you want exactly; because it usually means something like 50% opacity so a mix of a, b . So each frame will be darker

I'm willing to try the script approach.
will this work: orig=Avisource("C:\path\abc.mkv") ?
EDIT: It does not work with MKV's that's why.

You are right, my terminology is flawed, I meant interleave not blend.

poisondeathray
8th November 2014, 06:56
It won't work because AVISource() is for AVI video files. It's been a while but this was discussed on page 1 . You need another source filter like DirectShowSource, FFVideoSource, etc.... But otherwise it will work if you play the .avs directly

AssumeFPS is "required" for this because it "resets" the framerate of the interleaved clips to whatever you want. So you can always get 60.0 (or any number). There might be a workaround for ffdshow, it might be worth asking in another subforum here

James Freeman
8th November 2014, 06:59
Thanks

oddball
15th January 2017, 15:56
Did anyone come up with a working solution to this?