Send the picked target language to OmniVoice (CrispASR) - #13337
Merged
Conversation
The engine advertised HasLanguageParameter and offered all 646 of the
model's languages, but Speak() took the TtsLanguage and never put it on
the request - the payload was only {input, response_format, speed}. The
combo was decoration (#13273).
It has to be a payload field rather than a startup flag: SE keeps one
crispasr server for the whole session, so a launch argument could never
follow a combo change after the first line. The other cloning CrispASR
engines already send it this way.
Wiring it up needed a default first. The view model had no arm for this
engine, so it fell through to the first entry of an alphabetical list -
"Abadi", a real ISO 639-3 id the model would happily condition on - and
the pick was never persisted. So the list now leads with "Auto" (send no
field, stay language-agnostic, i.e. today's behaviour), both the main and
review windows restore the saved pick, and OmniVoiceCrispAsrLanguage
stores it.
Values that are not the model's own ids are dropped rather than sent.
crispasr falls back to language-agnostic on those anyway, but a locale
code like "de-DE" or a leftover language object from another engine has
no business on the wire.
Note the ids are ISO 639-3 individual languages, so there is no "ar" -
Arabic is arb/arz/ary and ~20 more. That is the model's vocabulary, not a
gap; asserted in tests so it does not get "fixed" later.
Honouring the field per request needs a crispasr build newer than the
pinned v0.8.25, where the adapter applies the language only at startup.
Sending it there is harmless and it goes live on the pin bump - the same
bump CosyVoice3 cross-lingual (#13272) is waiting on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the SE half of #13273.
The engine advertised
HasLanguageParameterand offered all 646 of the model's languages, butSpeak()took theTtsLanguageand never put it on the request — the payload was only{input, response_format, speed}. As reported, the menu was decoration.It has to be a payload field rather than a startup flag: SE keeps one crispasr server for the whole session, so a launch argument could never follow a combo change after the first line. The other cloning CrispASR engines already send it this way.
The default had to be fixed first
Adding the field alone would have made things worse. The view model had no arm for this engine, so it fell through to the first entry of an alphabetical list — "Abadi" (
kbt), a real ISO 639-3 id the model would happily condition on — and the pick was never persisted.So
OmniVoiceLanguages.Allnow leads with "Auto" (empty code → no field → language-agnostic, i.e. the pre-existing behaviour), with the 646 generated entries kept in a privateCatalogso they can still be regenerated wholesale. Both the main TTS window and the review window restore the saved pick — they had drifted apart, review already defaulting to English while the main window defaulted to Abadi — and a newOmniVoiceCrispAsrLanguagesetting stores it.Two things beyond the report
ResolveLanguageArg(null)falls back to the saved pick. The cast dialog's voice-test button and every cross-engine cast row passnullon purpose ("engines fall back to their own saved defaults") — the same hole CosyVoice3 had in CosyVoice-TTS - The target language is not assigned during cloning. #13272.de-DEor a leftover language object from another engine has no business on the wire.Note on the ids
They are ISO 639-3 individual languages, so there is no
ar— Arabic isarb(Standard),arz(Egyptian),ary(Moroccan) and ~20 more. That is the model's vocabulary, not a gap in the list; asserted in tests so it does not get "fixed" later by inventing an id the model has never seen.Requires a CrispASR bump to take effect
On the pinned v0.8.25 the CLI adapter applies the language only at startup, so the field is parsed and ignored on every request. The fixes — per-request apply, the session C-ABI arm, and running
_resolve_language()on the id — are on CrispASRmainand in no release yet.Sending it on v0.8.25 is harmless (SE only ever puts the model's own ids on the wire) and it goes live the moment
CrispAsrDownloadServiceis bumped past v0.8.25 — the same bump CosyVoice3 cross-lingual (#13272) is waiting on. Flagged in the class docs so nobody debugs it as broken in the meantime.Not fixed here
The other half of #13273 — the reference accent — is a separate, structural problem. OmniVoice has no cross-lingual mode: the reference transcript sits before the reference audio in a single token stream, so it cannot be dropped the way CosyVoice3 does. Cloning an English speaker onto German text may still sound English however the tag is set. Thanks to @CrispStrobe for the detailed backend analysis and for not overclaiming that part.
Testing
Full UI suite: 1599 passed, 0 failed. New coverage for the Auto-leads invariant, the null/Auto/unknown resolution paths, and the absent-
arcase.🤖 Generated with Claude Code