{"record":{"id":"c09f9e3f3cb4f54b","repo":"chenhg5/cc-connect","slug":"pico2wave-produced-empty-audio-file","errorCode":null,"errorMessage":"pico2wave: produced empty audio file","messagePattern":"pico2wave: produced empty audio file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tts.go","lineNumber":650,"sourceCode":"\t\t\"--wave=\" + tmpPath,\n\t\ttext,\n\t}\n\n\t// Execute pico2wave command\n\tcmd := exec.CommandContext(ctx, p.Path, args...)\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"pico2wave: voice=%s text=%q: %w, output: %s\", voice, text, err, string(output))\n\t}\n\n\t// Read the generated WAV file\n\taudioData, err := os.ReadFile(tmpPath)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"pico2wave: read output file: %w\", err)\n\t}\n\n\tif len(audioData) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(\"pico2wave: produced empty audio file\")\n\t}\n\n\treturn audioData, \"wav\", nil\n}\n\n// ──────────────────────────────────────────────────────────────\n// EdgeTTS — Microsoft Edge TTS (free, high quality, requires network)\n// ──────────────────────────────────────────────────────────────\n\n// EdgeTTS implements TextToSpeech using Microsoft Edge's free TTS API.\n// This uses the edge-tts CLI command under the hood.\ntype EdgeTTS struct {\n\tPath  string // path to edge-tts executable (empty = \"edge-tts\")\n\tVoice string // default voice (e.g. \"zh-CN-XiaoxiaoNeural\")\n}\n\n// NewEdgeTTS creates a new EdgeTTS instance.\nfunc NewEdgeTTS(voice string) *EdgeTTS {","sourceCodeStart":632,"sourceCodeEnd":668,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/tts.go#L632-L668","documentation":"PicoTTS.Synthesize (core/tts.go:650) runs the external pico2wave CLI to synthesize text into a WAV temp file, then reads it back. This error is returned when pico2wave exits successfully (exit code 0) but wrote a zero-byte WAV file, meaning no audio was actually produced. The library treats a silent/empty output as a synthesis failure rather than returning empty audio to the caller.","triggerScenarios":"Calling PicoTTS.Synthesize (directly or via the TTS engine) when the pico2wave binary exits 0 but creates no WAV content — e.g. synthesizing empty or whitespace-only text, an unsupported --lang value that pico2wave silently ignores, text consisting only of characters pico cannot pronounce, or a pico2wave build missing the language voice packs writing nothing while still exiting 0.","commonSituations":"Developers hit this on minimal/container images where libttspico language data is partially installed, after passing an invalid voice like 'zh-CN' on a build with only en-US packs, or when downstream code (e.g. message preprocessing) trims the text to an empty string before synthesis.","solutions":["Check the text argument passed to Synthesize is non-empty and contains pronounceable characters before calling","Verify pico2wave has the voice/language packs for the configured --lang (run `pico2wave --lang=en-US -w /tmp/t.wav 'test'` manually and inspect the file size)","Reinstall/symlink the missing libttspico language data files (e.g. /usr/share/pico/lang/*)","Fall back to another TTS backend (espeak, edge-tts) when this error occurs"],"exampleFix":"// before\naudio, format, err := tts.Synthesize(ctx, strings.TrimSpace(userText), opts)\n// after\ntext := strings.TrimSpace(userText)\nif text == \"\" {\n    return fmt.Errorf(\"cannot synthesize empty text\")\n}\naudio, format, err := tts.Synthesize(ctx, text, opts)","handlingStrategy":"validation","validationCode":"func canSynthesize(tts *core.PicoTTS, text string) error {\n    if strings.TrimSpace(text) == \"\" {\n        return errors.New(\"empty text for TTS\")\n    }\n    return nil\n}","typeGuard":"if len(audio) == 0 || (len(audio) > 44 && string(audio[:4]) != \"RIFF\") {\n    // treat as failed synthesis, use fallback TTS\n}","tryCatchPattern":"audio, format, err := pico.Synthesize(ctx, text, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"produced empty audio file\") {\n        slog.Warn(\"pico2wave produced no audio, falling back to espeak\")\n        audio, format, err = espeak.Synthesize(ctx, text, opts)\n    }\n    if err != nil {\n        return fmt.Errorf(\"tts: %w\", err)\n    }\n}","preventionTips":["Trim and validate text before passing it to Synthesize","Verify the pico2wave language packs are installed for every --lang you configure","Add a CI/doctor check that synthesizes a test string and asserts non-empty WAV output","Keep a fallback TTS backend for environments with incomplete voice packs"],"tags":["tts","external-cli","empty-output","pico2wave"],"backgroundTag":"empty-api-response","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"}