{"record":{"id":"b73a092125f84e75","repo":"harry0703/MoneyPrinterTurbo","slug":"elevenlabs-returned-audio-that-ffmpeg-cannot-decod","errorCode":null,"errorMessage":"ElevenLabs returned audio that FFmpeg cannot decode","messagePattern":"ElevenLabs returned audio that FFmpeg cannot decode","errorType":"exception","errorClass":"ElevenLabsMusicError","httpStatus":null,"severity":"error","filePath":"app/services/elevenlabs_music.py","lineNumber":349,"sourceCode":"                with response:\n                    if not response.ok:\n                        raise ElevenLabsMusicError(\n                            \"ElevenLabs generation failed \"\n                            f\"({response.status_code}): \"\n                            f\"{_safe_response_error(response)}\"\n                        )\n                    total_bytes = _stream_audio(response, temp_audio_path)\n        except requests.RequestException as exc:\n            # 下载阶段断线也属于请求失败，必须进入任务降级逻辑，不能留下半条\n            # 音频或让已经生成的视频因为第三方网络波动整体失败。\n            raise ElevenLabsMusicError(\n                f\"failed to request ElevenLabs music: {exc}\"\n            ) from exc\n\n        try:\n            bgm_service.validate_audio_file(temp_audio_path, timeout_seconds=120)\n        except (bgm_service.BgmUploadError, bgm_service.BgmServiceError) as exc:\n            raise ElevenLabsMusicError(\n                \"ElevenLabs returned audio that FFmpeg cannot decode\"\n            ) from exc\n        os.replace(temp_audio_path, output_path)\n        temp_audio_path = \"\"\n        logger.info(\n            \"ElevenLabs background music generated: \"\n            f\"output={output_path}, size={total_bytes} bytes\"\n        )\n        return output_path\n    finally:\n        _remove_file(temp_audio_path)\n\n\ndef generate_bgm(\n    video_path: str,\n    output_path: str,\n    video_duration: float,\n    prompt: str = \"\",","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/services/elevenlabs_music.py#L331-L367","documentation":"Raised after a successful download when the audio ElevenLabs returned fails the local FFmpeg decode check (bgm_service.validate_audio_file with a 120s timeout). It means the HTTP call succeeded but the bytes on disk are not a decodable audio file — e.g. a JSON error body saved with 200, a truncated stream, or an unsupported codec.","triggerScenarios":"_stream_audio wrote fewer bytes than expected (connection cut but requests did not raise), ElevenLabs returned an error payload with a 200 status, or the returned audio codec/container is not decodable by the bundled FFmpeg build. validate_audio_file then exits non-zero and raises BgmUploadError/BgmServiceError.","commonSituations":"MITM proxies that rewrite responses, partial writes when the process is SIGSTOPed mid-download, ElevenLabs serving a new audio format after an API update, or an FFmpeg binary missing from PATH so validation fails for every file.","solutions":["Manually inspect the temp audio bytes (the finally block deletes it, so reproduce with a raw curl to /v1/music/video-to-music) to see whether it is JSON/HTML instead of audio","Confirm ffmpeg is installed and on PATH — a missing FFmpeg makes every validation fail regardless of the audio","Retry the request; truncated streams are usually transient server-side or network issues","If ElevenLabs changed its output format, pin/switch music_model_id between music_v1 and music_v2 and retest"],"exampleFix":"# before\nbgm_service.validate_audio_file(temp_audio_path, timeout_seconds=120)  # opaque failure\n\n# after\n# capture format info for diagnosis before failing the task\nprobe = subprocess.run(\n    [\"ffprobe\", \"-v\", \"error\", \"-show_format\", temp_audio_path],\n    capture_output=True, text=True, timeout=30,\n)\nlogger.warning(f\"elevenlabs audio probe: rc={probe.returncode} err={probe.stderr[:200]}\")\nbgm_service.validate_audio_file(temp_audio_path, timeout_seconds=120)","handlingStrategy":"validation","validationCode":"import shutil\nassert shutil.which(\"ffmpeg\") and shutil.which(\"ffprobe\"), \"ffmpeg/ffprobe required\"","typeGuard":null,"tryCatchPattern":"try:\n    elm.generate_bgm(video, out, duration, prompt)\nexcept elm.ElevenLabsMusicError as e:\n    if \"cannot decode\" in str(e):\n        log_probe_details(video)  # ffprobe the raw response once, then give up BGM\n    raise_task_degradation()","preventionTips":["Verify ffmpeg/ffprobe are installed and on PATH in the deployment image","Retry once — truncated audio streams are often transient","Pin music_model_id to a known-good value when ElevenLabs ships format changes"],"tags":["ffmpeg","audio","validation","elevenlabs"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}