harry0703/MoneyPrinterTurbo · error · RuntimeError

ffmpeg concat failed

Error message

ffmpeg concat failed

What it means

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.

Source

Thrown at app/services/video.py:378

        ]
        if max_duration is not None and max_duration > 0:
            command.extend(["-t", f"{max_duration:.3f}"])
        command.append(output_file)
        return command

    def run_concat(codec: str):
        command = build_command(codec)
        # 使用 ffmpeg 只做一次串联与编码,避免 MoviePy 逐段合并时反复重编码,
        # 从而降低画质劣化与颜色偏移风险。
        result = subprocess.run(
            command,
            capture_output=True,
            text=True,
            check=False,
        )
        if result.returncode != 0:
            error_message = (result.stderr or result.stdout or "").strip()
            raise RuntimeError(error_message or "ffmpeg concat failed")
        return codec

    try:
        effective_codec = _get_effective_video_codec()
        try:
            return run_concat(effective_codec)
        except Exception as exc:
            if effective_codec == _DEFAULT_VIDEO_CODEC:
                raise
            result_codec = run_concat(_DEFAULT_VIDEO_CODEC)
            _disable_runtime_video_codec(effective_codec, str(exc))
            return result_codec
    finally:
        delete_files(concat_list_file)


def _sanitize_image_file(image_path: str) -> str:
    # 某些本地图片虽然能被 Pillow 打开,但会因为损坏的 EXIF/eXIf 元数据导致

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Read the captured stderr in the RuntimeError message — it is ffmpeg's own diagnostic and names the exact failing argument or encoder.
  2. Run the failing command manually in a shell to reproduce; check 'ffmpeg -encoders | grep <codec>' to verify the codec exists in the installed build.
  3. 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.
  4. Verify all input segment files exist, are non-empty, and share resolution/framerate/pixel format before concat.
  5. Confirm ffmpeg is installed and on PATH (e.g. 'ffmpeg -version').

Example fix

# before: assuming a hardware codec is available
params.video_codec = "h264_videotoolbox"  # may not exist on Linux builds

# after: fall back to the universally supported default
params.video_codec = "libx264"  # matches _DEFAULT_VIDEO_CODEC in app/services/video.py
Defensive patterns

Strategy: fallback

Validate before calling

import shutil
from app.services.video import _DEFAULT_VIDEO_CODEC

codec = _get_effective_video_codec()
encoders = subprocess.run(
    ["ffmpeg", "hide_banner", "-encoders"], capture_output=True, text=True
).stdout
if codec != _DEFAULT_VIDEO_CODEC and codec not in encoders:
    codec = _DEFAULT_VIDEO_CODEC  # pre-empt the runtime fallback path

Try / catch

try:
    combine_videos(segments, codec)
except RuntimeError as exc:
    # message is ffmpeg's own stderr; log it, then retry with libx264
    logger.error("concat failed: %s", exc)
    return combine_videos(segments, "libx264")

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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