Skip to content

Instantly share code, notes, and snippets.

@rlaphoenix
Last active December 16, 2022 14:26
Show Gist options
  • Save rlaphoenix/8cc734e08f765490d9cc48f2f3006e22 to your computer and use it in GitHub Desktop.
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
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()
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()
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