SubtitleEdit/subtitleedit · error · InvalidOperationException
MOSS-TTS (CrispASR) requires a reference voice WAV. Import o
Error message
MOSS-TTS (CrispASR) requires a reference voice WAV. Import one via the voice settings, then pick it in the voice combo. Reference WAV should be mono (3-10 s of clean speech); an adjacent .txt file with the spoken transcription is optional but improves cloning quality.
What it means
InvalidOperationException from MossTtsCrispAsr.Speak when the MossTtsVoice is the correct type but its `FilePath` is null or empty. MOSS-TTS is a cloning engine that bakes the reference WAV into the server at startup via `--voice` (and an optional adjacent `.txt` for ref-text). An empty path is unrecoverable; the message directs the user to import a reference WAV (mono, 3–10 s) and notes the optional transcription `.txt` improves cloning.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs:434
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 MossTtsVoice mossVoice)
{
throw new ArgumentException("Voice is not a MossTtsVoice");
}
if (string.IsNullOrEmpty(mossVoice.FilePath))
{
throw new InvalidOperationException(
"MOSS-TTS (CrispASR) requires a reference voice WAV. "
+ "Import one via the voice settings, then pick it in the voice combo. "
+ "Reference WAV should be mono (3-10 s of clean speech); an adjacent .txt file "
+ "with the spoken transcription is optional but improves cloning quality.");
}
var refText = TryReadRefText(mossVoice.FilePath);
var modelKey = ResolveModelKey(model);
var languageArg = MossTtsLanguages.ResolveLanguageArg(language);
await EnsureServerRunningAsync(modelKey, mossVoice.FilePath, refText, languageArg, cancellationToken);
var outputFileName = Path.Combine(TtsOutputFolder.Resolve(outputFolder, GetSetFolder), Guid.NewGuid() + ".wav");
var speed = Math.Clamp(Se.Settings.Video.TextToSpeech.MossTtsCrispAsrSpeed, 0.25, 4.0);
var payload = BuildSpeakPayload(text, speed);
var body = JsonSerializer.Serialize(payload);
using var content = new StringContent(body, Encoding.UTF8, "application/json");View on GitHub (pinned to 17a9f07487)
Solutions
- Open voice settings and import a clean 3–10 s mono WAV as the MOSS-TTS reference.
- Optionally place a `.txt` with the transcription next to the WAV (TryReadRefText picks it up).
- Re-select the voice in the MOSS-TTS combo so the entry is bound to the file.
- If the WAV moved, re-import from its new location.
Example fix
// before
var voice = new Voice { EngineVoice = new MossTtsVoice { FilePath = "" } };
// after
var voice = new Voice { EngineVoice = new MossTtsVoice { FilePath = @"C:\Voices\ref.wav" } }; Defensive patterns
Strategy: validation
Validate before calling
if (voice.EngineVoice is MossTtsVoice mv && string.IsNullOrEmpty(mv.FilePath))
{
PromptImportReferenceWav();
return;
} Try / catch
try { await mossEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("requires a reference voice WAV"))
{
PromptImportReferenceWav();
} Prevention
- Disable Speak until the selected MOSS-TTS voice has a non-empty FilePath.
- Validate the WAV exists before each batch (files can be moved/deleted).
- On import, verify mono PCM format and reject otherwise.
- Optionally provide an adjacent `.txt` transcription for better cloning.
When it happens
Trigger: Selecting a MOSS-TTS voice entry created before a reference WAV was attached; deleting/moving the referenced WAV after import; a settings migration that lost FilePath.
Common situations: User picked the engine before importing a clip; reference file on a detached removable drive; older settings format that didn't persist FilePath.
Related errors
- IndexTTS (CrispASR) requires a reference voice WAV. Import o
- F5-TTS (CrispASR) requires a reference voice WAV. Import one
- Voice is not an IndexTtsVoice
- MOSS-TTS (CrispASR) — the crispasr server crashed during syn
- MOSS-TTS (CrispASR) request failed — the connection to the c
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/001751c8d001c812.
Report an issue: GitHub.