#!/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)