{"record":{"id":"24307843b3165788","repo":"chenhg5/cc-connect","slug":"ffmpeg-not-found-in-path-install-ffmpeg-to-enable","errorCode":null,"errorMessage":"ffmpeg not found in PATH: install ffmpeg to enable voice message support","messagePattern":"ffmpeg not found in PATH: install ffmpeg to enable voice message support","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/speech.go","lineNumber":306,"sourceCode":"\t}\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"gemini stt: parse response: %w\", err)\n\t}\n\tif len(result.Candidates) == 0 || len(result.Candidates[0].Content.Parts) == 0 {\n\t\treturn \"\", fmt.Errorf(\"gemini stt: empty response\")\n\t}\n\n\treturn strings.TrimSpace(result.Candidates[0].Content.Parts[0].Text), nil\n}\n\n// ConvertAudioToMP3 uses ffmpeg to convert audio from unsupported formats to mp3.\n// Returns the mp3 bytes. If ffmpeg is not installed, returns an error.\n// The ctx is honored: cancellation kills the ffmpeg subprocess, matching the\n// behavior of the other Convert* helpers in this file.\nfunc ConvertAudioToMP3(ctx context.Context, audio []byte, srcFormat string) ([]byte, error) {\n\tffmpegPath, err := exec.LookPath(\"ffmpeg\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"ffmpeg not found in PATH: install ffmpeg to enable voice message support\")\n\t}\n\n\tvar cmd *exec.Cmd\n\tif srcFormat == \"amr\" || srcFormat == \"silk\" {\n\t\tcmd = exec.CommandContext(ctx, ffmpegPath,\n\t\t\t\"-f\", srcFormat,\n\t\t\t\"-i\", \"pipe:0\",\n\t\t\t\"-f\", \"mp3\",\n\t\t\t\"-ac\", \"1\",\n\t\t\t\"-ar\", \"16000\",\n\t\t\t\"-y\",\n\t\t\t\"pipe:1\",\n\t\t)\n\t} else {\n\t\tcmd = exec.CommandContext(ctx, ffmpegPath,\n\t\t\t\"-i\", \"pipe:0\",\n\t\t\t\"-f\", \"mp3\",\n\t\t\t\"-ac\", \"1\",","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/speech.go#L288-L324","documentation":"ConvertAudioToMP3 converts raw audio bytes (wav, amr, silk, etc.) to MP3 by shelling out to ffmpeg. Before spawning the subprocess it runs exec.LookPath(\"ffmpeg\"); if ffmpeg is not installed or not on the PATH, it returns this error instead of attempting the conversion. The library intentionally refuses to guess an ffmpeg location, so voice transcription cannot proceed without the binary present.","triggerScenarios":"Calling ConvertAudioToMP3 (directly or via TranscribeAudio) on a machine where `exec.LookPath(\"ffmpeg\")` fails: ffmpeg not installed, installed but not in the PATH of the process (e.g. systemd service with a minimal PATH, Docker scratch/slim image, GUI-launched app with a stripped environment).","commonSituations":"Deploying cc-connect in a minimal Docker image without ffmpeg; running the daemon under systemd where PATH is /usr/bin:/bin and ffmpeg was installed via a user-local tool (homebrew, ~/.local/bin); fresh macOS/Linux box where voice messages were never tested; switching from dev machine (ffmpeg present) to production (ffmpeg absent).","solutions":["Install ffmpeg: `apt-get install -y ffmpeg` (Debian/Ubuntu), `brew install ffmpeg` (macOS), or the equivalent for your distro.","If ffmpeg is already installed, ensure its directory is in the PATH of the cc-connect process (set PATH in the systemd unit, Dockerfile ENV, or launchd plist).","Verify from the same environment the daemon runs in: `which ffmpeg` or `sudo -u <daemonuser> which ffmpeg`.","If voice transcription is not needed, disable the voice/audio feature in config so TranscribeAudio is never invoked."],"exampleFix":"// Dockerfile before\nFROM golang:1.22-alpine\n// after\nFROM golang:1.22-alpine\nRUN apk add --no-cache ffmpeg","handlingStrategy":"fallback","validationCode":"if _, err := exec.LookPath(\"ffmpeg\"); err != nil {\n    // ffmpeg unavailable — skip voice transcription or warn the user\n}\n","typeGuard":"func ffmpegAvailable() bool { _, err := exec.LookPath(\"ffmpeg\"); return err == nil }","tryCatchPattern":"mp3, err := core.ConvertAudioToMP3(ctx, audio, format)\nif err != nil {\n    if strings.Contains(err.Error(), \"ffmpeg not found\") {\n        log.Warn(\"voice transcription unavailable: ffmpeg not installed\")\n        return nil // degrade gracefully\n    }\n    return fmt.Errorf(\"transcribe: %w\", err)\n}","preventionTips":["Add ffmpeg to the base Docker image / provisioning script of any deployment that handles voice.","Run a startup health check that calls exec.LookPath(\"ffmpeg\") and logs a clear warning when absent.","Set an explicit PATH in systemd/launchd unit files so user-local ffmpeg installs are found.","Test voice-message flows in a production-like minimal environment, not only on a dev machine."],"tags":["ffmpeg","external-dependency","audio","environment"],"backgroundTag":"command-not-found","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}