.

Restoring Video8/Hi8 tapes

Once you succeed at this, the world of digital video manipulation opens up.  The AviSynth script below attempts to correct camera shaking, chroma denoiser and remove edge enhancement artefacts (halo).

Notes

  • Script is written for 32-bit AviSynth 2.6 MT
  • Plugins can be found at avisynth.nl
  • The VidMod plugins are part of QTGMC.
  • The script below assumes that the DVD is ripped, and the resulting .vob file is indexed using dgindex.
  • To transfer the PAL Video8 tapes to PAL DVD, I used SunrayVideo in the US.

AviSynth Script:

# http://www.coertvonk.com/technology/videoediting/restoring-video8-hi8-10849

Global cwd = "C:\Path\To\File\Root\"  # UPDATE!
Global pd = cwd + "plugins\"  # UPDATE!

function loadSource(string "fname") {
    SetMTMode(5, 2)
    SetMemoryMax(2048)
    LoadPlugin(pd + "dgindex\DGDecode.dll")
    LoadPlugin(pd + "colormatrix\ColorMatrix.dll")
    LoadPlugin(pd + "nicaudio_206\NicAudio.dll")
    V=DGDecode_mpeg2source(cwd + fname + ".d2v", info=3).ConvertToYV12(interlaced=true).AssumeTFF() 
    A = NicAC3Source(cwd + fname + " T80 2_0ch 256Kbps DELAY -40ms.ac3")  # UPDATE!
    c = AudioDub(V, A)
    DelayAudio(c, -0.040)
    SetMTMode(2)
    return c
}

function restoreChroma( clip c ) {
    LoadPlugin(pd + "cnr2_v261\cnr2.dll")
    Cnr2(c)
}

function stabFast( clip c, int "range", int "dxmax", int "dymax", int "mirror" ) {  # http://avisynth.nl/images/Stab.avsi
    LoadPlugin(pd + "rgTools\RgTools.dll")
    LoadPlugin(pd + "depanestimate192\DePanEstimate.dll")
    LoadPlugin(pd + "depan1101\DePan.dll")
    range = default(range, 1)
    dxmax = default(dxmax, 4)
    dymax = default(dymax, 4)
    mirror = default(mirror, 0)
    temp = c.TemporalSoften(7,255,255,25,2)
    inter = Interleave(temp.Repair(c.TemporalSoften(1,255,255,25,2)), c)
    mdata = DePanEstimate(inter, range=range, trust=0, dxmax=dxmax, dymax=dymax)
    DePan(inter, data=mdata, offset=-1, mirror=mirror )
    SelectEvery(2,0)
}

function stabSlow( clip c) {
    LoadPlugin(pd + "depanestimate192\DePanEstimate.dll")
    LoadPlugin(pd + "depan1101\DePan.dll")
    maxstabH = 20 maxstabV = 20  # maximum values for the stabiliser (in pixels) 20 is a good start value
    trust = 1.0  # scene change detection, higher= more sensitive
    cutoff = 0.5  # no need to change this, but you can play with it and see what you get
    stabRef = c.crop(20,20,-20,-20).colorYUV(autogain=true).crop(20,60,-60,-60)
    mdata = DePanEstimate(stabRef, trust=trust, dxmax=maxstabH, dymax=maxstabV)
    return DePanStabilize(c, mdata, cutoff=cutoff, dxmax=maxstabH, dymax=maxstabV, method=0, mirror=15)
}

function fastDeinterlace( clip c ) {
    LoadPlugin(pd + "nnedi3\nnedi3.dll") 
    LoadPlugin(pd + "yadifmod_v1\yadifmod.dll") 
    edi=nnedi3(c, field=-2) 
    yadifmod(c, mode=1, edeint=edi) 
}

function slowDeinterlace( clip c ) {  # see http://avisynth.nl/index.php/QTGMC
    LoadPlugin(pd + "mvtools-2.6.0.5\mvtools2.dll")  # Mod16 version of MVTools 2
    LoadPlugin(pd + "masktools_VitMod\mt_masktools-26.dll")
    LoadPlugin(pd + "nnedi3_VitMod\nnedi3.dll")
    LoadPlugin(pd + "RemoveGrain_VitMod\RemoveGrainSSE2.dll")
    Import(pd + "QTGMC-3.33d\QTGMC-3.33d.avsi")
    c = QTGMC( c, Preset="Slow", EdiThreads=4 )
    return Distributor(c) # This line may or may not be necessary, try removing it and see if you get more speed
}

function deHalo( clip c ) {
    LoadPlugin(pd + "masktools_VitMod\mt_masktools-26.dll")
    Import(pd + "dehalo_alpha\DeHalo_alpha.avsi")
    return DeHalo_alpha(c)
}

function vividLessYellow( clip c ) {
    c = Tweak(c, cont=1.15, sat=1.05)
    return ColorYUV(c, off_u=3, off_v=0)
}

function autoLevels( clip c ) {
    LoadPlugin(pd + "autolevels_06\autolevels.dll")
    c = AutoLevels(c, output_low= 6, output_high= 235)
    return ColorYUV(c, autowhite=true, autogain=false)
}

