harry0703/MoneyPrinterTurbo · error · ElevenLabsMusicError

ElevenLabs generation failed ({response.status_code}): {_saf

Error message

ElevenLabs generation failed ({response.status_code}): {_safe_response_error(response)}

What it means

Raised by _request_bgm when the ElevenLabs video-to-music HTTP call (POST /v1/music/video-to-music) returns a non-2xx status. The message embeds the HTTP status code and a truncated (<=500 bytes) response body read via _safe_response_error, so the upstream ElevenLabs error text is preserved without dumping the whole body into logs.

Source

Thrown at app/services/elevenlabs_music.py:333

                    f"{_base_url()}{VIDEO_TO_MUSIC_PATH}",
                    headers={"xi-api-key": get_api_key()},
                    params={"output_format": "mp3_44100_128"},
                    files=[
                        (
                            # 官方文档把表单数组展示为 ``videos[]``,但 2026-07-18
                            # 生产接口会对该字段返回 422,实际 Starlette 参数名为
                            # ``videos``。重复上传时 requests 可继续添加同名字段。
                            "videos",
                            (Path(video_path).name, video_file, "video/mp4"),
                        )
                    ],
                    data=request_data,
                    stream=True,
                    timeout=_request_timeout(),
                )
                with response:
                    if not response.ok:
                        raise ElevenLabsMusicError(
                            "ElevenLabs generation failed "
                            f"({response.status_code}): "
                            f"{_safe_response_error(response)}"
                        )
                    total_bytes = _stream_audio(response, temp_audio_path)
        except requests.RequestException as exc:
            # 下载阶段断线也属于请求失败,必须进入任务降级逻辑,不能留下半条
            # 音频或让已经生成的视频因为第三方网络波动整体失败。
            raise ElevenLabsMusicError(
                f"failed to request ElevenLabs music: {exc}"
            ) from exc

        try:
            bgm_service.validate_audio_file(temp_audio_path, timeout_seconds=120)
        except (bgm_service.BgmUploadError, bgm_service.BgmServiceError) as exc:
            raise ElevenLabsMusicError(
                "ElevenLabs returned audio that FFmpeg cannot decode"
            ) from exc

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Read the embedded status code and body: 401/403 means rotate the key or grant the Music endpoint permission; 422 usually means the proxy expects the 'videos' multipart field or the prompt/duration is malformed
  2. Run test_connection() first to verify the key and that the account is not on a free plan
  3. Check music_base_url in config; it must point at https://api.elevenlabs.io or a compatible proxy that mirrors the video-to-music API
  4. Retry once after a delay if the status is 429 or 5xx — both are transient on ElevenLabs

Example fix

# before
output = _request_bgm(proxy_path, out_path, prompt)  # raises opaque ElevenLabsMusicError mid-pipeline

# after
from app.services import elevenlabs_music as elm
elm.test_connection()  # cheap preflight: verifies key + paid plan before any upload
output = elm.generate_bgm(video_path, out_path, duration, prompt)
Defensive patterns

Strategy: validation

Validate before calling

from app.services import elevenlabs_music as elm

elm.test_connection()  # raises ElevenLabsAuthenticationError / PaidPlanRequired early
assert len(prompt.strip()) <= 1000 and 0 < duration <= 600

Try / catch

try:
    out = elm.generate_bgm(video, out_path, duration, prompt)
except elm.ElevenLabsAuthenticationError:
    notify_user("invalid ElevenLabs key")
except elm.ElevenLabsMusicError as e:
    log_and_degrade(e)  # keep video without BGM instead of failing the task

Prevention

When it happens

Trigger: ElevenLabs rejects the multipart upload: 401/403 for a bad or endpoint-restricted API key, 422 for wrong multipart field names or invalid prompt/duration, 429 for quota exhaustion, 5xx for ElevenLabs outages. Only raised when response.ok is false after the streaming POST completes the status phase.

Common situations: Free-plan key without Music API access, key restricted per-endpoint in the ElevenLabs dashboard, prompt longer than 1000 chars slipping past client checks, wrong music_base_url (self-hosted proxy returning HTML errors), or rate limiting during batch video generation.

Related errors


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