5
0

Compare commits

..

No commits in common. "5f0bd29bebccef0c12248683eab286de5b6d470f" and "61981b3993f5815bdbd0c4ae62aecade0e9d85e1" have entirely different histories.

6 changed files with 82 additions and 39 deletions

View File

@ -5,11 +5,11 @@ from typing import Any, Dict, Optional
from yt_common.antialiasing import sraa_clamp, mask_strong
from yt_common.data import FSRCNNX
from yt_common.denoise import bm3d
from G41Fun import MaskedDHA
from awsmfunc import bbmod
from kagefunc import retinex_edgemask
from lvsfunc.denoise import bm3d
from lvsfunc.kernels import Bicubic, Kernel
from lvsfunc.misc import replace_ranges, scale_thresh
from lvsfunc.scale import descale as ldescale

View File

@ -14,10 +14,10 @@ TITLE_LONG: str = f"{TITLE} - Fluorite Eye's Song"
RESOLUTION: int = 1080
DATAPATH: str = os.path.dirname(__file__)
WAKA_RU_FILENAME: str = f"{TITLE}_{{epnum:s}}_RU_HD.mp4"
WAKA_FR_FILENAME: str = f"{TITLE}_{{epnum:s}}_FR_HD.mp4"
WAKA_DE_FILENAME: str = f"{TITLE} - Fluorite Eyes Song E{{epnum:s}} [1080p][AAC][JapDub][GerSub][Web-DL].mkv"
AMAZON_FILENAME: str = "{title_long} - {epnum:s} (Amazon Prime VBR {resolution}p).mkv"
WAKA_RU_FILENAME: str = f"{TITLE}_{{epnum:02d}}_RU_HD.mp4"
WAKA_FR_FILENAME: str = f"{TITLE}_{{epnum:02d}}_FR_HD.mp4"
WAKA_DE_FILENAME: str = f"{TITLE} - Fluorite Eyes Song E{{epnum:02d}} [1080p][AAC][JapDub][GerSub][Web-DL].mkv"
AMAZON_FILENAME: str = "{title_long} - {epnum:02d} (Amazon Prime VBR {resolution}p).mkv"
core = vs.core
@ -37,13 +37,13 @@ class VivyConfig(Config):
class VivySource(source.FunimationSource):
def get_amazon(self) -> vs.VideoNode:
# ep1-3 have good funi video, let's just use that
if int(self.config.desc) < 4:
if self.config.epnum < 4:
raise FileNotFoundError()
if not os.path.isfile(self.config.format_filename(AMAZON_FILENAME_VBR)):
log.warn("Amazon not found, falling back to Funimation")
raise FileNotFoundError()
log.success("Found Amazon video")
return self._open(self.config.format_filename(AMAZON_FILENAME_VBR))
return core.ffms2.Source(self.config.format_filename(AMAZON_FILENAME_VBR))
def get_waka_filenames(self) -> List[str]:
return [self.config.format_filename(f) for f in [

View File

@ -6,7 +6,6 @@ import vardefunc as vdf
from awsmfunc import bbmod
from debandshit import f3kbilateral
from lvsfunc.aa import upscaled_sraa
from lvsfunc.denoise import bm3d
from lvsfunc.kernels import Bicubic
from lvsfunc.misc import replace_ranges
from lvsfunc.types import Range
@ -14,6 +13,7 @@ from typing import List, Optional, Union
from yt_common import antialiasing
from yt_common.data import FSRCNNX
from yt_common.denoise import bm3d
from yt_common.deband import morpho_mask
import vsutil

View File

@ -1 +1 @@
from . import antialiasing, automation, config, data, deband, logging, source # noqa: F401
from . import antialiasing, automation, config, data, deband, denoise, logging, source # noqa: F401

View File

@ -8,9 +8,7 @@ import shutil
import string
import subprocess
from lvsfunc.render import clip_async_render
from typing import Any, BinaryIO, Callable, List, Optional, Sequence, Tuple, cast
from typing import Any, BinaryIO, Callable, List, Optional, Sequence, cast
from .config import Config
from .logging import log
@ -51,16 +49,14 @@ class Encoder():
self._get_encoder_settings(settings_path)
def encode(self, clip: vs.VideoNode, filename: str, start: int = 0, end: int = 0,
timecode_file: Optional[str] = None, want_timecodes: bool = False) -> Tuple[str, List[float]]:
def encode(self, clip: vs.VideoNode, filename: str, start: int = 0, end: int = 0) -> str:
end = end if end != 0 else clip.num_frames
want_timecodes = True if timecode_file else want_timecodes
outfile = self.out_template.format(filename=filename)
if os.path.isfile(outfile) and not self.force:
log.warn("Existing output detected, skipping encode!")
return outfile, []
return outfile
params = [p.format(frames=end-start, filename=filename) for p in self.params]
@ -75,13 +71,7 @@ class Encoder():
# signal.signal(signal.SIGINT, forward_to_proc)
# turns out this didn't work out the way i had hoped
# use the python renderer only if we need timecodes because it's slower
timecodes: List[float] = []
if want_timecodes:
timecode_io = open(timecode_file, "w") if timecode_file else None
timecodes = clip_async_render(clip[start:end], cast(BinaryIO, process.stdin), timecode_io)
else:
clip[start:end].output(cast(BinaryIO, process.stdin), y4m=True)
clip[start:end].output(cast(BinaryIO, process.stdin), y4m=True)
process.communicate()
# vapoursynth should handle this itself but just in case
@ -91,7 +81,7 @@ class Encoder():
log.success("--- ENCODE FINISHED ---")
self.cleanup.append(outfile)
return outfile, timecodes
return outfile
def _get_encoder_settings(self, settings_path: str) -> None:
with open(settings_path, "r") as settings:
@ -126,7 +116,7 @@ class AudioGetter():
trims = self.src.get_audio()
if not trims or len(trims) > 1:
raise NotImplementedError("Please implement multifile trimming")
audio_cut = acsuite.eztrim(trims[0].path, trims[0].trim or (0, None), streams=0)[0]
audio_cut = acsuite.eztrim(trims[0].path, cast(acsuite.types.Trim, trims[0].trim), streams=0)[0]
self.cleanup.append(audio_cut)
if ftrim:
@ -165,8 +155,6 @@ class SelfRunner():
video_file: str
audio_file: str
timecodes: List[float]
timecode_file: Optional[str]
encoder: Encoder
audio: AudioGetter
@ -255,16 +243,8 @@ class SelfRunner():
raise FileNotFoundError(f"Failed to find {settings_path}!")
self.encoder = Encoder(settings_path, args.encoder, args.force)
# we only want to generate timecodes if vfr, otherwise we can just calculate them
self.timecode_file = f"{self.config.desc}_{self.suffix}_{start}_{end}_timecodes.txt" \
if self.clip.fps_den == 0 else None
self.video_file, self.timecodes = self.encoder.encode(self.clip,
f"{self.config.desc}_{self.suffix}_{start}_{end}",
start, end, self.timecode_file)
# calculate timecodes if cfr and we didn't generate any (we shouldn'tve)
self.timecodes = [round(float(1e9*f*(1/self.clip.fps)))/1e9 for f in range(0, self.clip.num_frames + 1)] \
if self.clip.fps_den != 0 and len(self.timecodes) == 0 else self.timecodes
self.video_file = self.encoder.encode(self.clip, f"{self.config.desc}_{self.suffix}_{start}_{end}",
start, end)
self._do_audio(start, end, audio_codec)
@ -300,13 +280,11 @@ class SelfRunner():
self.audio_file = out_name
def _do_mux(self, name: str, chapters: bool = True) -> int:
tcargs = ["--timecodes", f"0:{self.timecode_file}"] if self.timecode_file else []
mkvtoolnix_args = [
"mkvmerge",
"--output", name,
"--no-chapters", "--no-track-tags", "--no-global-tags", "--track-name", "0:",
"--default-track", "0:yes",
] + tcargs + [
"(", self.video_file, ")",
"--no-chapters", "--no-track-tags", "--no-global-tags", "--track-name", "0:",
"--default-track", "0:yes", "--language", "0:jpn",

View File

@ -0,0 +1,65 @@
import vapoursynth as vs
from vsutil import iterate, Range, get_y
from typing import Any, Dict, List, Optional, Union
core = vs.core
# always uses float OPP
# mvsfunc is an unreadable mess and i was having bm3d issues so i rewrote the wrapper
# turns out, it's still an unreadable mess
def bm3d(clip: vs.VideoNode, matrix_s: str = "709", sigma: Union[float, List[float]] = 0.75,
radius: Union[int, List[int], None] = None, ref: Optional[vs.VideoNode] = None,
pre: Optional[vs.VideoNode] = None, refine: int = 1,
basic_args: Dict[str, Any] = {}, final_args: Dict[str, Any] = {}) -> vs.VideoNode:
assert clip.format is not None
isGray = clip.format.color_family == vs.GRAY
def to_opp(clip: vs.VideoNode) -> vs.VideoNode:
return clip.resize.Bicubic(format=vs.RGBS, matrix_in_s=matrix_s).bm3d.RGB2OPP(sample=1)
def to_fullgray(clip: vs.VideoNode) -> vs.VideoNode:
return get_y(clip).resize.Point(format=vs.GRAYS, range_in=Range.LIMITED, range=Range.FULL)
sigmal = [sigma] * 3 if not isinstance(sigma, list) else sigma + [sigma[-1]]*(3-len(sigma))
sigmal = [sigmal[0], 0, 0] if isGray else sigmal
isGray = True if sigmal[1] == 0 and sigmal[2] == 0 else isGray
if len(sigmal) != 3:
raise ValueError("bm3d: 'invalid number of sigma parameters supplied'")
radiusl = [0, 0] if radius is None else [radius] * 2 if not isinstance(radius, list) \
else radius + [radius[-1]]*(2-len(radius))
if len(radiusl) != 2:
raise ValueError("bm3d: 'invalid number or radius parameters supplied'")
if sigmal[0] == 0 and sigmal[1] == 0 and sigmal[2] == 0:
return clip
pre = pre if pre is None else to_opp(pre) if not isGray else to_fullgray(pre)
def basic(clip: vs.VideoNode) -> vs.VideoNode:
return clip.bm3d.Basic(sigma=sigmal, ref=pre, matrix=100, **basic_args) if radiusl[0] < 1 \
else clip.bm3d.VBasic(sigma=sigmal, ref=pre, radius=radiusl[0], matrix=100, **basic_args) \
.bm3d.VAggregate(radius=radiusl[0], sample=1)
clip_in = to_opp(clip) if not isGray else to_fullgray(clip)
refv = basic(clip_in) if ref is None else to_opp(ref) if not isGray else to_fullgray(ref)
def final(clip: vs.VideoNode) -> vs.VideoNode:
return clip.bm3d.Final(sigma=sigmal, ref=refv, matrix=100, **final_args) if radiusl[1] < 1 \
else clip.bm3d.VFinal(sigma=sigmal, ref=refv, radius=radiusl[1], matrix=100, **final_args) \
.bm3d.VAggregate(radius=radiusl[1], sample=1)
den = iterate(clip_in, final, refine)
# boil everything back down to whatever input we had
den = den.bm3d.OPP2RGB(sample=1).resize.Bicubic(format=clip.format.id, matrix_s=matrix_s) if not isGray \
else den.resize.Point(format=clip.format.replace(color_family=vs.GRAY, subsampling_w=0, subsampling_h=0).id,
range_in=Range.FULL, range=Range.LIMITED)
# merge source chroma if it exists and we didn't denoise it
den = core.std.ShufflePlanes([den, clip], planes=[0, 1, 2], colorfamily=vs.YUV) \
if isGray and clip.format.color_family == vs.YUV else den
# sub clip luma back in if we only denoised chroma
den = den if sigmal[0] != 0 else core.std.ShufflePlanes([clip, den], planes=[0, 1, 2], colorfamily=vs.YUV)
return den