{"record":{"id":"c0b889c9b85fa531","repo":"SubtitleEdit/subtitleedit","slug":"chatterbox-tts-could-not-use-the-reference-voice","errorCode":null,"errorMessage":"Chatterbox TTS could not use the reference voice \"{Path.GetFileName(chatterboxVoice.FilePath)}\" for cloning: CrispASR needs a {CloneReferenceSampleRate / 1000} kHz mono WAV and re-encoding this one did not produce that. Re-import the voice, or convert it yourself with `ffmpeg -i <input> -ar {CloneReferenceSampleRate} -ac 1 -c:a pcm_s16le <output>.wav`. Chatterbox TTS synthesis failed ({(int)response.StatusCode}): {errorBody}","messagePattern":"Chatterbox TTS could not use the reference voice \"(.+?)\" for cloning: CrispASR needs a (.+?) kHz mono WAV and re-encoding this one did not produce that\\. Re-import the voice, or convert it yourself with `ffmpeg -i <input> -ar (.+?) -ac 1 -c:a pcm_s16le <output>\\.wav`\\. Chatterbox TTS synthesis failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/ChatterboxTtsCpp.cs","lineNumber":436,"sourceCode":"                var serverLog = SnapshotServerLog();\n                var launchCommand = _serverLaunchCommand;\n                var errMsg = $\"Chatterbox TTS server error {(int)response.StatusCode} {response.StatusCode} - \"\n                    + $\"Voice: {chatterboxVoice}, Text: {text}, RequestJson: {body}, \"\n                    + $\"ResponseBody: {errorBody}, ServerLog: {serverLog}\"\n                    + LaunchCmdSuffix(launchCommand);\n                Se.LogError(errMsg);\n                Se.WriteToolsLog(errMsg);\n\n                // The HTTP body only ever says \"backend returned empty audio\" - the reason the\n                // backend produced none is in the server log, so name it (#13508).\n                var prefix = LooksLikeCloneReferenceRejected(serverLog)\n                    ? $\"Chatterbox TTS could not use the reference voice \\\"{Path.GetFileName(chatterboxVoice.FilePath)}\\\" for cloning: \"\n                      + $\"CrispASR needs a {CloneReferenceSampleRate / 1000} kHz mono WAV and re-encoding this one did not produce that. \"\n                      + \"Re-import the voice, or convert it yourself with \"\n                      + $\"`ffmpeg -i <input> -ar {CloneReferenceSampleRate} -ac 1 -c:a pcm_s16le <output>.wav`. \"\n                    : string.Empty;\n\n                throw new InvalidOperationException(\n                    prefix\n                    + $\"Chatterbox TTS synthesis failed ({(int)response.StatusCode}): {errorBody}\"\n                    + (string.IsNullOrEmpty(serverLog) ? string.Empty : $\"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}\")\n                    + LaunchCmdSuffix(launchCommand));\n            }\n\n            await using var fileStream = File.Create(outputFileName);\n            await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken);\n            await contentStream.CopyToAsync(fileStream, cancellationToken);\n        }\n\n        return new TtsResult(outputFileName, text);\n    }\n\n    /// <summary>\n    /// Builds the <c>/v1/audio/speech</c> JSON payload. Extracted so the cloning attestations are\n    /// unit-testable without a running crispasr server.\n    /// </summary>","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/ChatterboxTtsCpp.cs#L418-L454","documentation":"HTTP non-success from /v1/audio/speech AND LooksLikeCloneReferenceRejected(serverLog) matched. The reference voice WAV must be {CloneReferenceSampleRate/1000} kHz mono; the engine's ffmpeg re-encode did not produce that, so CrispASR rejected the clone. The message embeds the exact ffmpeg command to convert manually.","triggerScenarios":"chatterboxVoice.FilePath is a WAV of wrong sample rate, channel count, or codec; the auto re-encode (EnsureCloneReferenceIsUsable) failed to produce the required format; ffmpeg missing so re-encode never ran; backend returns non-2xx with a 'backend returned empty audio' style body and the server log shows the reference was rejected.","commonSituations":"Re-imported a stereo or 48 kHz WAV as a Chatterbox clone reference; ffmpeg not on PATH; reference WAV truncated; user imported an mp3 renamed to .wav.","solutions":["Re-import the voice from a clean source.","Convert manually: `ffmpeg -i <input> -ar <CloneReferenceSampleRate> -ac 1 -c:a pcm_s16le <output>.wav` (rate shown in the message).","Ensure ffmpeg is installed/on PATH so the automatic re-encode step runs.","Confirm the reference is a real PCM WAV, not a renamed lossy file."],"exampleFix":"// before: import any audio as a clone reference\n// after: pre-convert at import time\nffmpeg -i voice.mp3 -ar 16000 -ac 1 -c:a pcm_s16le voice_ref.wav","handlingStrategy":"validation","validationCode":"var refPath = chatterboxVoice.FilePath;\nif (!IsPcmMonoWavAtRate(refPath, CloneReferenceSampleRate))\n    return Invalid(\"reference must be \" + CloneReferenceSampleRate + \" Hz mono PCM WAV\");","typeGuard":null,"tryCatchPattern":"try { await chatterbox.Speak(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"could not use the reference voice\"))\n{ /* re-encode with the ffmpeg command in the message, then re-import */ }","preventionTips":["Pre-convert clone references to the required sample rate / mono PCM WAV at import time.","Ensure ffmpeg is on PATH so the automatic re-encode runs.","Reject non-PCM or stereo files at import rather than at synthesis."],"tags":["chatterbox","crispasr","voice-cloning","ffmpeg","text-to-speech"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}