function deGrain( clip c ) {
    Import(pd + "LSFmod\LSFmod.v1.9.avsi") 
    Import(pd + "GrainFactory3\GrainFactory3.avsi") 
    LoadPlugin(pd + "dgindex\DGDecode.dll")
    LoadPlugin(pd + "colormatrix\ColorMatrix.dll")
    LoadPlugin(pd + "nicaudio_206\NicAudio.dll")
    LoadPlugin(pd + "nnedi3\nnedi3.dll") 
    LoadPlugin(pd + "yadifmod_v1\yadifmod.dll") 
    LoadPlugin(pd + "removegrain-1.0b\RemoveGrainSSE2.dll") 
    LoadPlugin(pd + "removegrain-1.0b\RepairSSE2.dll") 
    LoadPlugin(pd + "mvtools-v2.5.11.3\mvtools2.dll") 
    LoadPlugin(pd + "masktools-26-for-2.6alpha4\mt_masktools-26.dll") 
    LoadPlugin(pd + "addgrainc-1.7.0\addgrainc.dll") 
    super = MSuper(c, pel=2, sharp=1)  # prepace multilevel (hierarchical scaled) frames data
    mvbw2 = super.MAnalyse(isb = true, delta = 2, overlap=4)  # generate backward motion vectors between the frame n and n-2 or n+2
    mvbw1 = super.MAnalyse(isb = true, delta = 1, overlap=4)  # generate backward motion vectors between the frame n and n-1 or n+1
    mvfw1 = super.MAnalyse(isb = false, delta = 1, overlap=4)  # generate forward motion vectors between the frame n and n-1 or n+1
    mvfw2 = super.MAnalyse(isb = false, delta = 2, overlap=4)  # generate forward motion vectors between the frame n and n-2 or n+2
    MDegrain2(c, super, mvbw1, mvfw1, mvbw2, mvfw2, thSAD=200) 
}

function upScale(clip c, int "height") {
    Spline36resize(round(height / height() * width() / 8) * 8, height)  # upscale
    LSFMod(Smode=5, strength=70)  # sharpen
    GrainFactory3(g1str=4, g2str=6, g3str=8)  # add some HD grain
}


# prepare source

src = loadSource("DVD\video1")  # UPDATE!

# start processing

dst = src
dst = false ? fastDeinterlace(dst) : slowDeinterlace(dst)
dst = SelectEven(dst)
dst = restoreChroma(dst)
dst = stabSlow(dst)
dst = deHalo(dst)
dst = vividLessYellow(dst)
# dst = autoLevels(dst)
dst = deGrain(dst)
cropLeft = 14 cropTop = 6 cropRight = 18 cropBtm = 18  # typical VHS overscan, keep the results mod8
dst = crop(dst, cropLeft, cropTop, -cropRight, -cropBtm)  
src = crop(src, cropLeft, cropTop, -cropRight, -cropBtm)

# compare side-by-side

# COMMENT OUT THE NEXT LINE FOR FINAL VERSION
dst = stackhorizontal(subtitle(src, "original", size=28, align=8), subtitle(dst, "restored", size=28, align=8))
SetMTMode(1) # multithreaded Avisynth only - end of script p1
GetMTMode(false) > 0 ? distributor(dst) : dst # multithreaded Avisynth only - end of script
Coert Vonk

Coert Vonk

Independent Firmware Engineer at Los Altos, CA
Welcome to the things that I couldn’t find.This blog shares some of the notes that I took while deep diving into various fields.Many such endeavors were triggered by curious inquiries from students. Even though the notes often cover a broader area, the key goal is to help the them adopt, flourish and inspire them to invent new technology.
Coert Vonk

Latest posts by Coert Vonk (see all)

1 comment to Restoring Video8/Hi8 tapes

  • Yann

    Greetings ,

    First happy new year since I just came to discover this page on January 1 !

    I, too, am after preserving as much I can from 8/Hi8 (family) tapes.

    Yet I made a DV copy using a Sony D8 to benefit from the built-in ‘poor man’ mini-TBC and CNR.

    Then I used QTGMC for deinterlace while using Cineform as intermediate codec . I like the idea of
    Wavelet (vs block size DCT) and transposition to the 10 bit 4:2:2 Chroma format for any filtering event …

    Now I noticed your script is quite sharp and smart and that you are fully aware of QTGMC even up in its
    latest mod releases (3.33s) . I then must conclude that you get better results from your script ( vs plain vanilla QTGMC)

    function fastDeinterlace( clip c ) {
    LoadPlugin(pd + “nnedi3\nnedi3.dll”)
    LoadPlugin(pd + “yadifmod_v1\yadifmod.dll”)
    edi=nnedi3(c, field=-2)
    yadifmod(c, mode=1, edeint=edi)
    }

    function slowDeinterlace( clip c ) { # see http://avisynth.nl/index.php/QTGMC
    LoadPlugin(pd + “mvtools-2.6.0.5\mvtools2.dll”) # Mod16 version of MVTools 2
    LoadPlugin(pd + “masktools_VitMod\mt_masktools-26.dll”)
    LoadPlugin(pd + “nnedi3_VitMod\nnedi3.dll”)
    LoadPlugin(pd + “RemoveGrain_VitMod\RemoveGrainSSE2.dll”)
    Import(pd + “QTGMC-3.33d\QTGMC-3.33d.avsi”)
    c = QTGMC( c, Preset=”Slow”, EdiThreads=4 )
    return Distributor(c) # This line may or may not be necessary, try removing it and see if you get more speed

    Would you be kind enough to explain where/how it improves ? do splitting to fast+slow deinterlace provide a real better result
    among motion/static scenes ? As I hardly understand how it then happens as you keep to the Bob (field) solution…

    Indeed , I will try ASAP but maybe you can give me yet some clues (?)

    Best Regards

    Yann

    ps : incidently I, too, was much interested in LRC ‘passive’ filtering for so called Audiophile speaker systems. I found that
    more ‘elegant” ( and so much more difficult ! well that’s where the pleasure is then … ) compared to ‘easy’ active + multi-amp filtering

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

  

  

  

Protected with IP Blacklist CloudIP Blacklist Cloud