21.09.2025, 18:41
Still sticking with my guess that the text lines look so horrible because the two VHS heads where vertically wobbling slightly out of sync from each other, I tried separating the top/bottom fields into a single stream with one field per frame, stabilize that, then reweave back to proper interlaced.
Interestingly, when I used ffmpeg to separate fields, then hybrid stab(mirror=15, dxmax=0, dymax=2, range=1) on that new half-height field-per-frame file, then finally ffmpeg again to weave back to interlaced, I was happy with the result and it did look improved to my eye.
I thought I should be able to accomplish the same thing with a custom VS filter, so tried this script (below) inserted just before the End event, but the results did not turn out the same at all. Any thoughts why this may be?
The difference is quite obvious when you apply to the clip of the VHS warning that I linked previously.
These are the ffmpeg commands I used to separate fields and weave:
Interestingly, when I used ffmpeg to separate fields, then hybrid stab(mirror=15, dxmax=0, dymax=2, range=1) on that new half-height field-per-frame file, then finally ffmpeg again to weave back to interlaced, I was happy with the result and it did look improved to my eye.
I thought I should be able to accomplish the same thing with a custom VS filter, so tried this script (below) inserted just before the End event, but the results did not turn out the same at all. Any thoughts why this may be?
core.std.LoadPlugin(path="C:/Program Files/Hybrid/64bit/vsfilters/MiscFilter/MiscFilters/MiscFilters.dll")
core.std.LoadPlugin(path="C:/Program Files/Hybrid/64bit/vsfilters/DenoiseFilter/ZSmooth/zsmooth.dll")
core.std.LoadPlugin(path="C:/Program Files/Hybrid/64bit/vsfilters/Support/libmvtools.dll")
core.std.LoadPlugin(path="C:/Program Files/Hybrid/64bit/vsfilters/Support/DePan.dll")
import stabilize
clip = core.std.SeparateFields(clip, tff=True)
clip = core.std.AssumeFPS(clip=clip, fpsnum=60000, fpsden=1001)
clip = stabilize.Stab(clp=clip, mirror=15, dxmax=0, dymax=2, range=1)
clip = core.std.DoubleWeave(clip, tff=True)
clip = core.std.SelectEvery(clip, 2, 0)
clip = core.std.AssumeFPS(clip=clip, fpsnum=30000, fpsden=1001)
The difference is quite obvious when you apply to the clip of the VHS warning that I linked previously.
These are the ffmpeg commands I used to separate fields and weave:
ffmpeg -i <in> -vf separatefields -c:v ffv1 -r "60000/1001" -c:a copy -map_metadata -1 <out>
ffmpeg -i <in> -vf weave -c:v ffv1 -r "30000/1001" -c:a copy -map_metadata -1 <out>