Update TTS modal to support 20 Qwen3-TTS voices
- Fix API response format parsing (data.data[].voices -> flat array) - Update fallback voices from 6 to 20 - Bump cache version to v3 to force refresh
This commit is contained in:
parent
3d1c06c1c1
commit
15e7e4c7c7
1 changed files with 46 additions and 11 deletions
|
|
@ -11,7 +11,7 @@ async function populateVoiceDropdown(voiceSelection) {
|
|||
const cacheTimeKey = 'uncloseai_voices_cache_time';
|
||||
const cacheVersionKey = 'uncloseai_voices_cache_version';
|
||||
const cacheExpiration = 60000; // 1 minute in milliseconds
|
||||
const currentVersion = '2'; // Increment this when voice models change
|
||||
const currentVersion = '3'; // Increment this when voice models change (v3: 20 voices)
|
||||
|
||||
try {
|
||||
const cachedTime = localStorage.getItem(cacheTimeKey);
|
||||
|
|
@ -49,27 +49,62 @@ async function populateVoiceDropdown(voiceSelection) {
|
|||
|
||||
const data = await response.json();
|
||||
|
||||
// Transform API response format to frontend format
|
||||
// API returns: {data: [{id: "tts-1-qwen", voices: ["alloy", ...]}]}
|
||||
// Frontend expects: [{model: "tts-1-qwen", voice: "alloy"}, ...]
|
||||
let voices = [];
|
||||
if (data.data && Array.isArray(data.data)) {
|
||||
data.data.forEach(modelInfo => {
|
||||
if (modelInfo.voices && Array.isArray(modelInfo.voices)) {
|
||||
modelInfo.voices.forEach(voice => {
|
||||
voices.push({ model: modelInfo.id, voice: voice });
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (data.voices && Array.isArray(data.voices)) {
|
||||
// Legacy format support
|
||||
voices = data.voices;
|
||||
}
|
||||
|
||||
console.log(`Loaded ${voices.length} voices from API`);
|
||||
|
||||
// Cache the response with version
|
||||
try {
|
||||
localStorage.setItem(cacheKey, JSON.stringify(data.voices));
|
||||
localStorage.setItem(cacheKey, JSON.stringify(voices));
|
||||
localStorage.setItem(cacheTimeKey, Date.now().toString());
|
||||
localStorage.setItem(cacheVersionKey, currentVersion);
|
||||
} catch (error) {
|
||||
console.warn('Cache write failed:', error);
|
||||
}
|
||||
|
||||
renderVoiceOptions(voiceSelection, data.voices);
|
||||
return data.voices;
|
||||
renderVoiceOptions(voiceSelection, voices);
|
||||
return voices;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch voices:', error);
|
||||
// Fallback to default voices
|
||||
// Fallback to default voices (20 voices from Qwen3-TTS)
|
||||
const defaultVoices = [
|
||||
{ model: 'tts-1', voice: 'alloy' },
|
||||
{ model: 'tts-1', voice: 'echo' },
|
||||
{ model: 'tts-1', voice: 'fable' },
|
||||
{ model: 'tts-1', voice: 'onyx' },
|
||||
{ model: 'tts-1', voice: 'nova' },
|
||||
{ model: 'tts-1', voice: 'shimmer' }
|
||||
// Standard OpenAI-compatible voices
|
||||
{ model: 'tts-1-qwen', voice: 'alloy' },
|
||||
{ model: 'tts-1-qwen', voice: 'echo' },
|
||||
{ model: 'tts-1-qwen', voice: 'fable' },
|
||||
{ model: 'tts-1-qwen', voice: 'onyx' },
|
||||
{ model: 'tts-1-qwen', voice: 'nova' },
|
||||
{ model: 'tts-1-qwen', voice: 'shimmer' },
|
||||
// Extended voices
|
||||
{ model: 'tts-1-qwen', voice: 'amber' },
|
||||
{ model: 'tts-1-qwen', voice: 'breeze' },
|
||||
{ model: 'tts-1-qwen', voice: 'coral' },
|
||||
{ model: 'tts-1-qwen', voice: 'dawn' },
|
||||
{ model: 'tts-1-qwen', voice: 'ember' },
|
||||
{ model: 'tts-1-qwen', voice: 'frost' },
|
||||
{ model: 'tts-1-qwen', voice: 'glow' },
|
||||
{ model: 'tts-1-qwen', voice: 'haze' },
|
||||
{ model: 'tts-1-qwen', voice: 'ivy' },
|
||||
{ model: 'tts-1-qwen', voice: 'jade' },
|
||||
{ model: 'tts-1-qwen', voice: 'kite' },
|
||||
{ model: 'tts-1-qwen', voice: 'lark' },
|
||||
{ model: 'tts-1-qwen', voice: 'mist' },
|
||||
{ model: 'tts-1-qwen', voice: 'nectar' }
|
||||
];
|
||||
renderVoiceOptions(voiceSelection, defaultVoices);
|
||||
return defaultVoices;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue