5
0

Compare commits

..

2 Commits

Author SHA1 Message Date
e144906b11
vivy: tv: common: upstream dehardsubbing utility to lvsfunc 2021-04-17 20:52:22 -04:00
69c3ddaa61
vivy: tv: friendship ended with funi & subsplease
Erai-Raws has good funi audio still if amazon isn't out in time
2021-04-17 18:19:28 -04:00
10 changed files with 81 additions and 167 deletions

4
.gitignore vendored
View File

@ -6,8 +6,12 @@
*.png *.png
*.aac *.aac
*.m4a *.m4a
*.h264
*.h265 *.h265
*.eac3 *.eac3
*.ass
*.mka
*.xml
cudnn_data/ cudnn_data/
*.webm *.webm
ffmpeg2pass*.log ffmpeg2pass*.log

View File

@ -1,12 +1,15 @@
import vapoursynth as vs import vapoursynth as vs
from lvsfunc.types import Range
from lvsfunc.dehardsub import HardsubSign, bounded_dehardsub
from typing import List from typing import List
import os import os
import sys import sys
sys.path.append("..") sys.path.append("..")
from vivy_common import (HardsubSign, Range, bounded_dehardsub, antialias, deband, denoise, # noqa: E402 from vivy_common import (SelfRunner, antialias, deband, denoise, # noqa: E402
finalize, fsrcnnx_rescale, letterbox_edgefix, source) finalize, fsrcnnx_rescale, letterbox_edgefix, source)
core = vs.core core = vs.core
@ -37,14 +40,27 @@ LETTERBOX: List[Range] = [
(659, 14071) (659, 14071)
] ]
waka, ref = source(EPNUM)
waka = waka[:37301] + core.std.BlankClip(waka, length=6) + waka[37301:]
src = bounded_dehardsub(waka, ref, SIGNS_RU) def filter_basic() -> vs.VideoNode:
rescale = fsrcnnx_rescale(src, NOSCALE) waka, ref = source(EPNUM)
den = denoise(rescale) waka = waka[:37301] + core.std.BlankClip(waka, length=6) + waka[37301:]
deb = deband(den) src = bounded_dehardsub(waka, ref, SIGNS_RU)
aa = antialias(deb, NOAA) return src
edgefix = letterbox_edgefix(aa, LETTERBOX)
final = finalize(edgefix)
final.set_output() def filter() -> vs.VideoNode:
src = filter_basic()
rescale = fsrcnnx_rescale(src, NOSCALE)
den = denoise(rescale)
deb = deband(den)
aa = antialias(deb, NOAA)
edgefix = letterbox_edgefix(aa, LETTERBOX)
final = finalize(edgefix)
final.set_output()
return final
if __name__ == "__main__":
SelfRunner(EPNUM, filter, filter_basic)
else:
filter()

View File

@ -1,13 +1,16 @@
import vapoursynth as vs import vapoursynth as vs
from lvsfunc.types import Range
from lvsfunc.dehardsub import HardsubSign, bounded_dehardsub
from typing import List from typing import List
import os import os
import sys import sys
sys.path.append("..") sys.path.append("..")
from vivy_common import (HardsubSign, Range, bounded_dehardsub, antialias, deband, denoise, # noqa: E402 from vivy_common import (SelfRunner, antialias, deband, denoise, finalize, # noqa: E402
finalize, fsrcnnx_rescale, source) fsrcnnx_rescale, source)
core = vs.core core = vs.core
@ -45,13 +48,26 @@ PIXELSHIT: List[Range] = [
NOSCALE: List[Range] = CREDITS + PIXELSHIT NOSCALE: List[Range] = CREDITS + PIXELSHIT
NOAA: List[Range] = PIXELSHIT NOAA: List[Range] = PIXELSHIT
waka, ref = source(EPNUM)
waka = waka[:32344] + waka[32349:]
src = bounded_dehardsub(waka, ref, SIGNS_RU) def filter_basic() -> vs.VideoNode:
rescale = fsrcnnx_rescale(src, NOSCALE) waka, ref = source(EPNUM)
den = denoise(rescale) waka = waka[:32344] + waka[32349:]
deb = deband(den) src = bounded_dehardsub(waka, ref, SIGNS_RU)
aa = antialias(deb, NOAA) return src
final = finalize(aa)
final.set_output()
def filter() -> vs.VideoNode:
src = filter_basic()
rescale = fsrcnnx_rescale(src, NOSCALE)
den = denoise(rescale)
deb = deband(den)
aa = antialias(deb, NOAA)
final = finalize(aa)
final.set_output()
return final
if __name__ == "__main__":
SelfRunner(EPNUM, filter, filter_basic)
else:
filter()

View File

@ -1,12 +1,15 @@
import vapoursynth as vs import vapoursynth as vs
from lvsfunc.types import Range
from lvsfunc.dehardsub import HardsubSign, bounded_dehardsub
from typing import List from typing import List
import os import os
import sys import sys
sys.path.append("..") sys.path.append("..")
from vivy_common import (HardsubSign, Range, SelfRunner, bounded_dehardsub, antialias, deband, denoise, # noqa: E402 from vivy_common import (SelfRunner, antialias, deband, denoise, # noqa: E402
finalize, fsrcnnx_rescale, letterbox_edgefix, source) finalize, fsrcnnx_rescale, letterbox_edgefix, source)
core = vs.core core = vs.core

View File

@ -1,32 +0,0 @@
#!/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.isfile(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.mka")

View File

@ -24,7 +24,7 @@ ignore_errors = False
allow_untyped_globals = False allow_untyped_globals = False
allow_redefinition = False allow_redefinition = False
implicit_reexport = False implicit_reexport = True
strict_equality = True strict_equality = True
show_error_context = False show_error_context = False
@ -34,6 +34,8 @@ color_output = True
error_summary = True error_summary = True
pretty = True pretty = True
mypy_path = .
[mypy-cytoolz.*] [mypy-cytoolz.*]
ignore_errors = True ignore_errors = True

View File

@ -1,3 +1,2 @@
from .dehardsub import HardsubSign, bounded_dehardsub, get_all_masks # noqa: F401
from .filter import antialias, deband, denoise, finalize, fsrcnnx_rescale, letterbox_edgefix # noqa: F401 from .filter import antialias, deband, denoise, finalize, fsrcnnx_rescale, letterbox_edgefix # noqa: F401
from .util import Range, SelfRunner, glob_crc, source # noqa: F401 from .util import SelfRunner, glob_crc, source # noqa: F401

View File

@ -1,97 +0,0 @@
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]
highpass: int
expand: int
def __init__(self,
range: Range,
bound: Union[BoundingBox, Tuple[Tuple[int, int], Tuple[int, int]], None],
refframe: Optional[int] = None, highpass: int = 5000, expand: int = 8):
self.range = range
self.refframe = refframe
self.highpass = highpass
self.expand = expand
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 _hardsub_mask(self, hrdsb: vs.VideoNode, ref: vs.VideoNode) -> vs.VideoNode:
if self.refframe is not None:
mask = kgf.hardsubmask_fades(hrdsb[self.refframe], ref[self.refframe],
highpass=self.highpass, expand_n=self.expand)
else:
mask = kgf.hardsubmask_fades(hrdsb, ref, highpass=self.highpass, expand_n=self.expand)
assert isinstance(mask, vs.VideoNode)
return mask
def _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 get_mask(self, hrdsb: vs.VideoNode, ref: vs.VideoNode) -> vs.VideoNode:
bm = self._bound_mask(ref)
hm = self._hardsub_mask(hrdsb, ref)
return core.std.MaskedMerge(core.std.BlankClip(hm), hm, bm)
def get_all_masks(hrdsb: vs.VideoNode, ref: vs.VideoNode, signs: List[HardsubSign]) -> vs.VideoNode:
"""
Scenefiltering helper, not used in encode
"""
assert ref.format is not None
mask = core.std.BlankClip(ref, format=ref.format.replace(color_family=vs.GRAY, subsampling_w=0, subsampling_h=0).id)
for sign in signs:
mask = lvf.misc.replace_ranges(mask, core.std.Expr([mask, sign.get_mask(hrdsb, ref)], 'x y +'), [sign.range])
return mask
def bounded_dehardsub(hrdsb: vs.VideoNode, ref: vs.VideoNode, signs: List[HardsubSign]) -> vs.VideoNode:
bound = hrdsb
for sign in signs:
bound = lvf.misc.replace_ranges(bound,
core.std.MaskedMerge(bound, ref, sign.get_mask(hrdsb, ref)),
[sign.range])
return bound

View File

@ -4,11 +4,10 @@ import lvsfunc as lvf
import vardefunc as vdf import vardefunc as vdf
from awsmfunc import bbmod from awsmfunc import bbmod
from lvsfunc.types import Range
from mvsfunc import BM3D from mvsfunc import BM3D
from typing import List, Optional from typing import List, Optional
from .util import Range
import os import os
import vsutil import vsutil

