harry0703/MoneyPrinterTurbo · error · SoniloError

Sonilo generation failed: {message}

Error message

Sonilo generation failed: {message}

What it means

Raised when the Sonilo stream itself reports failure: an event with type 'error' arrives, and the message is taken from its 'message' or 'error' field (falling back to unknown error). This is the provider's own error channel (content-policy rejections, prompt problems, server-side generation failures) surfaced verbatim in the raised SoniloError.

Source

Thrown at app/services/sonilo.py:234

    把第一条配乐流按事件顺序写入临时文件,并限制最大体积。

    API 可能同时返回多条候选流;当前产品只需要一条 BGM,所以固定选择
    stream_index=0。只有收到 complete 事件并通过 FFmpeg 完整解码后才会发布。
    """
    total_bytes = 0
    title = ""
    completed = False
    with open(temp_audio_path, "wb") as output:
        for raw_line in response.iter_lines():
            if not raw_line:
                continue
            event = _parse_event(raw_line)
            event_type = event["type"]
            if event_type == "error":
                message = str(
                    event.get("message") or event.get("error") or "unknown error"
                )
                raise SoniloError(f"Sonilo generation failed: {message}")
            if event_type == "title":
                title = str(event.get("title") or event.get("data") or "")[:200]
                continue
            if event_type == "complete":
                completed = True
                break
            if event_type != "audio_chunk":
                logger.debug(f"ignoring unsupported Sonilo event: type={event_type}")
                continue

            stream_index = event.get("stream_index", 0)
            if stream_index != 0:
                continue
            encoded_chunk = event.get("data") or event.get("audio")
            if not isinstance(encoded_chunk, str) or not encoded_chunk:
                raise SoniloError("Sonilo returned an empty audio chunk")
            try:
                chunk = base64.b64decode(encoded_chunk, validate=True)

View on GitHub (pinned to 1f9f19c202)

Solutions

  1. Read the embedded message; it is the provider's reason and dictates the fix (policy vs capacity vs credits).
  2. For content-policy messages, rephrase the prompt and/or change the video; retrying unchanged will fail again.
  3. For credit or quota messages, top up or switch the API key, then retry.
  4. For transient provider failures, retry the task after a short delay.
Defensive patterns

Strategy: try-catch

Validate before calling

# keep prompts inside policy before submitting
if len(prompt) > sonilo.MAX_PROMPT_LENGTH:
    prompt = prompt[: sonilo.MAX_PROMPT_LENGTH]

Try / catch

try:
    audio = request_bgm(video, out, prompt)
except SoniloError as exc:
    msg = str(exc)
    if msg.startswith("Sonilo generation failed:"):
        reason = msg.split(":", 1)[1]
        if is_content_policy(reason):
            fail_task_with_user_visible_reason(reason)  # do NOT retry
        else:
            schedule_retry_once()
    raise

Prevention

When it happens

Trigger: POST /v1/video-to-music completes the HTTP handshake with 2xx but the generation later fails server-side and the stream emits an error event. Typical embedded messages: content-policy rejection of the video or prompt, internal generation failure, credit exhaustion mid-generation.

Common situations: Prompt text (up to 2000 chars) trips content moderation; the source video contains flagged content; provider capacity issues abort generation; the account runs out of credits after the request started.

Related errors


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