5
0

Compare commits

...

2 Commits

Author SHA1 Message Date
60e6ff8563
pripri: bd: vol1 2021-05-13 09:13:44 -04:00
721a590111
automation: select only first audio stream 2021-05-12 15:05:41 -04:00
13 changed files with 244 additions and 17 deletions

1
.gitignore vendored
View File

@ -23,3 +23,4 @@ ffmpeg2pass*.log
**/__pycache__/ **/__pycache__/
**/*.egg-info/ **/*.egg-info/
**/bdmv/ **/bdmv/
**/bdpremux/

View File

@ -0,0 +1,41 @@
import vapoursynth as vs
from pripri_common import PriPriConfig, edgefix, denoise, descale, antialias, regrain, scenefilter_ed, finalize
from yt_common.automation import SelfRunner
from yt_common.source import FileTrim, SimpleSource
from typing import Optional
import os
core = vs.core
EPNUM: int = int(os.path.basename(os.path.splitext(__file__)[0]))
CONFIG: PriPriConfig = PriPriConfig(EPNUM)
SOURCE: SimpleSource = SimpleSource(
FileTrim("../bdmv/[170927][BDMV] プリンセス・プリンシパル I/PRINCESS_PRINCIPAL_1/BDMV/STREAM/00006.m2ts", (0, -24))
)
ED: Optional[int] = 32608
def filter() -> vs.VideoNode:
src = SOURCE.source()
if ED is not None:
src = src.std.FreezeFrames(first=[src.num_frames-4], last=[src.num_frames-1], replacement=[src.num_frames-5])
ef = edgefix(src)
den = denoise(ef)
rescale = descale(den)
aa = antialias(rescale)
grain = regrain(aa)
ed = scenefilter_ed(grain, src, ED)
final = finalize(ed)
src.set_output(1)
final.set_output(0)
return final
if __name__ == "__main__":
SelfRunner(CONFIG, SOURCE, filter, audio_codec=["-c:a", "libopus", "-b:a", "192k", "-sample_fmt", "s16"])
else:
filter()

View File

@ -0,0 +1,41 @@
import vapoursynth as vs
from pripri_common import PriPriConfig, edgefix, denoise, descale, antialias, regrain, scenefilter_ed, finalize
from yt_common.automation import SelfRunner
from yt_common.source import FileTrim, SimpleSource
from typing import Optional
import os
core = vs.core
EPNUM: int = int(os.path.basename(os.path.splitext(__file__)[0]))
CONFIG: PriPriConfig = PriPriConfig(EPNUM)
SOURCE: SimpleSource = SimpleSource(
FileTrim("../bdmv/[170927][BDMV] プリンセス・プリンシパル I/PRINCESS_PRINCIPAL_1/BDMV/STREAM/00007.m2ts", (0, -45))
)
ED: Optional[int] = 32607
def filter() -> vs.VideoNode:
src = SOURCE.source()
if ED is not None:
src = src.std.FreezeFrames(first=[src.num_frames-4], last=[src.num_frames-1], replacement=[src.num_frames-5])
ef = edgefix(src)
den = denoise(ef)
rescale = descale(den)
aa = antialias(rescale)
grain = regrain(aa)
ed = scenefilter_ed(grain, src, ED)
final = finalize(ed)
src.set_output(1)
final.set_output(0)
return final
if __name__ == "__main__":
SelfRunner(CONFIG, SOURCE, filter, audio_codec=["-c:a", "libopus", "-b:a", "192k", "-sample_fmt", "s16"])
else:
filter()

1
Princess Principal/mypy.ini Symbolic link
View File

@ -0,0 +1 @@
../yt_common/mypy.ini

View File

@ -0,0 +1,3 @@
from .config import PriPriConfig # noqa: F401
from .filter import edgefix, denoise, descale, antialias, regrain, scenefilter_ed, finalize # noqa: F401
from . import filter # noqa: F401

View File

@ -0,0 +1,21 @@
from yt_common.config import Config
from typing import Union
import os
TITLE: str = "PriPri"
TITLE_LONG: str = "Princess Principal"
RESOLUTION: int = 1080
DATAPATH: str = os.path.dirname(__file__)
class PriPriConfig(Config):
def __init__(self, desc: Union[str, int]) -> None:
super().__init__(
desc,
TITLE,
TITLE_LONG,
RESOLUTION,
DATAPATH
)