View File

@ -14,8 +14,6 @@ from typing import Any, BinaryIO, Callable, List, Optional, Sequence, Tuple, Uni
core = vs.core core = vs.core
Range = Union[int, Tuple[int, int]]
TITLE: str = "Vivy" TITLE: str = "Vivy"
TITLE_LONG: str = f"{TITLE} - Fluorite Eye's Song" TITLE_LONG: str = f"{TITLE} - Fluorite Eye's Song"
RESOLUTION: int = 1080 RESOLUTION: int = 1080
@ -184,13 +182,16 @@ class AudioGetter():
print(f"{SUCCESS}Found Amazon audio{RESET}") print(f"{SUCCESS}Found Amazon audio{RESET}")
return return
# as of Ep4 SubsPlease is using new funi 128kbps aac while erai has 256kbps still
try: try:
if os.path.isfile(ER_FILENAME.format(epnum=epnum)):
self.audio_file = ER_FILENAME.format(epnum=epnum)
self.video_src = core.ffms2.Source(ER_FILENAME.format(epnum=epnum))
if os.path.isfile(glob_crc(SUBSPLS_FILENAME.format(epnum=epnum))): if os.path.isfile(glob_crc(SUBSPLS_FILENAME.format(epnum=epnum))):
self.audio_file = glob_crc(SUBSPLS_FILENAME.format(epnum=epnum)) self.audio_file = glob_crc(SUBSPLS_FILENAME.format(epnum=epnum))
self.video_src = core.ffms2.Source(glob_crc(SUBSPLS_FILENAME.format(epnum=epnum))) self.video_src = core.ffms2.Source(glob_crc(SUBSPLS_FILENAME.format(epnum=epnum)))
elif os.path.isfile(ER_FILENAME.format(epnum=epnum)): if (epnum >= 4):
self.audio_file = ER_FILENAME.format(epnum=epnum) print(f"{WARNING}Using SubsPlease, audio may be worse than Erai-Raws{RESET}")
self.video_src = core.ffms2.Source(ER_FILENAME.format(epnum=epnum))
else: else:
raise FileNotFoundError() raise FileNotFoundError()
except FileNotFoundError: except FileNotFoundError:
@ -305,7 +306,8 @@ class SelfRunner():
try: try:
print(f"{STATUS}--- MUXING FILE ---{RESET}") print(f"{STATUS}--- MUXING FILE ---{RESET}")
if self._mux(f"{TITLE.lower()}_{epnum:02d}_{args.suffix}.mkv", not args.no_metadata) != 0: if self._mux(f"{TITLE.lower()}_{epnum:02d}_{args.suffix}.mkv", not args.no_metadata,
not args.no_metadata and start == 0 and end == self.clip.num_frames) != 0:
raise Exception("mkvmerge failed") raise Exception("mkvmerge failed")
except Exception: except Exception:
print(f"{ERROR}--- MUXING FAILED ---{RESET}") print(f"{ERROR}--- MUXING FAILED ---{RESET}")
@ -321,7 +323,7 @@ class SelfRunner():
print(f"{SUCCESS}--- ENCODE COMPLETE ---{RESET}") print(f"{SUCCESS}--- ENCODE COMPLETE ---{RESET}")
def _mux(self, name: str, metadata: bool = True) -> int: def _mux(self, name: str, metadata: bool = True, chapters: bool = True) -> int:
mkvtoolnix_args = [ mkvtoolnix_args = [
"mkvmerge", "mkvmerge",
"--output", name, "--output", name,
@ -337,10 +339,12 @@ class SelfRunner():
mkvtoolnix_args += [ mkvtoolnix_args += [
"--title", f"[{SUBGROUP}] {TITLE_LONG} - {self.epnum:02d}", "--title", f"[{SUBGROUP}] {TITLE_LONG} - {self.epnum:02d}",
] ]
chapters = [f for f in ["{self.epnum:02d}.xml", "chapters.xml"] if os.path.isfile(f)]
if len(chapters) != 0: if chapters:
chap = [f for f in ["{self.epnum:02d}.xml", "chapters.xml"] if os.path.isfile(f)]
if len(chap) != 0:
mkvtoolnix_args += [ mkvtoolnix_args += [
"--chapters", chapters[0], "--chapters", chap[0],
] ]
print("+ " + " ".join(mkvtoolnix_args)) print("+ " + " ".join(mkvtoolnix_args))