{"record":{"id":"cb4d93678e59c3cf","repo":"chenhg5/cc-connect","slug":"ffmpeg-not-found-in-path-w","errorCode":null,"errorMessage":"ffmpeg not found in PATH: %w","messagePattern":"ffmpeg not found in PATH: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/speech.go","lineNumber":405,"sourceCode":"\t}\n\tcmd := exec.CommandContext(ctx, ffmpegPath, args...)\n\tcmd.Stdin = bytes.NewReader(audio)\n\tvar stdout, stderr bytes.Buffer\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr\n\n\tif err := cmd.Run(); err != nil {\n\t\treturn nil, fmt.Errorf(\"ffmpeg AMR conversion failed: %w (stderr: %s)\", err, stderr.String())\n\t}\n\treturn stdout.Bytes(), nil\n}\n\n// ConvertMP3ToOGG converts MP3 audio to OGG format using ffmpeg with stdin/stdout pipes.\n// Optimized for voice: Opus codec, 16kHz mono, 32kbps, voip application.\nfunc ConvertMP3ToOGG(ctx context.Context, mp3Data []byte) ([]byte, error) {\n\tffmpegPath, err := exec.LookPath(\"ffmpeg\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"ffmpeg not found in PATH: %w\", err)\n\t}\n\n\targs := []string{\n\t\t\"-i\", \"pipe:0\",\n\t\t\"-c:a\", \"libopus\",\n\t\t\"-ar\", \"16000\",       // 16kHz sample rate for voice\n\t\t\"-ac\", \"1\",           // mono\n\t\t\"-b:a\", \"32k\",        // 32 kbps bitrate (voice quality)\n\t\t\"-application\", \"voip\", // optimize for voice\n\t\t\"-f\", \"ogg\",\n\t\t\"-y\",\n\t\t\"pipe:1\",\n\t}\n\tcmd := exec.CommandContext(ctx, ffmpegPath, args...)\n\tcmd.Stdin = bytes.NewReader(mp3Data)\n\tvar stdout, stderr bytes.Buffer\n\tcmd.Stdout = &stdout\n\tcmd.Stderr = &stderr","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/speech.go#L387-L423","documentation":"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.","triggerScenarios":"Calling ConvertMP3ToOGG (directly or via SendAudio) on a system where ffmpeg is not installed or not visible in the process's PATH environment variable.","commonSituations":"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.","solutions":["Install ffmpeg (`apt-get install -y ffmpeg`, `brew install ffmpeg`, `apk add ffmpeg`).","If installed, fix PATH for the daemon process (systemd Environment=, Docker ENV, launchd plist).","Confirm with `which ffmpeg` executed as the service user.","If MP3-to-OGG conversion is optional, guard the call site and send the original audio when ffmpeg is unavailable."],"exampleFix":"// before\nogg, err := core.ConvertMP3ToOGG(ctx, mp3)\nsend(ogg)\n// after\nogg, err := core.ConvertMP3ToOGG(ctx, mp3)\nif err != nil && strings.Contains(err.Error(), \"ffmpeg not found\") {\n    send(mp3) // fall back to original format\n    return nil\n}","handlingStrategy":"fallback","validationCode":"if _, err := exec.LookPath(\"ffmpeg\"); err != nil {\n    return nil // caller sends original MP3 instead\n}\n","typeGuard":"func ffmpegPresent() bool { _, err := exec.LookPath(\"ffmpeg\"); return err == nil }","tryCatchPattern":"ogg, err := core.ConvertMP3ToOGG(ctx, mp3)\nif err != nil {\n    if strings.Contains(err.Error(), \"ffmpeg not found\") {\n        return mp3, nil // graceful degradation to original format\n    }\n    return nil, fmt.Errorf(\"convert to ogg: %w\", err)\n}","preventionTips":["Install ffmpeg at image-build time, not at runtime.","Keep an environment probe at startup that reports missing external binaries.","Ensure PATH in service units includes the directory where ffmpeg is installed.","Design call sites to degrade to the unconverted format when ffmpeg is absent."],"tags":["ffmpeg","external-dependency","audio","ogg"],"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"}