chenhg5/cc-connect · error

ffmpeg conversion failed: %w (stderr: %s)

Error message

ffmpeg conversion failed: %w (stderr: %s)

What it means

ConvertAudioToMP3 pipes the audio into an ffmpeg subprocess and captures its stderr. When cmd.Run() returns an error — ffmpeg exited non-zero or could not be started — the error is wrapped with the captured stderr so the developer can see ffmpeg's own diagnostic output. This means the input audio was rejected or ffmpeg itself failed, not that ffmpeg is missing (that is a separate error).

Source

Thrown at core/speech.go:337

		)
	} else {
		cmd = exec.CommandContext(ctx, ffmpegPath,
			"-i", "pipe:0",
			"-f", "mp3",
			"-ac", "1",
			"-ar", "16000",
			"-y",
			"pipe:1",
		)
	}

	cmd.Stdin = bytes.NewReader(audio)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

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

// ConvertAudioToOpus uses ffmpeg to convert audio to opus format (ogg container).
// Returns the opus bytes. If ffmpeg is not installed, returns an error.
func ConvertAudioToOpus(ctx context.Context, audio []byte, srcFormat string) ([]byte, error) {
	ffmpegPath, err := exec.LookPath("ffmpeg")
	if err != nil {
		return nil, fmt.Errorf("ffmpeg not found in PATH: install ffmpeg to enable audio conversion")
	}

	args := []string{"-i", "pipe:0", "-c:a", "libopus", "-f", "opus", "-y", "pipe:1"}
	if srcFormat == "amr" || srcFormat == "silk" {
		args = append([]string{"-f", srcFormat}, args...)
	}
	cmd := exec.CommandContext(ctx, ffmpegPath, args...)
	cmd.Stdin = bytes.NewReader(audio)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Read the stderr portion of the error — it contains ffmpeg's exact complaint (unknown format, invalid data, etc.) and fix the input accordingly.
  2. Verify srcFormat matches the actual container/codec of the bytes (e.g. inspect the first bytes or the platform's mime type).
  3. If the error is a context cancellation/deadline, increase the timeout or investigate why conversion is slow.
  4. Re-fetch the audio from the platform if the download may have been truncated, and reject empty buffers before calling.

Example fix

// before
mp3, err := core.ConvertAudioToMP3(ctx, data, "silk")
// after
if len(data) == 0 {
    return fmt.Errorf("empty audio payload")
}
format := detectFormat(mimeType) // e.g. from Content-Type header
mp3, err := core.ConvertAudioToMP3(ctx, data, format)
Defensive patterns

Strategy: try-catch

Validate before calling

if len(audio) == 0 {
    return fmt.Errorf("empty audio payload")
}

Try / catch

mp3, err := core.ConvertAudioToMP3(ctx, audio, srcFormat)
if err != nil {
    var exitErr *exec.ExitError
    if errors.As(err, &exitErr) {
        log.Error("ffmpeg failed", "stderr", extractStderr(err))
    }
    if ctx.Err() != nil {
        return fmt.Errorf("conversion cancelled: %w", ctx.Err())
    }
    return fmt.Errorf("convert audio: %w", err)
}

Prevention

When it happens

Trigger: Calling ConvertAudioToMP3 with bytes that ffmpeg cannot decode (corrupt/truncated upload, wrong srcFormat such as claiming "silk" for mp3 data, unsupported codec), an empty audio buffer, or the ctx being cancelled mid-conversion (cancellation kills the subprocess and surfaces as a signal/killed error).

Common situations: A messaging platform delivers a voice file whose actual codec differs from the declared format; a user sends a zero-byte or partially downloaded file; the context deadline expires on a slow conversion; the installed ffmpeg build lacks a decoder for the source codec.

Related errors


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