chenhg5/cc-connect · error

ffmpeg not found in PATH: install ffmpeg to enable audio con

Error message

ffmpeg not found in PATH: install ffmpeg to enable audio conversion

What it means

ConvertAudioToOpus converts audio to Opus-in-OGG (used for voice notes on platforms like Telegram) by invoking ffmpeg. Like the other Convert* helpers, it first probes for ffmpeg with exec.LookPath and returns this error when the binary cannot be found in PATH. Opus encoding also requires an ffmpeg build that includes libopus; the presence check here only covers the binary itself.

Source

Thrown at core/speech.go:347

	}

	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)
	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

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

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Install ffmpeg (`apt-get install ffmpeg`, `apk add ffmpeg`, `brew install ffmpeg`).
  2. Ensure the install includes libopus support (`ffmpeg -encoders | grep opus` shows libopus).
  3. Add ffmpeg's location to the PATH of the cc-connect process (systemd Environment=PATH=..., Docker ENV).
  4. Verify with `which ffmpeg` run as the same user the daemon runs as.

Example fix

// docker-compose before
services:
  cc-connect:
    image: alpine:3.20
// after
services:
  cc-connect:
    image: alpine:3.20
    # in Dockerfile: RUN apk add --no-cache ffmpeg
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := exec.LookPath("ffmpeg"); err != nil {
    return fmt.Errorf("audio conversion unavailable: %w", err)
}

Type guard

func hasFFmpeg() bool { _, err := exec.LookPath("ffmpeg"); return err == nil }

Try / catch

opus, err := core.ConvertAudioToOpus(ctx, audio, format)
if err != nil && strings.Contains(err.Error(), "ffmpeg not found") {
    return sendRawAudio(audio) // send original bytes instead
}

Prevention

When it happens

Trigger: Calling ConvertAudioToOpus (directly or via SendAudio) on a host where `exec.LookPath("ffmpeg")` fails: ffmpeg not installed, not in the daemon's PATH, or the service runs in a container image that omits it.

Common situations: Alpine/slim Docker images without the ffmpeg package; systemd services with a minimal default PATH; self-hosted bots on fresh VPS instances; ffmpeg installed via snap/nix in a directory the service user does not have on PATH.

Related errors


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