SubtitleEdit/subtitleedit · error · InvalidOperationException

Chatterbox TTS could not use the reference voice "{Path.GetF

Error message

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}

What it means

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.

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/ChatterboxTtsCpp.cs:436

                var serverLog = SnapshotServerLog();
                var launchCommand = _serverLaunchCommand;
                var errMsg = $"Chatterbox TTS server error {(int)response.StatusCode} {response.StatusCode} - "
                    + $"Voice: {chatterboxVoice}, Text: {text}, RequestJson: {body}, "
                    + $"ResponseBody: {errorBody}, ServerLog: {serverLog}"
                    + LaunchCmdSuffix(launchCommand);
                Se.LogError(errMsg);
                Se.WriteToolsLog(errMsg);

                // The HTTP body only ever says "backend returned empty audio" - the reason the
                // backend produced none is in the server log, so name it (#13508).
                var prefix = LooksLikeCloneReferenceRejected(serverLog)
                    ? $"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`. "
                    : string.Empty;

                throw new InvalidOperationException(
                    prefix
                    + $"Chatterbox TTS synthesis failed ({(int)response.StatusCode}): {errorBody}"
                    + (string.IsNullOrEmpty(serverLog) ? string.Empty : $"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}")
                    + LaunchCmdSuffix(launchCommand));
            }

            await using var fileStream = File.Create(outputFileName);
            await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken);
            await contentStream.CopyToAsync(fileStream, cancellationToken);
        }

        return new TtsResult(outputFileName, text);
    }

    /// <summary>
    /// Builds the <c>/v1/audio/speech</c> JSON payload. Extracted so the cloning attestations are
    /// unit-testable without a running crispasr server.
    /// </summary>

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Re-import the voice from a clean source.
  2. Convert manually: `ffmpeg -i <input> -ar <CloneReferenceSampleRate> -ac 1 -c:a pcm_s16le <output>.wav` (rate shown in the message).
  3. Ensure ffmpeg is installed/on PATH so the automatic re-encode step runs.
  4. Confirm the reference is a real PCM WAV, not a renamed lossy file.

Example fix

// before: import any audio as a clone reference
// after: pre-convert at import time
ffmpeg -i voice.mp3 -ar 16000 -ac 1 -c:a pcm_s16le voice_ref.wav
Defensive patterns

Strategy: validation

Validate before calling

var refPath = chatterboxVoice.FilePath;
if (!IsPcmMonoWavAtRate(refPath, CloneReferenceSampleRate))
    return Invalid("reference must be " + CloneReferenceSampleRate + " Hz mono PCM WAV");

Try / catch

try { await chatterbox.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not use the reference voice"))
{ /* re-encode with the ffmpeg command in the message, then re-import */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/c0b889c9b85fa531. Report an issue: GitHub.