chenhg5/cc-connect · error

ffmpeg MP3 to AMR conversion failed: %w (stderr: %s)

Error message

ffmpeg MP3 to AMR conversion failed: %w (stderr: %s)

What it means

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.

Source

Thrown at core/speech.go:456

	args := []string{
		"-i", "pipe:0",
		"-c:a", "amr_nb",
		"-ar", "8000",     // 8kHz sample rate (AMR-NB standard)
		"-ac", "1",        // mono
		"-b:a", "12.2k",   // 12.2 kbps bitrate (AMR-NB max)
		"-f", "amr",
		"-y",
		"pipe:1",
	}
	cmd := exec.CommandContext(ctx, ffmpegPath, args...)
	cmd.Stdin = bytes.NewReader(mp3Data)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		return nil, fmt.Errorf("ffmpeg MP3 to AMR conversion failed: %w (stderr: %s)", err, stderr.String())
	}
	return stdout.Bytes(), nil
}

// NeedsConversion returns true if the audio format is not directly supported by Whisper API.
func NeedsConversion(format string) bool {
	switch strings.ToLower(format) {
	case "mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm":
		return false
	default:
		return true
	}
}

// HasFFmpeg checks if ffmpeg is available.
func HasFFmpeg() bool {
	_, err := exec.LookPath("ffmpeg")
	return err == nil

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Examine the stderr in the error — it states whether decode (Invalid data) or encode (Unknown encoder 'amr_nb') failed.
  2. Install an ffmpeg build with AMR encoder support if the encoder is missing.
  3. Verify the payload is genuinely MP3 before converting (ID3 header or MPEG frame sync).
  4. For cancellations, extend the timeout; re-fetch or reject empty/truncated audio.

Example fix

// before
amr, err := core.ConvertMP3ToAMR(ctx, mp3Data)
if err != nil {
    return err
}
// after
amr, err := core.ConvertMP3ToAMR(ctx, mp3Data)
if err != nil {
    return fmt.Errorf("send audio: convert mp3 to amr: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if len(mp3) == 0 || !(bytes.HasPrefix(mp3, []byte("ID3")) || mp3[0] == 0xFF) {
    return fmt.Errorf("invalid MP3 payload")
}

Try / catch

amr, err := core.ConvertMP3ToAMR(ctx, mp3Data)
if err != nil {
    log.Error("mp3->amr failed", "stderr", extractStderr(err))
    return fmt.Errorf("prepare voice message: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/fc20165efc1788bf. Report an issue: GitHub.