diff --git a/webui/native/dist/index.html b/webui/native/dist/index.html index 572c920e..affaa4fc 100644 --- a/webui/native/dist/index.html +++ b/webui/native/dist/index.html @@ -5,7 +5,7 @@ - + @@ -13,20 +13,20 @@
diff --git a/webui/native/src/lib/catalog.ts b/webui/native/src/lib/catalog.ts index 393dd795..deb21996 100644 --- a/webui/native/src/lib/catalog.ts +++ b/webui/native/src/lib/catalog.ts @@ -18,7 +18,7 @@ interface PackageSpec { family: string; packages?: Array>; options?: { - request?: Array<{ name: string }>; + request?: Array<{ name: string; required?: boolean }>; }; ui?: { builtin_voices?: string[]; @@ -179,6 +179,9 @@ export const catalog = (rawCatalog.models as CatalogEntry[]).flatMap((entry) => install_packages: choices, path: installPackage?.path || entry.path, request_options: spec?.options?.request?.map((option) => option.name), + required_request_options: spec?.options?.request + ?.filter((option) => option.required === true) + .map((option) => option.name), builtin_voices: spec?.ui?.builtin_voices, default_voice: spec?.ui?.default_voice }]; diff --git a/webui/native/src/lib/types.ts b/webui/native/src/lib/types.ts index 11d8a3c0..4e58067e 100644 --- a/webui/native/src/lib/types.ts +++ b/webui/native/src/lib/types.ts @@ -25,6 +25,7 @@ export interface CatalogEntry { load_options?: StringMap; session_options?: StringMap; request_options?: string[]; + required_request_options?: string[]; builtin_voices?: string[]; default_voice?: string; } diff --git a/webui/native/src/routes/+page.svelte b/webui/native/src/routes/+page.svelte index 46f076a5..a7f0cafd 100644 --- a/webui/native/src/routes/+page.svelte +++ b/webui/native/src/routes/+page.svelte @@ -258,7 +258,9 @@ !selected?.id.includes('custom'); $: referenceVoiceRequired = !quickStartVoice && ( (['clon', 'vc', 'svc'].includes(selected?.task) && selected?.family !== 'rvc') || isQwenBase); - $: referenceTextRequired = Boolean(voiceFile) && isQwenBase; + $: lyricsRequired = requiresRequestOption(selected, 'lyrics'); + $: referenceTextRequired = requiresRequestOption(selected, 'reference_text') || + (Boolean(voiceFile) && isQwenBase); $: quickStartVoices = Object.entries(demoVoiceSources) .filter(([, source]) => bundledVoices.includes(source)) .map(([voice]) => voice); @@ -494,6 +496,10 @@ return entry.request_options === undefined || entry.request_options.includes(option); } + function requiresRequestOption(entry: CatalogEntry, option: string) { + return entry.required_request_options?.includes(option) === true; + } + function packageVersionLabel(size: ModelPackageSize | undefined, translate = tr) { if (!size?.installed) return ''; if (size.version_state === 'up_to_date') return translate('models.upToDate'); @@ -1158,7 +1164,11 @@ throw new StatusWarning(`${selected.display_name_en || selected.display_name} requires a reference voice.`); } if (referenceTextRequired && !referenceText.trim()) { - throw new StatusWarning('Qwen3-TTS Base voice cloning requires a reference transcript. Choose a matching .txt file or enter the transcript.'); + const prefix = isQwenBase ? 'Qwen3-TTS Base voice cloning' : (selected.display_name_en || selected.display_name); + throw new StatusWarning(`${prefix} requires a reference transcript. Choose a matching .txt file or enter the transcript.`); + } + if (lyricsRequired && !lyrics.trim()) { + throw new StatusWarning(`${selected.display_name_en || selected.display_name} requires lyrics.`); } await ensureLoaded(); const options = requestOptions(); @@ -1727,8 +1737,9 @@ {/if} {#if selected.task === 'gen'} - - + + {/if} {#if selected.task === 'asr'}