Compare commits
2 Commits
be1a0d8ac7
...
60e6ff8563
Author | SHA1 | Date | |
---|---|---|---|
60e6ff8563 | |||
721a590111 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,3 +23,4 @@ ffmpeg2pass*.log
|
|||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
**/*.egg-info/
|
**/*.egg-info/
|
||||||
**/bdmv/
|
**/bdmv/
|
||||||
|
**/bdpremux/
|
||||||
|
41
Princess Principal/01/01.vpy
Normal file
41
Princess Principal/01/01.vpy
Normal 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()
|
41
Princess Principal/02/02.vpy
Normal file
41
Princess Principal/02/02.vpy
Normal 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
1
Princess Principal/mypy.ini
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../yt_common/mypy.ini
|
3
Princess Principal/pripri_common/__init__.py
Normal file
3
Princess Principal/pripri_common/__init__.py
Normal 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
|
21
Princess Principal/pripri_common/config.py
Normal file
21
Princess Principal/pripri_common/config.py
Normal 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
|
||||||
|
)
|
91
Princess Principal/pripri_common/filter.py
Normal file
91
Princess Principal/pripri_common/filter.py
Normal 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)
|
1
Princess Principal/pripri_common/final-settings
Normal file
1
Princess Principal/pripri_common/final-settings
Normal 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
25
Princess Principal/setup.py
Executable 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',
|
||||||
|
)
|
@ -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
|
||||||
|
@ -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],
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user