View File

@ -0,0 +1,91 @@
import vapoursynth as vs
import os
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.kernels import Bicubic
from lvsfunc.misc import replace_ranges, scale_thresh
from lvsfunc.scale import descale as ldescale
from vardefunc import fsrcnnx_upscale, diff_creditless_mask
from vsutil import depth
from vsutil import Range as CRange
NCED = os.path.join(os.path.dirname(__file__),
"../bdmv/[180223][BDMV] プリンセス・プリンシパル VI/PRINCESS_PRINCIPAL_6/BDMV/STREAM/00013.m2ts")
core = vs.core
def edgefix(clip: vs.VideoNode) -> vs.VideoNode:
bb: vs.VideoNode = bbmod(clip, top=3, bottom=3, left=3, right=3, blur=500)
return bb
def denoise(clip: vs.VideoNode) -> vs.VideoNode:
return bm3d(clip, sigma=0.75, radius=1)
def _nnedi3_double(clip: vs.VideoNode) -> vs.VideoNode:
nnargs: Dict[str, Any] = dict(field=0, dh=True, nsize=4, nns=4, qual=2, pscrn=2)
nn = clip.std.Transpose() \
.nnedi3.nnedi3(**nnargs) \
.std.Transpose() \
.nnedi3.nnedi3(**nnargs)
return nn.resize.Bicubic(src_top=0.5, src_left=0.5)
def descale(clip: vs.VideoNode) -> vs.VideoNode:
def _fsrlineart(clip: vs.VideoNode, width: int, height: int) -> vs.VideoNode:
clip = clip.resize.Point(1280, 720)
assert clip.format is not None
nn = depth(_nnedi3_double(depth(clip, 16)), clip.format.bits_per_sample)
fsr = fsrcnnx_upscale(clip, width, height, upscaled_smooth=nn, shader_file=FSRCNNX)
mask = retinex_edgemask(depth(fsr.std.ShufflePlanes(0, vs.GRAY), 16))
mask = mask.std.Binarize(scale_thresh(0.65, mask)).std.Maximum()
mask = depth(mask, clip.format.bits_per_sample, range_in=CRange.FULL, range=CRange.FULL)
return core.std.MaskedMerge(nn.resize.Bicubic(width, height, filter_param_a=0, filter_param_b=1/2), fsr, mask)
return depth(ldescale(clip, height=720, kernel=Bicubic(b=0, c=1/2), upscaler=_fsrlineart, mask=None), 16)
def antialias(clip: vs.VideoNode) -> vs.VideoNode:
def _sraa_pp_dehalo(sraa: vs.VideoNode) -> vs.VideoNode:
sraa = MaskedDHA(sraa, rx=2.4, darkstr=0.1, brightstr=0.75)
return sraa
return sraa_clamp(clip, postprocess=_sraa_pp_dehalo, mask=mask_strong(clip))
def regrain(clip: vs.VideoNode) -> vs.VideoNode:
mask_bright = clip.std.PlaneStats().adg.Mask(5)
mask_dark = clip.std.PlaneStats().adg.Mask(15)
sgrain_l = core.std.MaskedMerge(clip, clip.grain.Add(var=0.15, constant=True, seed=393), mask_bright.std.Invert())
sgrain_h = core.std.MaskedMerge(clip, clip.grain.Add(var=0.25, uvar=0.1, constant=True, seed=393), mask_bright)
sgrain_h = core.std.MaskedMerge(clip, sgrain_h, mask_dark.std.Invert())
sgrain = sgrain_h.std.MergeDiff(clip.std.MakeDiff(sgrain_l))
dgrain = core.std.MaskedMerge(clip, clip.grain.Add(var=0.35, uvar=0.1, constant=False, seed=393), mask_dark)
grain = dgrain.std.MergeDiff(clip.std.MakeDiff(sgrain))
return grain
def scenefilter_ed(clip: vs.VideoNode, src: vs.VideoNode, ed: Optional[int]) -> vs.VideoNode:
if ed is None:
return clip
nc = depth(core.lsmas.LWLibavSource(NCED)[24:-24], 16)
den = denoise(src)
dehalo = MaskedDHA(den, rx=2, darkstr=0.1, brightstr=0.75)
edc = replace_ranges(den, dehalo, [(ed+2121, ed+2159)])
edc = antialias(edc)
edc = regrain(edc)
mask = diff_creditless_mask(src, src[ed:], nc, ed, 6425, prefilter=True)
edc = core.std.MaskedMerge(edc, den, mask)
return replace_ranges(clip, edc, [(ed, ed+2159)])
def finalize(clip: vs.VideoNode) -> vs.VideoNode:
return depth(clip, 10)

