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
- 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').
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
- 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.
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
- Sonilo video proxy generation timed out
- failed to generate Sonilo video proxy: {detail}
- Sonilo video proxy is empty or exceeds the 300 MB limit
- {request_id}: background music validation is unavailable
- uploaded file must contain a decodable audio stream
AI-assisted analysis of harry0703/MoneyPrinterTurbo@1f9f19c202 (2026-08-14).
Data as JSON: /api/errors/b81c230ddbac8cc3.
Report an issue: GitHub.