e27cc22cfb
Derived from pengchujin/jzsub at 222a90265d2a8797ca258eb1a980cee0863a8311; preserve the upstream MIT license and attribution.
102 lines
3.2 KiB
Python
Executable File
102 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Run MaterialSub dependency and font checks before a long download."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import shutil
|
|
import sys
|
|
from typing import Any, Sequence
|
|
|
|
import burn_subtitles as burn
|
|
|
|
|
|
def assess(*, font: str, allow_missing_font: bool, youtube: bool) -> tuple[int, dict[str, Any]]:
|
|
if sys.version_info < (3, 10):
|
|
return 2, {
|
|
"complete": False,
|
|
"stage": "dependency_required",
|
|
"error": "Python 3.10 or newer is required",
|
|
}
|
|
yt_dlp = shutil.which("yt-dlp")
|
|
if not yt_dlp:
|
|
return 2, {
|
|
"complete": False,
|
|
"stage": "dependency_required",
|
|
"error": "yt-dlp was not found in PATH",
|
|
}
|
|
try:
|
|
ffmpeg, ffprobe = burn._required_executables()
|
|
burn._require_libass_subtitles_filter(ffmpeg)
|
|
except burn.BurnError as exc:
|
|
return 2, {
|
|
"complete": False,
|
|
"stage": "dependency_required",
|
|
"error": str(exc),
|
|
}
|
|
|
|
warnings: list[str] = []
|
|
if youtube and not shutil.which("deno"):
|
|
warnings.append(
|
|
"Deno was not found; current yt-dlp may expose fewer YouTube formats"
|
|
)
|
|
installed = burn._font_installed(font)
|
|
if installed is False and not allow_missing_font:
|
|
return 3, {
|
|
"complete": False,
|
|
"stage": "font_decision_required",
|
|
"font": font,
|
|
"font_installed": False,
|
|
"substitution_allowed": False,
|
|
"instruction": (
|
|
"Install the requested font, or rerun preflight and the final burn "
|
|
"with --allow-missing-font to accept libass substitution"
|
|
),
|
|
"warnings": warnings,
|
|
}
|
|
if installed is False:
|
|
warnings.append(f"Font {font!r} is missing; libass substitution was accepted")
|
|
elif installed is None:
|
|
warnings.append(f"Could not verify whether font {font!r} is installed")
|
|
return 0, {
|
|
"complete": True,
|
|
"stage": "preflight_complete",
|
|
"font": font,
|
|
"font_installed": installed,
|
|
"substitution_allowed": bool(installed is False and allow_missing_font),
|
|
"executables": {
|
|
"yt_dlp": yt_dlp,
|
|
"ffmpeg": ffmpeg,
|
|
"ffprobe": ffprobe,
|
|
},
|
|
"warnings": warnings,
|
|
}
|
|
|
|
|
|
def _parser() -> argparse.ArgumentParser:
|
|
parser = argparse.ArgumentParser(description="Check MaterialSub dependencies before downloading.")
|
|
parser.add_argument("--font", default="MiSans")
|
|
parser.add_argument("--allow-missing-font", action="store_true")
|
|
parser.add_argument("--youtube", action="store_true")
|
|
return parser
|
|
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
args = _parser().parse_args(argv)
|
|
font = args.font.strip()
|
|
if not font:
|
|
print(json.dumps({"complete": False, "error": "font cannot be empty"}))
|
|
return 2
|
|
exit_code, result = assess(
|
|
font=font,
|
|
allow_missing_font=args.allow_missing_font,
|
|
youtube=args.youtube,
|
|
)
|
|
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
|
|
return exit_code
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|