chenhg5/cc-connect · error

ffmpeg not found in PATH: %w

Error message

ffmpeg not found in PATH: %w

What it means

ConvertMP3ToOGG converts MP3 voice data to Opus-in-OGG via an ffmpeg subprocess. When exec.LookPath("ffmpeg") fails, the error is wrapped as "ffmpeg not found in PATH: %w", preserving the underlying LookPath error (e.g. exec.ErrNotFound). Unlike the earlier converters, this variant keeps the wrapped cause, so the message includes why the lookup failed.

Source

Thrown at core/speech.go:405

	}
	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 AMR conversion failed: %w (stderr: %s)", err, stderr.String())
	}
	return stdout.Bytes(), nil
}

// ConvertMP3ToOGG converts MP3 audio to OGG format using ffmpeg with stdin/stdout pipes.
// Optimized for voice: Opus codec, 16kHz mono, 32kbps, voip application.
func ConvertMP3ToOGG(ctx context.Context, mp3Data []byte) ([]byte, error) {
	ffmpegPath, err := exec.LookPath("ffmpeg")
	if err != nil {
		return nil, fmt.Errorf("ffmpeg not found in PATH: %w", err)
	}

	args := []string{
		"-i", "pipe:0",
		"-c:a", "libopus",
		"-ar", "16000",       // 16kHz sample rate for voice
		"-ac", "1",           // mono
		"-b:a", "32k",        // 32 kbps bitrate (voice quality)
		"-application", "voip", // optimize for voice
		"-f", "ogg",
		"-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

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Install ffmpeg (`apt-get install -y ffmpeg`, `brew install ffmpeg`, `apk add ffmpeg`).
  2. If installed, fix PATH for the daemon process (systemd Environment=, Docker ENV, launchd plist).
  3. Confirm with `which ffmpeg` executed as the service user.
  4. If MP3-to-OGG conversion is optional, guard the call site and send the original audio when ffmpeg is unavailable.

Example fix

// before
ogg, err := core.ConvertMP3ToOGG(ctx, mp3)
send(ogg)
// after
ogg, err := core.ConvertMP3ToOGG(ctx, mp3)
if err != nil && strings.Contains(err.Error(), "ffmpeg not found") {
    send(mp3) // fall back to original format
    return nil
}
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := exec.LookPath("ffmpeg"); err != nil {
    return nil // caller sends original MP3 instead
}

Type guard

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

Try / catch

ogg, err := core.ConvertMP3ToOGG(ctx, mp3)
if err != nil {
    if strings.Contains(err.Error(), "ffmpeg not found") {
        return mp3, nil // graceful degradation to original format
    }
    return nil, fmt.Errorf("convert to ogg: %w", err)
}

Prevention

When it happens

Trigger: Calling ConvertMP3ToOGG (directly or via SendAudio) on a system where ffmpeg is not installed or not visible in the process's PATH environment variable.

Common situations: Docker images built from slim/alpine bases; production servers provisioned without media tooling; daemons whose PATH differs from the interactive shell (launchd GUI apps, systemd with default PATH); ffmpeg installed only for one user.

Related errors


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