From 648b8e1a79f5d450b8e372c3965acd2be8aa2f26 Mon Sep 17 00:00:00 2001 From: louis <louis@poweris.moe> Date: Tue, 13 Apr 2021 13:15:57 -0400 Subject: [PATCH] vivy: tv: 01 --- .gitignore | 4 ++ Vivy/01/01.vpy | 46 ++++++++++++++++++ Vivy/funi_ac.py | 32 +++++++++++++ Vivy/mypy.ini | 41 ++++++++++++++++ Vivy/vivy_common/__init__.py | 3 ++ Vivy/vivy_common/dehardsub.py | 73 +++++++++++++++++++++++++++++ Vivy/vivy_common/filter.py | 49 +++++++++++++++++++ Vivy/vivy_common/py.typed | 0 Vivy/vivy_common/shaders/.gitignore | 1 + Vivy/vivy_common/util.py | 27 +++++++++++ Vivy/x265-settings | 1 + 11 files changed, 277 insertions(+) create mode 100644 Vivy/01/01.vpy create mode 100755 Vivy/funi_ac.py create mode 100644 Vivy/mypy.ini create mode 100644 Vivy/vivy_common/__init__.py create mode 100644 Vivy/vivy_common/dehardsub.py create mode 100644 Vivy/vivy_common/filter.py create mode 100644 Vivy/vivy_common/py.typed create mode 100644 Vivy/vivy_common/shaders/.gitignore create mode 100644 Vivy/vivy_common/util.py create mode 100644 Vivy/x265-settings diff --git a/.gitignore b/.gitignore index 194f4ad..3e4b3b5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ *.ffindex *.png *.aac +*.m4a +*.h265 cudnn_data/ *.webm ffmpeg2pass*.log @@ -12,3 +14,5 @@ ffmpeg2pass*.log *.m2ts *.lwi **/.vspreview/ +**/results/ +**/__pycache__/ diff --git a/Vivy/01/01.vpy b/Vivy/01/01.vpy new file mode 100644 index 0000000..a66787c --- /dev/null +++ b/Vivy/01/01.vpy @@ -0,0 +1,46 @@ +import vapoursynth as vs + +from typing import List + +import os +import sys +sys.path.append("..") + +from vivy_common import (HardsubSign, Range, bounded_dehardsub, antialias, deband, denoise, # noqa: E402 + finalize, fsrcnnx_rescale, source) + +core = vs.core + + +EPNUM: int = int(os.path.basename(os.path.splitext(__file__)[0])) +SIGNS_RU: List[HardsubSign] = [ + HardsubSign((5283, 5403), ((226, 786), (1214, 102))), + HardsubSign((6778, 6888), ((588, 454), (434, 63))), + HardsubSign((9017, 9070), ((975, 301), (157, 24))), + HardsubSign((22276, 22350), ((480, 75), (959, 66))), + HardsubSign((25715, 25904), ((623, 73), (681, 67))), + HardsubSign((35223, 36108), ((775, 866), (1138, 211))), + HardsubSign((37572, 37666), ((259, 856), (987, 103))), +] +CREDITS: List[Range] = [(35151, 37306)] +PIXELSHIT: List[Range] = [ + (2534, 2605), + (1937, 2021), + (6607, 6762), + (14160, 14227), + (16609, 16674), + (20112, 20558), +] +NOSCALE: List[Range] = CREDITS + PIXELSHIT +NOAA: List[Range] = PIXELSHIT + +waka, funi = source(EPNUM) +waka = waka[:37301] + core.std.BlankClip(waka, length=6) + waka[37301:] + +src = bounded_dehardsub(waka, funi, SIGNS_RU) +rescale = fsrcnnx_rescale(src, NOSCALE) +den = denoise(rescale) +deb = deband(den) +aa = antialias(deb, NOAA) +final = finalize(aa) +final.set_output() diff --git a/Vivy/funi_ac.py b/Vivy/funi_ac.py new file mode 100755 index 0000000..e090747 --- /dev/null +++ b/Vivy/funi_ac.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import vapoursynth as vs + +import acsuite +import os +import sys + +from subprocess import DEVNULL, call + +from vivy_common.util import FUNI_FILENAME, FUNI_INTRO, glob_crc + +EPNUM: int = int(sys.argv[1]) + +ac = acsuite.AC() +core = vs.core + +funi: str = glob_crc(os.path.join(f"{EPNUM:02d}", FUNI_FILENAME.format(epnum=EPNUM))) +src = core.ffms2.Source(funi) + +if __name__ == "__main__": + funi_audio: str = f"{EPNUM:02d}/funi.aac" + if not os.path.exists(funi_audio): + call(["ffmpeg", + "-i", funi, + "-vn", + "-sn", + "-map_metadata", "-1", + "-c:a", "copy", + funi_audio], + stdout=DEVNULL, stderr=DEVNULL + ) + ac.eztrim(src, (FUNI_INTRO, 0), funi_audio, f"{EPNUM:02d}/{EPNUM:02d}_cut.aac") diff --git a/Vivy/mypy.ini b/Vivy/mypy.ini new file mode 100644 index 0000000..18f16c0 --- /dev/null +++ b/Vivy/mypy.ini @@ -0,0 +1,41 @@ +[mypy] +python_version = 3.9 + +ignore_missing_imports = True + +disallow_any_generics = True + +disallow_untyped_defs = True +disallow_incomplete_defs = True +check_untyped_defs = True +disallow_untyped_decorators = True + +no_implicit_optional = True +strict_optional = True + +warn_redundant_casts = True +warn_unused_ignores = True +warn_no_return = True +warn_return_any = True +warn_unreachable = True + +show_none_errors = True +ignore_errors = False + +allow_untyped_globals = False +allow_redefinition = False +implicit_reexport = False +strict_equality = True + +show_error_context = False +show_column_numbers = True +show_error_codes = True +color_output = True +error_summary = True +pretty = True + +[mypy-cytoolz.*] +ignore_errors = True + +[mypy-vsutil.*] +implicit_reexport = True diff --git a/Vivy/vivy_common/__init__.py b/Vivy/vivy_common/__init__.py new file mode 100644 index 0000000..d4ca774 --- /dev/null +++ b/Vivy/vivy_common/__init__.py @@ -0,0 +1,3 @@ +from .dehardsub import HardsubSign, bounded_dehardsub # noqa: F401 +from .filter import antialias, deband, denoise, finalize, fsrcnnx_rescale # noqa: F401 +from .util import Range, glob_crc, source # noqa: F401 diff --git a/Vivy/vivy_common/dehardsub.py b/Vivy/vivy_common/dehardsub.py new file mode 100644 index 0000000..364f7fa --- /dev/null +++ b/Vivy/vivy_common/dehardsub.py @@ -0,0 +1,73 @@ +import vapoursynth as vs +import kagefunc as kgf +import lvsfunc as lvf + +from typing import List, NamedTuple, Optional, Tuple, Union + +from .util import Range + +core = vs.core + + +class Position(NamedTuple): + x: int + y: int + + +class Size(NamedTuple): + x: int + y: int + + +class BoundingBox(): + pos: Position + size: Size + + def __init__(self, pos: Position, size: Size): + self.pos = pos + self.size = size + + +class HardsubSign(): + range: Range + bound: Optional[BoundingBox] + refframe: Optional[int] + + def __init__(self, + range: Range, + bound: Union[BoundingBox, Tuple[Tuple[int, int], Tuple[int, int]], None], + refframe: Optional[int] = None): + self.range = range + self.refframe = refframe + if bound is None: + self.bound = None + elif isinstance(bound, BoundingBox): + self.bound = bound + else: + self.bound = BoundingBox(Position(bound[0][0], bound[0][1]), Size(bound[1][0], bound[1][1])) + + def get_hardsub_mask(self, hrdsb: vs.VideoNode, ref: vs.VideoNode) -> vs.VideoNode: + if self.refframe is not None: + return kgf.hardsubmask_fades(hrdsb[self.refframe], ref[self.refframe], highpass=2000) + return kgf.hardsubmask_fades(hrdsb, ref, highpass=2000) + + def get_bound_mask(self, ref: vs.VideoNode) -> vs.VideoNode: + if self.bound is not None: + mask = kgf.squaremask(ref, self.bound.size.x, self.bound.size.y, + self.bound.pos.x, self.bound.pos.y) + else: + mask = kgf.squaremask(ref, ref.width, ref.height, 0, 0) + + assert isinstance(mask, vs.VideoNode) + return mask + + +def bounded_dehardsub(hrdsb: vs.VideoNode, ref: vs.VideoNode, signs: List[HardsubSign]) -> vs.VideoNode: + bound = hrdsb + for sign in signs: + dhs = core.std.MaskedMerge(hrdsb, ref, sign.get_hardsub_mask(hrdsb, ref)) + bound = lvf.misc.replace_ranges(bound, + core.std.MaskedMerge(hrdsb, dhs, sign.get_bound_mask(hrdsb)), + [sign.range]) + + return bound diff --git a/Vivy/vivy_common/filter.py b/Vivy/vivy_common/filter.py new file mode 100644 index 0000000..a5191b7 --- /dev/null +++ b/Vivy/vivy_common/filter.py @@ -0,0 +1,49 @@ +import vapoursynth as vs +import kagefunc as kgf +import lvsfunc as lvf +import vardefunc as vdf + +from mvsfunc import BM3D +from typing import List, Optional + +from .util import Range + +import os +import vsutil + +core = vs.core + +FSRCNNX = os.path.join(os.path.dirname(__file__), "shaders/FSRCNNX_x2_56-16-4-1.glsl") + + +def fsrcnnx_rescale(src: vs.VideoNode, noscale: Optional[List[Range]] = None) -> vs.VideoNode: + def _vdf_fsrcnnx(clip: vs.VideoNode, width: int, height: int) -> vs.VideoNode: + clip = core.std.ShufflePlanes([vsutil.depth(clip.resize.Point(vsutil.get_w(864), 864), 16), + src.resize.Bicubic(vsutil.get_w(864), 864)], + planes=[0, 1, 2], colorfamily=vs.YUV) + + return vsutil.get_y(vsutil.depth(vdf.fsrcnnx_upscale(clip, width, height, FSRCNNX), 32)) + + descale = lvf.scale.descale(src, height=864, upscaler=_vdf_fsrcnnx, kernel=lvf.kernels.Bicubic()) \ + .resize.Bicubic(format=vs.YUV420P16) + return lvf.misc.replace_ranges(descale, src, noscale) if noscale else descale + + +def denoise(clip: vs.VideoNode) -> vs.VideoNode: + bm3d = BM3D(clip, sigma=[1.5, 0], depth=16) + knl = core.knlm.KNLMeansCL(clip, d=3, a=2, h=0.4, channels="UV", device_type='gpu', device_id=0) + return core.std.ShufflePlanes([bm3d, knl], planes=[0, 1, 2], colorfamily=vs.YUV) + + +def deband(clip: vs.VideoNode) -> vs.VideoNode: + return clip.neo_f3kdb.Deband(range=18, y=32, cb=24, cr=24, grainy=24, grainc=0, output_depth=16, sample_mode=4) + + +def antialias(clip: vs.VideoNode, noaa: Optional[List[Range]] = None) -> vs.VideoNode: + clamp = lvf.aa.nneedi3_clamp(clip) + return lvf.misc.replace_ranges(clamp, clip, noaa) if noaa else clamp + + +def finalize(clip: vs.VideoNode) -> vs.VideoNode: + grain = kgf.adaptive_grain(clip, 0.1) + return vsutil.depth(grain, 10) diff --git a/Vivy/vivy_common/py.typed b/Vivy/vivy_common/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/Vivy/vivy_common/shaders/.gitignore b/Vivy/vivy_common/shaders/.gitignore new file mode 100644 index 0000000..e8e3dc8 --- /dev/null +++ b/Vivy/vivy_common/shaders/.gitignore @@ -0,0 +1 @@ +FSRCNNX_x2_56-16-4-1.glsl diff --git a/Vivy/vivy_common/util.py b/Vivy/vivy_common/util.py new file mode 100644 index 0000000..fb8e7fc --- /dev/null +++ b/Vivy/vivy_common/util.py @@ -0,0 +1,27 @@ +import vapoursynth as vs + +import glob +import vsutil + +from typing import Tuple, Union + +core = vs.core + +Range = Union[int, Tuple[int, int]] + +FUNI_FILENAME: str = "[SubsPlease] Vivy - Fluorite Eye's Song - {epnum:02d} (1080p) [$CRC].mkv" +FUNI_INTRO: int = 289 +WAKA_FILENAME: str = "Vivy_{epnum:02d}_RU_HD.mp4" + + +def glob_crc(pattern: str) -> str: + res = glob.glob(glob.escape(pattern).replace("$CRC", "*")) + if len(res) == 0: + raise FileNotFoundError(f"File matching \"{pattern}\" not found!") + return res[0] + + +def source(epnum: int) -> Tuple[vs.VideoNode, vs.VideoNode]: + waka = vsutil.depth(core.ffms2.Source(WAKA_FILENAME.format(epnum=epnum)), 16) + funi = vsutil.depth(core.ffms2.Source(glob_crc(FUNI_FILENAME.format(epnum=epnum))), 16)[FUNI_INTRO:] + return waka, funi diff --git a/Vivy/x265-settings b/Vivy/x265-settings new file mode 100644 index 0000000..9ec68bf --- /dev/null +++ b/Vivy/x265-settings @@ -0,0 +1 @@ +--y4m --input-depth 10 --output-depth 10 --input-csp i420 --profile main10 --colormatrix bt709 --colorprim bt709 --transfer bt709 --preset slower --rc-lookahead 72 --keyint 360 --min-keyint 23 --subme 5 --qcomp 0.7 --crf 15 --aq-mode 3 --aq-strength 0.9 --bframes 16 --psy-rd 0.95 --psy-rdoq 1.8 --rdoq-level 1 --deblock -2:-2 --no-sao