Posts: 123
Threads: 26
Joined: May 2023
right now after processing a footage with Hybrid .. i need to use a Linux script (FFMPEG + blackdetect filter) to cut in pieces the clip removing the black frames interruptions (i use a blackmagic intensity PRO that generate BLACK frames when the signal is too much "noised" ) and after that i need to merge all these parts to create an output without any BLACK frame..
is possible to used the "blackdetect" filter or something similar on Hybrid to AUTOMATICALLY remove all black frames from footage? (or maybe <5% black frames)
thank you!
Posts: 10.617
Threads: 57
Joined: May 2017
No, Hybrid has no filter which would:
a. remove black frames
and
b. cut the audio to keep the source sync
Cu Selur
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.
Posts: 123
Threads: 26
Joined: May 2023
thank you Cu Selur
Posts: 10.617
Threads: 57
Joined: May 2017
Cu = see you
Selur <- the Name
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.
Posts: 10.617
Threads: 57
Joined: May 2017
18.05.2023, 18:35
(This post was last modified: 18.05.2023, 18:36 by Selur.)
Can you share a small sample of such a clip (with the black frames)?
I suspect that one could use something like:
def replace_low_luma_frames(clip, threshold):
# Calculate average luma for each frame
luma = core.std.ShufflePlanes(clip, planes=0, colorfamily=vs.GRAY)
avg_luma = core.std.PlaneStats(luma)
# Create a mask of frames with luma below the threshold
low_luma_mask = core.std.Expr(avg_luma, f'x {threshold} <')
# Get frame before for replacement
frame_before = core.std.Trim(clip, 0, clip.num_frames - 1)
# Replace frames with low luma using frame_before
replaced = core.std.MaskedMerge(clip, frame_before, low_luma_mask)
return replaced
clip = replace_low_luma_frames(clip, 30)
(code is untested, not totally sure whether it works
)
to replace each frame which luma is below 30 (or lower) with the frame before it.
Assuming there are only single black frames in the soure and thus singe duplicates that one could use 'FillDrops' to replace the inserted duplicates with interpolated frames.
Cu Selur
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.
Posts: 258
Threads: 34
Joined: Aug 2022
try it - pulldown="telecine" or "interpolation"
+ tune: Grain or PSNR or SSIM
Posts: 123
Threads: 26
Joined: May 2023
OMG very thank you helping me!
here a small interlaced sample:
www.wcn.it/black.avi
i have a lot of old footages with these black frames (generated by the blackmagic intensity pro card) (there are more than 1 black consecutive frames BTW.. in the sample maybe not.. but there are)
here there are a lot of black "zones" :
www.wcn.it/black2.avi
Posts: 10.617
Threads: 57
Joined: May 2017
28.05.2023, 13:59
(This post was last modified: 28.05.2023, 14:00 by Selur.)
Okay, here's what you can do.
- Start Hybrid
- load clip
- set 'Filtering->(De-)Interlace/Telecine->Overwrite input scan type to' to 'top field first'
- optional: enable 'Filtering->(De-)Interlace/Telecine->QTGMC Vapoursynth->Bob'.
- go to 'Filtering->Vapoursynth->Custom->Insert Before' set it to 'FillDrops', enable the text box below it.
- in this custom section you now enter:
# replace a black frames with last frame that was not black
def ReplaceBlackFrames(clip, thresh=0.1, debug=False):
core = vs.core
if not isinstance(clip, vs.VideoNode):
raise ValueError('This is not a clip')
def selectFunc(n, f):
if f.props['PlaneStatsAverage'] > thresh or n == 0:
if debug:
return core.text.Text(clip=clip,text="Org, avg: "+str(f.props['PlaneStatsAverage']),alignment=8)
return clip
toReplace = n
for i in range(n)[::-1]:
if clip.get_frame(i).props['PlaneStatsAverage'] <= thresh:
continue
# remove current replace with frame before
start = core.std.Trim(clip, first=0, last=n-1)
r = core.std.Trim(clip, first=i, last=i)
end = core.std.Trim(clip, first=n+1)
replaced = start + r + end
break
if debug:
return core.text.Text(clip=replaced,text="Replaced, avg: "+str(f.props['PlaneStatsAverage']),alignment=8)
return replaced
clip = core.std.PlaneStats(clip)
fixed = core.std.FrameEval(clip, selectFunc, prop_src=clip)
return fixed
clip = ReplaceBlackFrames(clip, thresh=0.1, debug=False)
If you now look at the Vapoursynth Preview all black frames should be replaced with the last non-black frame.
- optional: if there were no multiple black frames in a row, enable 'Filtering->Vapoursynth->Misc->FillDrops', this will then replace the duplicate with an interpolated version.
Cu Selur
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.
Posts: 123
Threads: 26
Joined: May 2023
OMG!!! very very very thank you!!!
Posts: 10.617
Threads: 57
Joined: May 2017
29.05.2023, 14:19
(This post was last modified: 29.05.2023, 14:19 by Selur.)
Happy that helped, note that this will only work on clips that do not start with black frames.
Cu Selur
----
Dev versions are in the 'experimental'-folder of my GoogleDrive, which is linked on the download page.