View File

@ -0,0 +1 @@
x265 --input - --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 2.0 --psy-rdoq 1.8 --rdoq-level 1 --deblock -2:-2 --no-sao --no-open-gop --no-strong-intra-smoothing --frames {frames:d} --output {filename:s}.h265

25
Princess Principal/setup.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python3
import setuptools
name = "pripri_common"
version = "0.0.0"
release = "0.0.0"
setuptools.setup(
name=name,
version=release,
author="louis",
author_email="louis@poweris.moe",
description="princess principal common module",
packages=["pripri_common"],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
package_data={
'pripri_common': ['py.typed', 'final-settings'],
},
python_requires='>=3.8',
)

View File

@ -35,7 +35,7 @@ def combine_mask(clip: vs.VideoNode, weak: Union[Range, List[Range], None] = Non
def sraa_clamp(clip: vs.VideoNode, mask: Optional[vs.VideoNode] = None, def sraa_clamp(clip: vs.VideoNode, mask: Optional[vs.VideoNode] = None,
strength: float = 2, opencl: bool = True, strength: float = 2, opencl: bool = False,
postprocess: Optional[Callable[[vs.VideoNode], vs.VideoNode]] = None) -> vs.VideoNode: postprocess: Optional[Callable[[vs.VideoNode], vs.VideoNode]] = None) -> vs.VideoNode:
sraa = upscaled_sraa(clip, rfactor=1.3, nnedi3cl=opencl, downscaler=Bicubic(b=0, c=1/2).scale) sraa = upscaled_sraa(clip, rfactor=1.3, nnedi3cl=opencl, downscaler=Bicubic(b=0, c=1/2).scale)
sraa = postprocess(sraa) if postprocess else sraa sraa = postprocess(sraa) if postprocess else sraa

View File

@ -42,8 +42,7 @@ class Encoder():
cleanup: List[str] cleanup: List[str]
def __init__(self, epnum: int, settings_path: str, def __init__(self, settings_path: str, binary: Optional[str] = None, force: bool = False) -> None:
binary: Optional[str] = None, force: bool = False) -> None:
self.binary = binary if binary is not None else "" self.binary = binary if binary is not None else ""
self.force = force self.force = force
self.cleanup = [] self.cleanup = []
@ -128,7 +127,7 @@ class AudioGetter():
trims = self.src.get_audio() trims = self.src.get_audio()
if not trims or len(trims) > 1: if not trims or len(trims) > 1:
raise NotImplementedError("Please implement multifile trimming") raise NotImplementedError("Please implement multifile trimming")
audio_cut = acsuite.eztrim(trims[0].path, cast(acsuite.types.Trim, trims[0].trim))[0] audio_cut = acsuite.eztrim(trims[0].path, cast(acsuite.types.Trim, trims[0].trim), streams=0)[0]
self.cleanup.append(audio_cut) self.cleanup.append(audio_cut)
if ftrim: if ftrim:
@ -181,7 +180,7 @@ class SelfRunner():
self.video_clean = False self.video_clean = False
self.audio_clean = False self.audio_clean = False
parser = argparse.ArgumentParser(description=f"Encode {self.config.title} Episode {self.config.epnum:02d}") parser = argparse.ArgumentParser(description=f"Encode {self.config.title} {self.config.desc}")
if workraw_filter: if workraw_filter:
parser.add_argument("-w", "--workraw", help="Encode workraw, fast x264.", action="store_true") parser.add_argument("-w", "--workraw", help="Encode workraw, fast x264.", action="store_true")
parser.add_argument("-s", "--start", nargs='?', type=int, help="Start encode at frame START.") parser.add_argument("-s", "--start", nargs='?', type=int, help="Start encode at frame START.")
@ -226,7 +225,7 @@ class SelfRunner():
if start >= end: if start >= end:
raise ValueError("Start frame must be before end frame!") raise ValueError("Start frame must be before end frame!")
out_name = f"{self.config.title.lower()}_{self.config.epnum:02d}_{self.suffix}.mkv" out_name = f"{self.config.title.lower()}_{self.config.desc}_{self.suffix}.mkv"
if args.comparison and workraw_filter: if args.comparison and workraw_filter:
log.status("Generating comparison...") log.status("Generating comparison...")
@ -244,8 +243,8 @@ class SelfRunner():
if not os.path.isfile(settings_path): if not os.path.isfile(settings_path):
raise FileNotFoundError(f"Failed to find {settings_path}!") raise FileNotFoundError(f"Failed to find {settings_path}!")
self.encoder = Encoder(self.config.epnum, settings_path, args.encoder, args.force) self.encoder = Encoder(settings_path, args.encoder, args.force)
self.video_file = self.encoder.encode(self.clip, f"{self.config.epnum:02d}_{self.suffix}_{start}_{end}", self.video_file = self.encoder.encode(self.clip, f"{self.config.desc}_{self.suffix}_{start}_{end}",
start, end) start, end)
log.status("--- LOOKING FOR AUDIO ---") log.status("--- LOOKING FOR AUDIO ---")
@ -288,7 +287,7 @@ class SelfRunner():
"--track-order", "0:0,0:1", "--track-order", "0:0,0:1",
] ]
if chapters: if chapters:
chap = [f for f in [f"{self.config.epnum:02d}.xml", "chapters.xml"] if os.path.isfile(f)] chap = [f for f in [f"{self.config.desc}.xml", "chapters.xml"] if os.path.isfile(f)]
if len(chap) != 0: if len(chap) != 0:
mkvtoolnix_args += [ mkvtoolnix_args += [
"--chapters", chap[0], "--chapters", chap[0],

View File

@ -1,17 +1,20 @@
from typing import Union
class Config(): class Config():
epnum: int desc: str
title: str title: str
title_long: str title_long: str
resolution: int resolution: int
datapath: str datapath: str
def __init__(self, epnum: int, title: str, title_long: str, resolution: int, datapath: str) -> None: def __init__(self, desc: Union[int, str], title: str, title_long: str, resolution: int, datapath: str) -> None:
self.epnum = epnum self.desc = desc if isinstance(desc, str) else f"{desc:02d}"
self.title = title self.title = title
self.title_long = title_long self.title_long = title_long
self.resolution = resolution self.resolution = resolution
self.datapath = datapath self.datapath = datapath
def format_filename(self, filename: str) -> str: def format_filename(self, filename: str) -> str:
return filename.format(epnum=self.epnum, title=self.title, return filename.format(epnum=self.desc, title=self.title,
title_long=self.title_long, resolution=self.resolution) title_long=self.title_long, resolution=self.resolution)

View File

@ -17,11 +17,11 @@ from .logging import log
core = vs.core core = vs.core
SUBSPLS_FILENAME: str = "[SubsPlease] {title_long} - {epnum:02d} ({resolution}p) [$GLOB].mkv" SUBSPLS_FILENAME: str = "[SubsPlease] {title_long} - {epnum} ({resolution}p) [$GLOB].mkv"
ER_FILENAME: str = "[Erai-raws] {title_long} - {epnum:02d} [v0][{resolution}p]$GLOB.mkv" ER_FILENAME: str = "[Erai-raws] {title_long} - {epnum} [v0][{resolution}p]$GLOB.mkv"
FUNI_INTRO: int = 289 FUNI_INTRO: int = 289
AMAZON_FILENAME_CBR: str = "{title_long} - {epnum:02d} (Amazon Prime CBR {resolution}p).mkv" AMAZON_FILENAME_CBR: str = "{title_long} - {epnum} (Amazon Prime CBR {resolution}p).mkv"
AMAZON_FILENAME_VBR: str = "{title_long} - {epnum:02d} (Amazon Prime VBR {resolution}p).mkv" AMAZON_FILENAME_VBR: str = "{title_long} - {epnum} (Amazon Prime VBR {resolution}p).mkv"
class FileTrim(NamedTuple): class FileTrim(NamedTuple):