{"record":{"id":"6b4173be2d25d42d","repo":"chenhg5/cc-connect","slug":"ffmpeg-compression-failed-w-stderr-s","errorCode":null,"errorMessage":"ffmpeg compression failed: %w (stderr: %s)","messagePattern":"ffmpeg compression failed: %w \\(stderr: (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1331,"sourceCode":"\t}\n\n\targs := []string{\n\t\t\"-i\", \"pipe:0\",\n\t\t\"-ar\", \"16000\", // 16kHz sample rate for voice\n\t\t\"-ac\", \"1\", // mono\n\t\t\"-b:a\", \"64k\", // 64 kbps bitrate (voice quality)\n\t\t\"-f\", \"mp3\",\n\t\t\"-y\",\n\t\t\"pipe:1\",\n\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 compression failed: %w (stderr: %s)\", err, stderr.String())\n\t}\n\n\treturn stdout.Bytes(), \"mp3\", nil\n}\n\n// uploadMedia uploads a file to DingTalk media API and returns the media ID.\n// mediaType should be \"voice\" or \"image\".\nfunc (p *Platform) uploadMedia(ctx context.Context, data []byte, fileName, mediaType string) (string, error) {\n\ttoken, err := p.getAccessToken()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"get access token: %w\", err)\n\t}\n\n\tuploadURL := fmt.Sprintf(\"https://oapi.dingtalk.com/media/upload?access_token=%s&type=%s\", token, mediaType)\n\n\tbody := bytes.NewBuffer(nil)\n\twriter := multipart.NewWriter(body)\n","sourceCodeStart":1313,"sourceCodeEnd":1349,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1313-L1349","documentation":"ffmpeg itself was found and started but exited with a non-zero status while transcoding the WAV input to 16kHz mono 64kbps MP3. The error wraps ffmpeg's exit error plus the process stderr, which contains ffmpeg's own diagnostic (bad input, unsupported codec, etc.).","triggerScenarios":"cmd.Run() returns an error during compressAudioWithFFmpeg — e.g. the stdin bytes are not a valid WAV stream, the file is truncated/corrupt, or the installed ffmpeg build lacks the MP3 (libmp3lame) encoder.","commonSituations":"Upstream TTS produced truncated audio (partial write/cancelled context); a minimal ffmpeg build compiled without libmp3lame; input mislabeled as WAV but actually another codec; OOM kill of the ffmpeg process.","solutions":["Inspect the stderr suffix in the error — it names the real cause (e.g. \"Invalid data\", \"Unknown encoder 'libmp3lame'\").","Install a full ffmpeg build with libmp3lame (e.g. ffmpeg-full).","Validate/repair the source WAV before compressing (check header, RIFF size, non-zero length).","Retry once for transient failures (killed process, interrupted I/O)."],"exampleFix":"// before: passing truncated audio\naudio := buf.Bytes() // buf may be incomplete after context cancel\n// after\nif len(audio) == 0 || !bytes.HasPrefix(audio, []byte(\"RIFF\")) {\n    return errors.New(\"invalid WAV payload\")\n}\nout, format, err := p.compressAudio(ctx, audio, \"wav\")","handlingStrategy":"validation","validationCode":"func looksLikeWav(b []byte) bool { return len(b) > 44 && bytes.HasPrefix(b, []byte(\"RIFF\")) && bytes.Contains(b[:12], []byte(\"WAVE\")) }\nif !looksLikeWav(audio) { return errors.New(\"invalid or truncated WAV input\") }","typeGuard":null,"tryCatchPattern":"out, format, err := p.compressAudio(ctx, audio, \"wav\")\nif err != nil {\n    slog.Warn(\"ffmpeg transcode failed\", \"stderr\", extractStderr(err))\n    return err // surface stderr to user diagnostics\n}","preventionTips":["Install a full ffmpeg build including libmp3lame.","Validate RIFF/WAVE headers and non-truncated size before invoking ffmpeg.","Propagate context cancellation so cancelled uploads don't kill ffmpeg mid-stream."],"tags":["dingtalk","ffmpeg","audio","external-command"],"backgroundTag":"external-command-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}