harry0703/MoneyPrinterTurbo · error · ValueError

subtitle font must use the .ttf or .ttc extension

Error message

subtitle font must use the .ttf or .ttc extension

What it means

Thrown by the CLI when subtitles are enabled (--subtitles/--subtitle-enabled), a --font-name was supplied, and stop_at is 'video', but the resolved font file does not end in .ttf or .ttc. TrueType/OpenType-with-true-extensions is the only supported subtitle font format downstream (FFmpeg/ass subtitles), so .otf, .fon, or extension-less files are rejected. Note the font must also already have passed _resolve_managed_resource_file, meaning it lives inside resource/fonts.

Source

Thrown at cli.py:712

                params.bgm_file = bgm_service.resolve_bgm_file(params.bgm_file)
            except ValueError as exc:
                supported_extensions = ", ".join(
                    bgm_service.SUPPORTED_BGM_EXTENSIONS
                )
                raise ValueError(
                    "background music must be a supported audio file inside "
                    f"storage/bgm or resource/songs ({supported_extensions}): "
                    f"{params.bgm_file}"
                ) from exc

    if params.subtitle_enabled and params.font_name and stop_at == "video":
        font_path = _resolve_managed_resource_file(
            params.font_name,
            resource_dir=utils.font_dir(),
            description="subtitle font",
        )
        if not font_path.lower().endswith((".ttf", ".ttc")):
            raise ValueError("subtitle font must use the .ttf or .ttc extension")
        # 下游根据 resource/fonts 内的文件名拼接路径,因此仍保留纯文件名。
        params.font_name = os.path.basename(font_path)

    if params.video_source != "local" or stop_at not in {"materials", "video"}:
        return

    local_videos_dir = utils.storage_dir("local_videos", create=True)
    resolved_materials: list[tuple[MaterialInfo, str, str]] = []
    for material in params.video_materials or []:
        source_path = _resolve_cli_file(
            material.url,
            description="local material",
            fallback_dir=local_videos_dir,
        )
        extension = os.path.splitext(source_path)[1].lower()
        if extension not in local_material_extensions:
            allowed = ", ".join(sorted(local_material_extensions))
            raise ValueError(

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Use only .ttf or .ttc font files in resource/fonts — convert .otf to .ttf with a tool like fontforge or fonttools if needed
  2. Rename the file to carry the correct, real extension (do not just force-rename an incompatible format)
  3. If you did not intend custom subtitles font, omit --font-name to use the default font

Example fix

# before
--subtitle-enabled --font-name MyFont.otf --stop-at video

# after (convert otf -> ttf, place in resource/fonts)
fonttools ttLib.woff2 compress  # or: pyftsubset / fontforge conversion
cp MyFont.ttf resource/fonts/MyFont.ttf
--subtitle-enabled --font-name MyFont.ttf --stop-at video
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def font_file_is_supported(font_name: str) -> bool:
    return Path(font_name).suffix.lower() in (".ttf", ".ttc")

Type guard

def is_subtitle_font(name: str) -> bool:
    """Guard: font resolves inside resource/fonts with .ttf/.ttc extension."""
    return (
        isinstance(name, str)
        and Path(name).suffix.lower() in (".ttf", ".ttc")
    )

Prevention

When it happens

Trigger: CLI invocation with params.subtitle_enabled=True, params.font_name set, stop_at=='video', and the basename resolved from resource/fonts has an extension other than .ttf/.ttc (checked case-insensitively), e.g. myfont.otf or a file with no extension.

Common situations: User drops an .otf font into resource/fonts and selects it; font file downloaded without its extension; misnamed file like font.ttf.bak; expecting OpenType support that the renderer does not have.

Related errors


AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14). Data as JSON: /api/errors/7df52ee4eb869709. Report an issue: GitHub.