Fixed option ui binidngs.

This commit is contained in:
2025-04-05 11:29:30 +00:00
parent b50f60e195
commit 115704f89d
6 changed files with 355 additions and 301 deletions
+79 -111
View File
@@ -89,6 +89,12 @@ export class KokoroHandler extends TTSHandler {
return true;
}
// Ensure we have at least default voices ready
if (!this.voices || this.voices.length === 0) {
console.log('Kokoro TTS: No voices set, initializing with defaults');
this.voices = this.getDefaultVoices();
}
// Set loading flag
this.loading = true;
this.isReady = false; // Explicitly set to false during initialization
@@ -169,10 +175,11 @@ export class KokoroHandler extends TTSHandler {
} else {
console.warn('Kokoro TTS: No voices received during initialization or invalid voices data');
if (data.success) {
// If initialization was successful but no voices were received,
// use default voices
this.voices = this.getDefaultVoices();
console.log('Kokoro TTS: Using default voices as fallback');
// Even though we already set the default voices, check and update if needed
if (!this.voices || this.voices.length === 0) {
this.voices = this.getDefaultVoices();
console.log('Kokoro TTS: Using default voices as fallback');
}
}
}
@@ -182,7 +189,7 @@ export class KokoroHandler extends TTSHandler {
console.log('Kokoro TTS: Voice set up from preferences during initialization');
}).catch(error => {
console.error('Kokoro TTS: Error setting up voice from preferences during initialization:',
error ? (error.message || JSON.stringify(error)) : 'Unknown error');
error ? (error.message || error) : 'Unknown error');
});
}
@@ -191,30 +198,17 @@ export class KokoroHandler extends TTSHandler {
}
};
// Add the message listener
// Add the message handler
window.addEventListener('message', messageHandler);
// Send initialization message to iframe
if (this.iframe.contentWindow) {
console.log('Kokoro TTS: Sending init message to iframe');
setTimeout(() => {
this.iframe.contentWindow.postMessage({
type: 'kokoro-init'
}, '*');
}, 500); // Add a small delay to ensure iframe is ready
} else {
console.error('Kokoro TTS: Cannot access iframe content window');
this.loading = false;
this.isReady = false;
this.available = false;
resolve(false);
}
// Initial progress update
handleProgress(0.1, 'Starting Kokoro initialization');
});
} catch (error) {
console.error('Kokoro TTS: Error initializing:', error ? (error.message || JSON.stringify(error)) : 'Unknown error');
console.error('Kokoro TTS: Error during initialization:', error);
this.loading = false;
this.available = false;
this.isReady = false;
this.available = false;
return false;
}
}
@@ -224,91 +218,56 @@ export class KokoroHandler extends TTSHandler {
* @param {MessageEvent} event - Message event
*/
handleIframeMessage(event) {
// Ignore messages from other sources
// Only process messages from our iframe
if (!this.iframe || event.source !== this.iframe.contentWindow) {
return;
}
const data = event.data;
console.log('Kokoro TTS: Received message from iframe:', JSON.stringify(data));
console.log('Kokoro TTS: Received message from iframe:', data.type);
switch (data.type) {
case 'kokoro-ready':
console.log('Kokoro TTS: Received ready message with success =', data.success);
case 'kokoro-log':
console.log(`Kokoro Loader: ${data.message}`);
break;
// Store voices if provided
case 'kokoro-ready':
console.log('Kokoro TTS: Received ready message from iframe. Success:', data.success, 'Voices:', data.voices ? data.voices.length : 0);
// Store availability
this.loading = false;
this.available = data.success;
this.isReady = data.success; // Important to set this for the base handler
// Store voices
if (data.success && data.voices && Array.isArray(data.voices)) {
console.log(`Kokoro TTS: Received ${data.voices.length} voices from Kokoro iframe`);
console.log(`Kokoro TTS: Storing ${data.voices.length} voices from iframe`);
this.voices = data.voices;
// Set availability and ready flags
this.available = true;
this.loading = false;
this.isReady = true;
// Set up voice from preferences after voices are loaded
this.setupVoiceFromPreferences().then(() => {
console.log('Kokoro TTS: Voice set up from preferences after receiving voices');
// Notify TTS Factory that we're ready now
document.dispatchEvent(new CustomEvent('kokoro:ready', {
detail: { success: true }
}));
}).catch(error => {
console.error('Kokoro TTS: Error setting up voice from preferences after receiving voices:',
error ? (error.message || JSON.stringify(error)) : 'Unknown error');
// Still notify as ready since we have voices, even if preference setup failed
document.dispatchEvent(new CustomEvent('kokoro:ready', {
detail: { success: true }
}));
});
// Notify about voices being updated
document.dispatchEvent(new CustomEvent('kokoro:voices-updated', {
detail: { voices: this.voices }
}));
} else {
console.warn('Kokoro TTS: No voices received from iframe or invalid voices data');
// Even with no voices, mark as ready if success is true
if (data.success) {
this.voices = this.getDefaultVoices();
this.available = true;
this.loading = false;
this.isReady = true;
console.log('Kokoro TTS: Using default voices as fallback');
// Notify TTS Factory that we're ready
document.dispatchEvent(new CustomEvent('kokoro:ready', {
detail: { success: true }
}));
// Notify about voices being available
document.dispatchEvent(new CustomEvent('kokoro:voices-updated', {
detail: { voices: this.voices }
}));
} else {
this.available = false;
this.loading = false;
this.isReady = false;
console.error('Kokoro TTS: Initialization failed:', data.error || 'Unknown error');
// Notify TTS Factory about failure
document.dispatchEvent(new CustomEvent('kokoro:ready', {
detail: { success: false, error: data.error || 'Unknown error' }
}));
}
} else if (data.success) {
// If success but no voices, use defaults
console.warn('Kokoro TTS: No voices received from iframe, using defaults');
this.voices = this.getDefaultVoices();
}
// Set up voice from preferences if ready
if (this.available) {
this.setupVoiceFromPreferences().then(() => {
console.log('Kokoro TTS: Voice set up from preferences');
});
}
// Dispatch ready event
this.dispatchEvent('tts:ready', { success: data.success });
break;
case 'kokoro-generated':
// Handle generated speech
const pendingGeneration = this.pendingGenerations.get(data.id);
if (pendingGeneration) {
// Handle generated speech
if (data.id && this.pendingGenerations.has(data.id)) {
const { resolve, reject } = this.pendingGenerations.get(data.id);
this.pendingGenerations.delete(data.id);
if (data.success) {
// Create audio element from the result
if (data.success && data.result) {
// Create an audio element from the result
try {
// Create a blob from the buffer
const blob = new Blob([data.result.buffer], { type: 'audio/wav' });
@@ -323,26 +282,18 @@ export class KokoroHandler extends TTSHandler {
});
};
pendingGeneration.resolve({ audio, play, blob });
resolve({ audio, play, blob });
} catch (error) {
console.error('Error processing Kokoro audio:', error);
pendingGeneration.reject(error);
reject(error);
}
} else {
pendingGeneration.reject(new Error(data.error || 'Unknown error'));
console.error('Kokoro TTS: Invalid speech generation result');
reject(new Error(data.error || 'Unknown error generating speech'));
}
}
break;
case 'kokoro-log':
// Log messages from the iframe
if (data.logType === 'error') {
console.error(`Kokoro iframe: ${data.message}`);
} else {
console.log(`Kokoro iframe: ${data.message}`);
}
break;
case 'kokoro-progress':
// Progress updates are handled during initialization
break;
@@ -440,7 +391,7 @@ export class KokoroHandler extends TTSHandler {
}
} catch (error) {
// Log detailed error information
console.error('Kokoro TTS: Error setting up voice from preferences:', error ? error.message || JSON.stringify(error) : 'Unknown error');
console.error('Kokoro TTS: Error setting up voice from preferences:', error ? error.message || error : 'Unknown error');
// Default to first voice if available
if (this.voices && this.voices.length > 0) {
@@ -505,9 +456,12 @@ export class KokoroHandler extends TTSHandler {
/**
* Get available voices
* @returns {Array} - Array of available voices
* @returns {Array} - Array of voice objects
*/
getVoices() {
if (!this.voices || this.voices.length === 0) {
return this.getDefaultVoices();
}
return this.voices;
}
@@ -710,11 +664,14 @@ export class KokoroHandler extends TTSHandler {
if (this.currentVoice && this.currentVoice.id) {
voiceId = this.currentVoice.id;
} else if (this.voices && this.voices.length > 0) {
// If currentVoice is not set but we have voices, use the first one
voiceId = this.voices[0].id;
// Default to first voice if none selected
this.currentVoice = this.voices[0];
voiceId = this.currentVoice.id;
console.log(`Kokoro TTS: No voice set, defaulting to ${voiceId}`);
}
console.log(`Kokoro TTS: Generating speech with voice ${voiceId}`);
return new Promise((resolve, reject) => {
// Generate unique ID for this request
const id = `gen-${++this.generationCounter}`;
@@ -787,11 +744,22 @@ export class KokoroHandler extends TTSHandler {
}
/**
* Get default voices
* @returns {Array} - Array of default voices
* @private
* Get default voices for current locale
* @returns {Array} Default voices
*/
getDefaultVoices() {
// Check if localization module is available
const localization = this.getModule('localization');
let locale = 'en-us'; // Default fallback
if (localization) {
locale = localization.getLocale();
console.log(`Kokoro TTS: Getting default voices for locale: ${locale}`);
} else {
console.log('Kokoro TTS: Localization module not available, using default locale: en-us');
}
// Use the actual voices defined in the Kokoro loader
return [
// American Female voices
{ id: 'af_heart', name: 'Heart', lang: 'en-US', gender: 'female' },