Last active
December 16, 2022 14:26
-
-
Save rlaphoenix/8cc734e08f765490d9cc48f2f3006e22 to your computer and use it in GitHub Desktop.
Batch VapourSynth & FFMPEG Python Script | Assumes `mpeg12.vpy` and `h264.vpy` scripts are next to it
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import subprocess | |
from pathlib import Path | |
import click | |
from pymediainfo import MediaInfo | |
BASE_FFMPEG_ARGS = [ | |
"-nostats", | |
"-colorspace", "bt709", "-color_primaries", "bt709", "-color_trc", "bt709", "-color_range", "1", | |
"-c:v", "libx264", | |
"-preset", "veryslow", | |
"-psy-rd", "0.90:0", | |
"-rc-lookahead", "120", "-me_range", "32", "-partitions", "p8x8,b8x8,i8x8,i4x4", | |
"-mbtree", "0", "-fast-pskip", "0", "-aq-mode", "3", | |
"-x264-params", "deadzone-inter=21:deadzone-intra=11" | |
] | |
SOURCE_ARGS = { | |
"DVD": [ | |
"-level", "3.1", | |
"-b:v", "6M", "-maxrate:v", "6M", "-bufsize:v", "10M", | |
"-deblock", "-2:-2" | |
], | |
"BD": [ | |
"-level", "4.1", | |
"-b:v", "8M", "-maxrate:v", "8M", "-bufsize:v", "16M", | |
"-deblock", "-3:-3" | |
] | |
} | |
@click.command() | |
@click.argument("files", type=Path) | |
@click.option("-r", "--resolution", type=int, default=None) | |
@click.argument("source", type=click.Choice(["DVD", "BD"])) | |
@click.option("-o", "--output", type=Path, default=Path("P:/")) | |
def main(files: Path, source: str, resolution: int, output: Path): | |
# append source to output folder | |
output = output / source | |
# make sure output folder exists | |
output.mkdir(parents=True, exist_ok=True) | |
# add source-specific settings to ffmpeg | |
ffmpeg_args = BASE_FFMPEG_ARGS + SOURCE_ARGS[source] | |
if resolution: | |
ffmpeg_args.extend([ | |
"-vf", f"scale={resolution}:-2:flags=spline" | |
]) | |
# get vpy script path | |
vpy_script = Path(__file__).parent / { | |
"DVD": "mpeg12.vpy", | |
"BD": "h264.vpy" | |
}[source] | |
if files.is_dir(): | |
files = files.glob("*.mkv") | |
else: | |
files = [files] | |
for mkv in files: | |
# get input file media info | |
mi = MediaInfo.parse(mkv) | |
aspect_ratio = mi.video_tracks[0].other_display_aspect_ratio[0] | |
if aspect_ratio.endswith(":1"): | |
# ffmpeg doesnt like n:1 ratios, so supply as decimal/int | |
aspect_ratio = aspect_ratio.split(":")[0] | |
# initialize the script | |
# this is to skip the mkvextract and so on stdout | |
vspipe_init = subprocess.Popen([ | |
"vspipe", | |
"-c", "y4m", | |
"--end", "0", | |
"--arg", f"source={str(mkv)}", | |
str(vpy_script), "-" | |
], stdout=open(os.devnull, "w")) | |
vspipe_init.wait() | |
vspipe = subprocess.Popen([ | |
"vspipe", | |
"-c", "y4m", | |
"--arg", f"source={str(mkv)}", | |
str(vpy_script), "-" | |
], stdout=subprocess.PIPE) | |
ffmpeg = subprocess.Popen([ | |
"ffmpeg", "-y", | |
"-vn", "-sn", "-i", str(mkv), | |
"-i", "-", | |
*ffmpeg_args, | |
"-aspect", aspect_ratio, | |
"-c:a", "ac3", | |
"-b:a", "448k", | |
str((output / mkv.name).with_suffix(".mkv")) | |
], stdin=vspipe.stdout) | |
vspipe.stdout.close() | |
ffmpeg.communicate() | |
# delete all LWI files (index files) | |
if source == "BD": | |
for lwi in Path(__file__).parent.glob("*.lwi"): | |
lwi.unlink() | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import vapoursynth as vs | |
from vapoursynth import core | |
from functools import partial | |
from pvsfunc import PLWI | |
from havsfunc import QTGMC | |
# example script to use pvsfunc.PLWI to get a progressive stream. | |
# this does not deal with VFR at all. | |
# `source` variable should be set via vs-pipe, if not, manually set it | |
# source = r"C:\Users\John\title_t01.mkv" | |
clip = PLWI(source, verbose=False).\ | |
deinterlace(kernel=partial(QTGMC, FPSDivisor=2, Preset="Very Slow"), verbose=False).\ | |
clip | |
clip.set_output() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import vapoursynth as vs | |
from vapoursynth import core | |
from functools import partial | |
from pvsfunc import PD2V | |
from havsfunc import QTGMC | |
# example script to use pvsfunc.PD2V to get a CFR ceiled progressive stream. | |
# `source` variable should be set via vs-pipe, if not, manually set it | |
# source = r"C:\Users\John\title_t01.mkv" | |
clip = PD2V(source, verbose=False).\ | |
ceil().\ | |
deinterlace(kernel=partial(QTGMC, FPSDivisor=2, Preset="Very Slow"), verbose=False).\ | |
clip | |
clip.set_output() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment