{"record":{"id":"b81c230ddbac8cc3","repo":"harry0703/MoneyPrinterTurbo","slug":"ffmpeg-concat-failed","errorCode":null,"errorMessage":"ffmpeg concat failed","messagePattern":"ffmpeg concat failed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/services/video.py","lineNumber":378,"sourceCode":"        ]\n        if max_duration is not None and max_duration > 0:\n            command.extend([\"-t\", f\"{max_duration:.3f}\"])\n        command.append(output_file)\n        return command\n\n    def run_concat(codec: str):\n        command = build_command(codec)\n        # 使用 ffmpeg 只做一次串联与编码，避免 MoviePy 逐段合并时反复重编码，\n        # 从而降低画质劣化与颜色偏移风险。\n        result = subprocess.run(\n            command,\n            capture_output=True,\n            text=True,\n            check=False,\n        )\n        if result.returncode != 0:\n            error_message = (result.stderr or result.stdout or \"\").strip()\n            raise RuntimeError(error_message or \"ffmpeg concat failed\")\n        return codec\n\n    try:\n        effective_codec = _get_effective_video_codec()\n        try:\n            return run_concat(effective_codec)\n        except Exception as exc:\n            if effective_codec == _DEFAULT_VIDEO_CODEC:\n                raise\n            result_codec = run_concat(_DEFAULT_VIDEO_CODEC)\n            _disable_runtime_video_codec(effective_codec, str(exc))\n            return result_codec\n    finally:\n        delete_files(concat_list_file)\n\n\ndef _sanitize_image_file(image_path: str) -> str:\n    # 某些本地图片虽然能被 Pillow 打开，但会因为损坏的 EXIF/eXIf 元数据导致","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/video.py#L360-L396","documentation":"Raised when an ffmpeg subprocess that concatenates and encodes video segments exits with a non-zero return code. The code deliberately runs ffmpeg once (instead of MoviePy per-segment merges) and surfaces ffmpeg's own stderr as the exception message. When the effective codec is not the default (libx264), it retries once with the default codec and disables the failed codec for the runtime.","triggerScenarios":"Calling the concat routine with a non-default video codec (e.g. a hardware codec like h264_videotoolbox) that ffmpeg cannot handle on this machine; corrupt or zero-length intermediate segment files; an ffmpeg binary missing from PATH; unsupported pixel format / codec combination producing ffmpeg exit code != 0.","commonSituations":"User configured a hardware-accelerated encoder in settings that is unavailable in their ffmpeg build; one of the generated video clips is truncated because a prior step was interrupted; older ffmpeg version lacking the requested encoder; odd container/codec mismatch in the concat demuxer.","solutions":["Read the captured stderr in the RuntimeError message — it is ffmpeg's own diagnostic and names the exact failing argument or encoder.","Run the failing command manually in a shell to reproduce; check 'ffmpeg -encoders | grep <codec>' to verify the codec exists in the installed build.","If the codec is unavailable, switch the video codec setting back to libx264 (the default fallback) or install an ffmpeg build that includes the codec.","Verify all input segment files exist, are non-empty, and share resolution/framerate/pixel format before concat.","Confirm ffmpeg is installed and on PATH (e.g. 'ffmpeg -version')."],"exampleFix":"# before: assuming a hardware codec is available\nparams.video_codec = \"h264_videotoolbox\"  # may not exist on Linux builds\n\n# after: fall back to the universally supported default\nparams.video_codec = \"libx264\"  # matches _DEFAULT_VIDEO_CODEC in app/services/video.py","handlingStrategy":"fallback","validationCode":"import shutil\nfrom app.services.video import _DEFAULT_VIDEO_CODEC\n\ncodec = _get_effective_video_codec()\nencoders = subprocess.run(\n    [\"ffmpeg\", \"hide_banner\", \"-encoders\"], capture_output=True, text=True\n).stdout\nif codec != _DEFAULT_VIDEO_CODEC and codec not in encoders:\n    codec = _DEFAULT_VIDEO_CODEC  # pre-empt the runtime fallback path","typeGuard":null,"tryCatchPattern":"try:\n    combine_videos(segments, codec)\nexcept RuntimeError as exc:\n    # message is ffmpeg's own stderr; log it, then retry with libx264\n    logger.error(\"concat failed: %s\", exc)\n    return combine_videos(segments, \"libx264\")","preventionTips":["Verify required encoders exist in the installed ffmpeg build before starting a long pipeline.","Check segment files are non-empty and share codec parameters before concat.","Let the built-in default-codec fallback run — it also disables the bad codec for the rest of the runtime."],"tags":["ffmpeg","video","subprocess","codec"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}