{"record":{"id":"fc20165efc1788bf","repo":"chenhg5/cc-connect","slug":"ffmpeg-mp3-to-amr-conversion-failed-w-stderr","errorCode":null,"errorMessage":"ffmpeg MP3 to AMR conversion failed: %w (stderr: %s)","messagePattern":"ffmpeg MP3 to AMR conversion failed: %w \\(stderr: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/speech.go","lineNumber":456,"sourceCode":"\n\targs := []string{\n\t\t\"-i\", \"pipe:0\",\n\t\t\"-c:a\", \"amr_nb\",\n\t\t\"-ar\", \"8000\",     // 8kHz sample rate (AMR-NB standard)\n\t\t\"-ac\", \"1\",        // mono\n\t\t\"-b:a\", \"12.2k\",   // 12.2 kbps bitrate (AMR-NB max)\n\t\t\"-f\", \"amr\",\n\t\t\"-y\",\n\t\t\"pipe:1\",\n\t}\n\tcmd := exec.CommandContext(ctx, ffmpegPath, args...)\n\tcmd.Stdin = bytes.NewReader(mp3Data)\n\tvar stdout, stderr bytes.Buffer\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, fmt.Errorf(\"ffmpeg MP3 to AMR conversion failed: %w (stderr: %s)\", err, stderr.String())\n\t}\n\treturn stdout.Bytes(), nil\n}\n\n// NeedsConversion returns true if the audio format is not directly supported by Whisper API.\nfunc NeedsConversion(format string) bool {\n\tswitch strings.ToLower(format) {\n\tcase \"mp3\", \"mp4\", \"mpeg\", \"mpga\", \"m4a\", \"wav\", \"webm\":\n\t\treturn false\n\tdefault:\n\t\treturn true\n\t}\n}\n\n// HasFFmpeg checks if ffmpeg is available.\nfunc HasFFmpeg() bool {\n\t_, err := exec.LookPath(\"ffmpeg\")\n\treturn err == nil","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/speech.go#L438-L474","documentation":"ConvertMP3ToAMR pipes MP3 bytes into ffmpeg and converts them to AMR-NB (8kHz mono, 12.2kbps). If cmd.Run() fails, the error is wrapped as \"ffmpeg MP3 to AMR conversion failed\" with the captured stderr appended. ffmpeg was found and launched, so the failure is in decoding the MP3 or encoding AMR — the stderr text pinpoints which.","triggerScenarios":"SendAudio (or a direct call) passes bytes ffmpeg cannot decode as MP3, an empty buffer, or a payload whose real format differs from MP3; an ffmpeg build without the amr_nb encoder; or ctx cancellation killing the subprocess mid-conversion.","commonSituations":"Voice downloads that are actually OGG/WAV despite .mp3 naming; truncated files after flaky downloads; stripped ffmpeg builds lacking native AMR support; short context deadlines on large audio.","solutions":["Examine the stderr in the error — it states whether decode (Invalid data) or encode (Unknown encoder 'amr_nb') failed.","Install an ffmpeg build with AMR encoder support if the encoder is missing.","Verify the payload is genuinely MP3 before converting (ID3 header or MPEG frame sync).","For cancellations, extend the timeout; re-fetch or reject empty/truncated audio."],"exampleFix":"// before\namr, err := core.ConvertMP3ToAMR(ctx, mp3Data)\nif err != nil {\n    return err\n}\n// after\namr, err := core.ConvertMP3ToAMR(ctx, mp3Data)\nif err != nil {\n    return fmt.Errorf(\"send audio: convert mp3 to amr: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if len(mp3) == 0 || !(bytes.HasPrefix(mp3, []byte(\"ID3\")) || mp3[0] == 0xFF) {\n    return fmt.Errorf(\"invalid MP3 payload\")\n}\n","typeGuard":null,"tryCatchPattern":"amr, err := core.ConvertMP3ToAMR(ctx, mp3Data)\nif err != nil {\n    log.Error(\"mp3->amr failed\", \"stderr\", extractStderr(err))\n    return fmt.Errorf(\"prepare voice message: %w\", err)\n}","preventionTips":["Validate MP3 headers before handing bytes to the converter.","Ensure the ffmpeg build has the native AMR encoder enabled.","Size context timeouts to the audio duration to avoid cancellation kills.","Always inspect the stderr embedded in the wrapped error — it distinguishes decode vs encode failures."],"tags":["ffmpeg","audio","subprocess","amr","conversion-failed"],"backgroundTag":"ffmpeg-conversion-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}