diff --git a/Symphogear/XV [BD]/.gitignore b/Symphogear/XV [BD]/.gitignore new file mode 100644 index 0000000..5b55fab --- /dev/null +++ b/Symphogear/XV [BD]/.gitignore @@ -0,0 +1,12 @@ +.mypy_cache/ +bdmv/ +common/__pycache__/ +*.bookmarks +*.png +!common/mask_2.png +*.swp +*.mkv +*.mp4 +*.wav +*.flac +*.mka diff --git a/Symphogear/XV [BD]/05/ep5.vpy b/Symphogear/XV [BD]/05/ep5.vpy new file mode 100644 index 0000000..02f45e7 --- /dev/null +++ b/Symphogear/XV [BD]/05/ep5.vpy @@ -0,0 +1,45 @@ +import vapoursynth as vs + +import sys +sys.path.append("..") + +from common import FadeRange, denoise, descale, w2x, deband, ncop_mask, finalize +from functools import partial +from toolz.functoolz import compose + +core = vs.core +core.max_cache_size = 1024 + +OP = (1272, 3668) +ED = (31889, 34046) +NO_SCALE = [(34514, 34600)] +FORCE_SCALE = [(22384, 23376)] +FADE_RANGES = [FadeRange(ref=3700, range_=(3670, 3751)), # title + FadeRange(ref=17383, range_=(17300, 17436)) # logo +] +W2X_DENOISE = [ + (OP[0]+1859, OP[0]+1896) # flashy OP scene +] +DEBAND_HARD = [] +DEBAND_HARDER = [] + +src_ep = core.lsmas.LWLibavSource("../bdmv/KIXA_90890/BDMV/STREAM/00003.m2ts") +src_pv = core.lsmas.LWLibavSource("../bdmv/KIXA_90890/BDMV/STREAM/00004.m2ts")[:-24] +src_op = core.lsmas.LWLibavSource("../bdmv/KIXA_90889/BDMV/STREAM/00007.m2ts")[24:-24] +src_ed = core.lsmas.LWLibavSource("../bdmv/KIXA_90889/BDMV/STREAM/00008.m2ts")[24:-24] +src = src_ep + src_pv +src = src.fmtc.bitdepth(bits=16) +den = denoise(src) + +descale = partial(descale, force_scale=FORCE_SCALE, no_scale=NO_SCALE, fade_ranges=FADE_RANGES) +w2x = partial(w2x, w2x_range=W2X_DENOISE) +deband = partial(deband, hard=DEBAND_HARD, harder=DEBAND_HARDER) +ncop_mask = partial(ncop_mask, src=den, op=OP, ed=ED, src_op=src_op, src_ed=src_ed) +final = compose( + finalize, + ncop_mask, + deband, + w2x, + descale + )(den) +final.set_output() diff --git a/Symphogear/XV [BD]/05/ep5pv_ac.py b/Symphogear/XV [BD]/05/ep5pv_ac.py new file mode 100755 index 0000000..efbbef1 --- /dev/null +++ b/Symphogear/XV [BD]/05/ep5pv_ac.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import acsuite +import os +import vapoursynth as vs + +core = vs.core + +ac = acsuite.AC() +path = r"bdmv/KIXA_90889/BDMV/STREAM/00004.m2ts" +src = core.lsmas.LWLibavSource(path) +ac.eztrim(src, [(0, -24)], os.path.splitext(path)[0] + ".wav", "ep5pv.wav") diff --git a/Symphogear/XV [BD]/06/ep6.vpy b/Symphogear/XV [BD]/06/ep6.vpy new file mode 100644 index 0000000..5689d99 --- /dev/null +++ b/Symphogear/XV [BD]/06/ep6.vpy @@ -0,0 +1,45 @@ +import vapoursynth as vs + +import sys +sys.path.append("..") + +from common import FadeRange, denoise, descale, w2x, deband, ncop_mask, finalize +from functools import partial +from toolz.functoolz import compose + +core = vs.core +core.max_cache_size = 1024 + +OP = (1726, 4124) +ED = (31890, 34047) +NO_SCALE = [(34495, 34590)] +FORCE_SCALE = [(25196, 26501)] +FADE_RANGES = [FadeRange(ref=4179, range_=(4126, 4207)), # title + FadeRange(ref=18421, range_=(18333, 18498)) # logo +] +W2X_DENOISE = [ + (OP[0]+1859, OP[0]+1896) # flashy OP scene +] +DEBAND_HARD = [] +DEBAND_HARDER = [] + +src_ep = core.lsmas.LWLibavSource("../bdmv/KIXA_90890/BDMV/STREAM/00005.m2ts") +src_pv = core.lsmas.LWLibavSource("../bdmv/KIXA_90890/BDMV/STREAM/00006.m2ts")[:-24] +src_op = core.lsmas.LWLibavSource("../bdmv/KIXA_90889/BDMV/STREAM/00007.m2ts")[24:-24] +src_ed = core.lsmas.LWLibavSource("../bdmv/KIXA_90889/BDMV/STREAM/00008.m2ts")[24:-24] +src = src_ep + src_pv +src = src.fmtc.bitdepth(bits=16) +den = denoise(src) + +descale = partial(descale, force_scale=FORCE_SCALE, no_scale=NO_SCALE, fade_ranges=FADE_RANGES) +w2x = partial(w2x, w2x_range=W2X_DENOISE) +deband = partial(deband, hard=DEBAND_HARD, harder=DEBAND_HARDER) +ncop_mask = partial(ncop_mask, src=den, op=OP, ed=ED, src_op=src_op, src_ed=src_ed) +final = compose( + finalize, + ncop_mask, + deband, + w2x, + descale + )(den) +final.set_output() diff --git a/Symphogear/XV [BD]/06/ep6pv_ac.py b/Symphogear/XV [BD]/06/ep6pv_ac.py new file mode 100755 index 0000000..e68c243 --- /dev/null +++ b/Symphogear/XV [BD]/06/ep6pv_ac.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import acsuite +import os +import vapoursynth as vs + +core = vs.core + +ac = acsuite.AC() +path = r"bdmv/KIXA_90889/BDMV/STREAM/00006.m2ts" +src = core.lsmas.LWLibavSource(path) +ac.eztrim(src, [(0, -24)], os.path.splitext(path)[0] + ".wav", "ep6pv.wav") diff --git a/Symphogear/XV [BD]/common/__init__.py b/Symphogear/XV [BD]/common/__init__.py new file mode 100644 index 0000000..0a15376 --- /dev/null +++ b/Symphogear/XV [BD]/common/__init__.py @@ -0,0 +1,2 @@ +from .scale import FadeRange, descale +from .filter import denoise, w2x, deband, ncop_mask, finalize diff --git a/Symphogear/XV [BD]/common/filter.py b/Symphogear/XV [BD]/common/filter.py new file mode 100644 index 0000000..4578670 --- /dev/null +++ b/Symphogear/XV [BD]/common/filter.py @@ -0,0 +1,64 @@ +import vapoursynth as vs + +from kagefunc import adaptive_grain, retinex_edgemask +from lvsfunc.misc import replace_ranges +from mvsfunc import BM3D +from typing import List, Tuple, Union +from vardefunc import dcm + +core = vs.core + + +def denoise(clip: vs.VideoNode) -> vs.VideoNode: + denoisechroma = core.knlm.KNLMeansCL(clip, d=1, a=2, h=0.45, channels="UV", + device_type='gpu', device_id=0) + denoiseluma = core.knlm.KNLMeansCL(clip, d=3, a=2, h=0.4, channels="Y", + device_type='gpu', device_id=0) + return core.std.ShufflePlanes([denoiseluma, denoisechroma], + planes=[0, 1, 2], colorfamily=vs.YUV) + + +def w2x(clip: vs.VideoNode, w2x_range: List[Union[int, Tuple[int, int]]] + ) -> vs.VideoNode: + rgb = clip.resize.Point(format=vs.RGBS, matrix_in_s="709") + w2x = rgb.w2xnvk.Waifu2x(noise=1, scale=1, model=2) \ + .resize.Point(format=clip.format.id, matrix_s="709") + + bm3d = BM3D(clip, sigma=[0, 5], ref=w2x) + bm3d = core.std.ShufflePlanes([w2x, bm3d], planes=[0, 1, 2], + colorfamily=vs.YUV) + denoise = replace_ranges(clip, bm3d, w2x_range) + return denoise + + +def deband(clip: vs.VideoNode, hard: List[Union[int, Tuple[int, int]]], + harder: List[Union[int, Tuple[int, int]]]): + line = retinex_edgemask(clip).std.Binarize(9500).rgvs.RemoveGrain(3) \ + .std.Inflate() + nf3kdb = clip.neo_f3kdb.Deband(range=18, y=32, cb=24, cr=24, grainy=24, + grainc=0, output_depth=16, sample_mode=4) + nf3kdb = core.std.MaskedMerge(nf3kdb, clip, line) + placebo = clip.placebo.Deband(iterations=3, threshold=3, radius=24, + grain=4) + placebo2 = clip.placebo.Deband(iterations=3, threshold=5, radius=32, + grain=4) + deband = replace_ranges(nf3kdb, placebo, hard) + deband = replace_ranges(deband, placebo2, harder) + return deband + + +def ncop_mask(clip: vs.VideoNode, src: vs.VideoNode, + op: Tuple[int, int], ed: Tuple[int, int], src_op: vs.VideoNode, + src_ed: vs.VideoNode) -> vs.VideoNode: + credit_op_m = dcm(clip, src[op[0]:op[1]+1], + src_op[:op[1]-op[0]+1], op[0], op[1], 2, 2) + credit_ed_m = dcm(clip, src[ed[0]:ed[1]+1], + src_ed[:ed[1]-ed[0]+1], ed[0], ed[1], 2, 2) + credit_m = core.std.Expr([credit_op_m, credit_ed_m], 'x y +') + return core.std.MaskedMerge(clip, src, credit_m) + + +def finalize(clip: vs.VideoNode) -> vs.VideoNode: + final = adaptive_grain(clip, 0.3) + final = final.fmtc.bitdepth(bits=10, dmode=3) + return final diff --git a/Symphogear/XV [BD]/common/py.typed b/Symphogear/XV [BD]/common/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/Symphogear/XV [BD]/common/scale.py b/Symphogear/XV [BD]/common/scale.py new file mode 100644 index 0000000..f381a6f --- /dev/null +++ b/Symphogear/XV [BD]/common/scale.py @@ -0,0 +1,77 @@ +import vapoursynth as vs +import vsutil + +from functools import partial +from kagefunc import retinex_edgemask +from lvsfunc.aa import upscaled_sraa +from lvsfunc.kernels import Bicubic +from lvsfunc.misc import replace_ranges +from lvsfunc.scale import descale as ldescale +from typing import List, NamedTuple, Tuple, Union + +core = vs.core + + +class FadeRange(NamedTuple): + ref: int + range_: Tuple[int, int] + + +def _sraa_frameeval(n: int, clip: vs.VideoNode, w: int, h: int): + frame = clip.get_frame(n) + if frame.height < 1080: + rfactor = 2.5 + else: + rfactor = 1.5 + return upscaled_sraa(clip.resize.Bicubic(frame.width, frame.height), + rfactor=rfactor, h=h, ar=w/h) + + +def _sraa_reupscale(clip: vs.VideoNode, width: int, height: int): + sraa = clip.std.FrameEval(partial(_sraa_frameeval, clip=clip, w=width, + h=height)) + scale = sraa.resize.Spline36(width, height, format=vs.GRAY16) + return scale + + +def _fade_ranges_with_refs(clip, reupscaled, ranges): + mask = core.std.BlankClip(clip) + for r in ranges: + rmask = core.std.Expr([clip[r.ref], reupscaled[r.ref]], "x y - abs") + rmask = vsutil.iterate(rmask, core.std.Maximum, 4) + rmask = rmask.std.Binarize(4000) + rmask = core.std.Expr([mask, rmask], "x y +") + mask = replace_ranges(mask, rmask, [r.range_]) + + return mask + + +def _really_dumb_inverse_mask(clip, reupscaled: vs.VideoNode, + ranges: List[FadeRange]) -> vs.VideoNode: + reupscaled = reupscaled.resize.Bicubic(format=clip.format.id) + line_mask = retinex_edgemask(clip, 0.0001).std.Binarize(10000) + fade_mask = _fade_ranges_with_refs(clip, reupscaled, ranges) + mask = core.std.Expr([fade_mask, line_mask.std.Invert()], "x y +") + return mask.resize.Bicubic(format=clip.format.id) + + +def descale(clip: vs.VideoNode, force_scale: List[Union[int, Tuple[int, int]]], + no_scale: List[Union[int, Tuple[int, int]]], + fade_ranges: List[FadeRange], show_mask=False) -> vs.VideoNode: + dmask = partial(_really_dumb_inverse_mask, ranges=fade_ranges) + kernel = Bicubic(b=1/3, c=1/3) + heights = [871, 872, 873] + y = vsutil.get_y(clip) + ys = ldescale(y, upscaler=_sraa_reupscale, height=heights, + kernel=kernel, threshold=0.003, mask=dmask, + show_mask=show_mask) + if show_mask: + return ys + + yf = ldescale(y, upscaler=_sraa_reupscale, height=heights, + kernel=kernel, threshold=0, mask=dmask) + yd = replace_ranges(ys, yf, force_scale) + scaled = core.std.ShufflePlanes([yd, clip], planes=[0, 1, 2], + colorfamily=vs.YUV) + scaled = replace_ranges(scaled, clip, no_scale) + return scaled