diff --git a/src/lib/shared/tts-provider-catalog.ts b/src/lib/shared/tts-provider-catalog.ts index 86c1466..cb30fc2 100644 --- a/src/lib/shared/tts-provider-catalog.ts +++ b/src/lib/shared/tts-provider-catalog.ts @@ -232,7 +232,9 @@ export function getDefaultVoices(provider: TtsProviderId, model: string): string } if (provider === 'custom-openai') { - return isKokoroModel(model) ? [...KOKORO_DEFAULT_VOICES] : [...CUSTOM_OPENAI_DEFAULT_VOICES]; + // Kokoro models get the kokoro voice set; any other OpenAI-compatible model + // falls back to the canonical OpenAI six, which such servers generally accept. + return isKokoroModel(model) ? [...KOKORO_DEFAULT_VOICES] : [...OPENAI_DEFAULT_VOICES]; } if (provider === 'replicate') { diff --git a/tests/unit/tts-provider-catalog.vitest.spec.ts b/tests/unit/tts-provider-catalog.vitest.spec.ts index 02e72af..3453cc1 100644 --- a/tests/unit/tts-provider-catalog.vitest.spec.ts +++ b/tests/unit/tts-provider-catalog.vitest.spec.ts @@ -41,6 +41,8 @@ describe('tts provider catalog', () => { test('resolves default voices and instruction support unchanged', () => { expect(getDefaultVoices('openai', 'gpt-4o-mini-tts')).toContain('sage'); expect(getDefaultVoices('custom-openai', 'kokoro')).toContain('af_sarah'); + // Non-kokoro custom-openai models fall back to the canonical OpenAI six. + expect(getDefaultVoices('custom-openai', 'supertonic-3')).toEqual(['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer']); expect(getDefaultVoices('deepinfra', 'ResembleAI/chatterbox')).toEqual(['None']); expect(getDefaultVoices('deepinfra', 'Zyphra/Zonos-v0.1-transformer')).toEqual(['random']); expect(supportsTtsInstructions('gpt-4o-mini-tts')).toBe(true);