{"record":{"id":"3d268e5dcd936198","repo":"harry0703/MoneyPrinterTurbo","slug":"background-music-must-be-a-supported-audio-file-in","errorCode":null,"errorMessage":"background music must be a supported audio file inside storage/bgm or resource/songs ({supported_extensions}): {params.bgm_file}","messagePattern":"background music must be a supported audio file inside storage/bgm or resource/songs \\((.+?)\\): (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"cli.py","lineNumber":699,"sourceCode":"            # CLI 为一个不会被读取的文件执行路径解析、存在性检查或格式\n            # 校验。\n            params.bgm_file = \"\"\n        elif not params.bgm_file:\n            # 缺少文件是否构成错误取决于通用 BGM 开关，不能在 argparse 阶段\n            # 无条件拦截，否则 ``custom + 0%`` 会和 WebUI、服务层行为不一致。\n            raise ValueError(\"--bgm-file is required when --bgm-type is custom\")\n        else:\n            try:\n                # CLI、WebUI 和任务服务必须共用同一个 BGM 文件边界。这里直接\n                # 复用服务层解析，既支持用户上传目录和内置歌曲目录，也\n                # 自动继承新增音频格式及路径安全规则，避免多个入口分别\n                # 维护白名单。\n                params.bgm_file = bgm_service.resolve_bgm_file(params.bgm_file)\n            except ValueError as exc:\n                supported_extensions = \", \".join(\n                    bgm_service.SUPPORTED_BGM_EXTENSIONS\n                )\n                raise ValueError(\n                    \"background music must be a supported audio file inside \"\n                    f\"storage/bgm or resource/songs ({supported_extensions}): \"\n                    f\"{params.bgm_file}\"\n                ) from exc\n\n    if params.subtitle_enabled and params.font_name and stop_at == \"video\":\n        font_path = _resolve_managed_resource_file(\n            params.font_name,\n            resource_dir=utils.font_dir(),\n            description=\"subtitle font\",\n        )\n        if not font_path.lower().endswith((\".ttf\", \".ttc\")):\n            raise ValueError(\"subtitle font must use the .ttf or .ttc extension\")\n        # 下游根据 resource/fonts 内的文件名拼接路径，因此仍保留纯文件名。\n        params.font_name = os.path.basename(font_path)\n\n    if params.video_source != \"local\" or stop_at not in {\"materials\", \"video\"}:\n        return","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/cli.py#L681-L717","documentation":"Thrown by the CLI parameter validator when --bgm-type=custom but --bgm-file cannot be resolved by bgm_service.resolve_bgm_file. That service (app/services/bgm.py:303) only accepts audio files whose extension is in SUPPORTED_BGM_EXTENSIONS (.mp3, .m4a, .aac, .wav, .flac, .ogg, .opus, .wma) AND whose path resolves safely inside the user upload directory (storage/bgm) or the built-in song directory (resource/songs). Any other extension, a path-traversal attempt, or a nonexistent file raises ValueError upstream, which the CLI re-raises with this consolidated message.","triggerScenarios":"Running the CLI with --bgm-type custom --bgm-file <path> where: (1) the extension is not one of the eight supported audio extensions (e.g. .mp4, .txt, or no extension); (2) the file does not exist in either storage/bgm or resource/songs; (3) the path tries to escape those directories (e.g. ../secrets.mp3) and is rejected by file_security.resolve_path_within_directory.","commonSituations":"Passing a full absolute path from elsewhere on disk (outside the two whitelisted dirs); uploading an MP4 or video container thinking it works as BGM; typo'd filename; file was deleted or never copied into storage/bgm; script generated the name with a missing extension.","solutions":["Check the extension is one of: .mp3, .m4a, .aac, .wav, .flac, .ogg, .opus, .wma — convert the file (e.g. with ffmpeg -i in.mp4 out.mp3) if it is a different container","Copy the audio file into storage/bgm/ (user uploads) or resource/songs/ (built-in songs), then pass just the filename or a path inside those directories","Verify the file actually exists: ls storage/bgm resource/songs — a nonexistent file fails resolution even with a valid extension","If you need a new audio format supported, add the extension to SUPPORTED_BGM_EXTENSIONS in app/services/bgm.py:28 (CLI, WebUI and task service all inherit it automatically)"],"exampleFix":"# before\n--bgm-type custom --bgm-file /home/user/Music/track.mp4\n\n# after (convert, then place inside the allowed directory)\nffmpeg -i /home/user/Music/track.mp4 /tmp/track.mp3\ncp /tmp/track.mp3 storage/bgm/track.mp3\n--bgm-type custom --bgm-file track.mp3","handlingStrategy":"validation","validationCode":"from app.services import bgm as bgm_service\nfrom pathlib import Path\n\ndef bgm_file_is_valid(path: str) -> bool:\n    if not path or Path(path).suffix.lower() not in bgm_service.SUPPORTED_BGM_EXTENSIONS:\n        return False\n    try:\n        bgm_service.resolve_bgm_file(path)\n        return True\n    except ValueError:\n        return False\n\n# before running the task:\nif params.bgm_type == \"custom\" and not bgm_file_is_valid(params.bgm_file):\n    print(\"BGM file missing, unsupported extension, or outside storage/bgm and resource/songs\")","typeGuard":"def is_supported_bgm_path(path: str) -> bool:\n    \"\"\"Type/value guard: non-empty str with a whitelisted audio extension.\"\"\"\n    return (\n        isinstance(path, str)\n        and bool(path.strip())\n        and Path(path).suffix.lower() in bgm_service.SUPPORTED_BGM_EXTENSIONS\n    )","tryCatchPattern":"try:\n    params.bgm_file = bgm_service.resolve_bgm_file(params.bgm_file)\nexcept ValueError as exc:\n    # exc from the service layer already states whether it is an extension,\n    # existence, or path-traversal failure; log and fail fast.\n    logger.error(\"invalid bgm file %r: %s\", params.bgm_file, exc)\n    raise","preventionTips":["Standardize on one helper (bgm_service.resolve_bgm_file) for every entry point instead of re-implementing the whitelist","Reference SUPPORTED_BGM_EXTENSIONS programmatically rather than hardcoding the extension list in scripts or docs","Keep uploaded BGM files in storage/bgm and built-in songs in resource/songs only","Validate the file right after download/upload (fail early), not at task start"],"tags":["cli","bgm","audio","validation","path-security"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}