scripts/ass2mks.py

117 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env cached-nix-shell
#!nix-shell -i python3 -p python3 ffmpeg-full
from subprocess import run
import mimetypes
import os.path
import re
import sys
def lavfi_escape(parameter):
return (
parameter.replace("'", "\\'")
.replace(":", "\:")
.replace("\\'", "\\\\\\'")
.replace("[", "\[")
.replace("]", "\]")
.replace(",", "\,")
)
infile = sys.argv[1]
try:
timeout = sys.argv[2]
except IndexError:
timeout = 1800
# the system default font
# if the font name does not include this but the resulting fqn does, it is treated as missing
default_font = "Roboto"
res = run(
[
"ffmpeg",
"-hide_banner",
"-t",
str(timeout),
"-f",
"lavfi",
"-i",
"nullsrc=16x16",
"-filter:v",
f"subtitles={lavfi_escape(infile)}",
"-f",
"null",
"-",
],
capture_output=True,
)
if res.returncode != 0:
print("ffmpeg failed")
print(f"stdout: {res.stdout.decode('utf-8')}")
print(f"stderr: {res.stderr.decode('utf-8')}")
sys.exit(1)
if res.stdout != b"":
print(f"Got Stdout: {res.stdout.decode('utf-8')}")
substitutions = []
fonts = []
for line in res.stderr.decode("utf-8").splitlines():
substitution = re.match(
"^\[Parsed_subtitles_0 @ 0x[0-9a-f]*\] Glyph .* not found, selecting one more font for \((.*), ([0-9]{1,3}), ([0-9]{1,3})\)",
line,
)
fontselect = re.match(
"^\[Parsed_subtitles_0 @ 0x[0-9a-f]*\] fontselect: \((.*), ([0-9]{1,3}), ([0-9]{1,3})\) -> (.*), ([0-9]*), (.*)",
line,
)
if substitution is not None:
substitutions.append(
(
substitution.group(1),
int(substitution.group(2)),
int(substitution.group(3)),
)
)
if fontselect is not None:
font = {
"name": fontselect.group(1),
"weight": int(fontselect.group(2)),
"italic": int(fontselect.group(3)),
"path": fontselect.group(4),
#'?': fontselect.group(5),
"fqn": fontselect.group(6),
}
if font["name"] == "":
continue
if (font["name"], font["weight"], font["italic"]) in substitutions:
print(
f"Font {font['name']} lacks glyph support which lead to the substitution by {font['fqn']}, not including substitution font"
)
continue
if default_font in font["fqn"] and not default_font in font["name"]:
print(
f"Font {font['name']} could not be found (based on {font['fqn']} looking like the default font)"
)
sys.exit(1)
fonts.append(font)
command = ["mkvmerge", "-q", "-o", f"{os.path.splitext(infile)[0]}.mks", infile]
for font in fonts:
command.extend(
[
"--attachment-mime-type",
mimetypes.guess_type(font["path"])[0] or "font/sfnt",
"--attach-file",
font["path"],
]
)
run(command, check=True)