SubtitleEdit/subtitleedit · error · InvalidOperationException

IndexTTS (CrispASR) requires a reference voice WAV. Import o

Error message

IndexTTS (CrispASR) requires a reference voice WAV. Import one via the voice settings, then pick it in the voice combo. Reference WAV should be 24 kHz mono (3-10 s of clean speech).

What it means

InvalidOperationException from IndexTtsCrispAsr.Speak when the IndexTtsVoice is the correct type but its `FilePath` is null or empty. IndexTTS is a voice-cloning engine: it needs a reference WAV baked into the server at startup via `--voice`, so an empty path is unrecoverable. The message tells the user to import a reference WAV and gives the format spec (24 kHz mono, 3–10 s).

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/IndexTtsCrispAsr.cs:357

        GetVoices(language);

    public async Task<TtsResult> Speak(
        string text,
        string outputFolder,
        Voice voice,
        TtsLanguage? language,
        string? region,
        string? model,
        CancellationToken cancellationToken)
    {
        if (voice.EngineVoice is not IndexTtsVoice indexVoice)
        {
            throw new ArgumentException("Voice is not an IndexTtsVoice");
        }

        if (string.IsNullOrEmpty(indexVoice.FilePath))
        {
            throw new InvalidOperationException(
                "IndexTTS (CrispASR) requires a reference voice WAV. "
                + "Import one via the voice settings, then pick it in the voice combo. "
                + "Reference WAV should be 24 kHz mono (3-10 s of clean speech).");
        }

        var modelKey = ResolveModelKey(model);
        await EnsureServerRunningAsync(modelKey, indexVoice.FilePath, cancellationToken);

        var outputFileName = Path.Combine(TtsOutputFolder.Resolve(outputFolder, GetSetFolder), Guid.NewGuid() + ".wav");
        var inputText = text;

        // OpenAI-compatible /v1/audio/speech payload. CrispASR's indextts backend uses:
        //   - `input`             — the text to synthesise
        //   - `response_format`   — "wav"
        //   - `voice`             — absolute WAV path or filename in --voice-dir
        //   - `speed`             — server-side linear resample of the synth output (0.25-4.0).
        //                           Default is 1.0; the user can override in the engine settings.
        // The server-mode indextts backend ignores the request `voice` field, so we still

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Open the voice settings and import a clean 3–10 s 24 kHz mono WAV as the reference.
  2. Re-select that voice in the IndexTTS combo so the entry is bound to the file.
  3. If the WAV was moved, re-import from its new location.
  4. Validate the WAV format (24 kHz mono PCM) — wrong format can also cause downstream synth failures.

Example fix

// before
var voice = new Voice { EngineVoice = new IndexTtsVoice { FilePath = "" } };

// after
var voice = new Voice { EngineVoice = new IndexTtsVoice { FilePath = @"C:\Voices\ref.wav" } };
Defensive patterns

Strategy: validation

Validate before calling

if (voice.EngineVoice is IndexTtsVoice iv && string.IsNullOrEmpty(iv.FilePath))
{
    WarnUser("Import a reference WAV (24 kHz mono, 3-10 s) first.");
    return;
}

Try / catch

try { await indexEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("requires a reference voice WAV"))
{
    PromptImportReferenceWav();
}

Prevention

When it happens

Trigger: Selecting an IndexTTS voice entry that was created before a reference WAV was attached; deleting/moving the referenced WAV after import; an import flow that registered the voice name but left FilePath blank.

Common situations: User picked the engine before importing a reference clip; the imported file was on a removable drive now detached; voice list loaded from an older settings format that didn't persist FilePath.

Related errors


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