Fix Kokoro TTS integration issues: Remove API key requirement and ensure system-specific options display correctly
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* TTSHandlerModule Base Class
|
||||
* Base class for all TTS handler modules
|
||||
*/
|
||||
import { BaseModule } from './base-module.js';
|
||||
|
||||
export class TTSHandlerModule extends BaseModule {
|
||||
constructor(id, name) {
|
||||
super(id, name);
|
||||
|
||||
// Common TTS handler properties
|
||||
this.isReady = false;
|
||||
this.isSpeaking = false;
|
||||
this.currentUtterance = null;
|
||||
this.voices = [];
|
||||
this.currentVoice = null;
|
||||
this.defaultVoice = null;
|
||||
this.speechRate = 1.0;
|
||||
this.pitch = 1.0;
|
||||
this.volume = 1.0;
|
||||
|
||||
// Common dependencies for TTS handlers
|
||||
this.dependencies = ['persistence-manager', 'localization'];
|
||||
|
||||
// Bind common methods
|
||||
this.bindMethods([
|
||||
'speak',
|
||||
'stop',
|
||||
'getVoices',
|
||||
'setVoice',
|
||||
'configure',
|
||||
'generateSpeech'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handler ID
|
||||
* @returns {string} - The handler ID
|
||||
*/
|
||||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TTS handler
|
||||
* @returns {Promise<boolean>} - Resolves with success status
|
||||
*/
|
||||
async initialize() {
|
||||
try {
|
||||
this.reportProgress(20, `Initializing ${this.name}`);
|
||||
|
||||
// Check for required dependencies
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (!persistenceManager) {
|
||||
console.error(`${this.name}: Persistence Manager dependency not found`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load preferences
|
||||
this.loadPreferences(persistenceManager);
|
||||
|
||||
// Set up event listeners
|
||||
this.setupEventListeners();
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`${this.name}: Initialization error`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load preferences from persistence manager
|
||||
* @param {Object} persistenceManager - The persistence manager module
|
||||
*/
|
||||
loadPreferences(persistenceManager) {
|
||||
// Load common preferences
|
||||
this.speechRate = persistenceManager.getPreference('tts', 'rate', 1.0);
|
||||
this.pitch = persistenceManager.getPreference('tts', 'pitch', 1.0);
|
||||
this.volume = persistenceManager.getPreference('tts', 'volume', 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up common event listeners
|
||||
*/
|
||||
setupEventListeners() {
|
||||
// To be implemented by subclasses if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is ready
|
||||
* @returns {boolean} - Whether the handler is ready
|
||||
*/
|
||||
isHandlerReady() {
|
||||
return this.isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is currently speaking
|
||||
* @returns {boolean} - Whether the handler is speaking
|
||||
*/
|
||||
isSpeakingNow() {
|
||||
return this.isSpeaking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available voices
|
||||
* @returns {Promise<Array>} - Resolves with array of voice objects
|
||||
*/
|
||||
async getVoices() {
|
||||
return this.voices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the voice to use
|
||||
* @param {string} voiceId - Voice identifier
|
||||
* @returns {boolean} - Success status
|
||||
*/
|
||||
setVoice(voiceId) {
|
||||
// To be implemented by subclasses
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure TTS parameters
|
||||
* @param {Object} options - Configuration options
|
||||
* @returns {boolean} - Success status
|
||||
*/
|
||||
configure(options) {
|
||||
let changed = false;
|
||||
|
||||
if (options.voice && options.voice !== this.currentVoice) {
|
||||
this.setVoice(options.voice);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (options.speed && options.speed !== this.speechRate) {
|
||||
this.speechRate = options.speed;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (options.pitch && options.pitch !== this.pitch) {
|
||||
this.pitch = options.pitch;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (options.volume && options.volume !== this.volume) {
|
||||
this.volume = options.volume;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Save preferences if changed
|
||||
if (changed) {
|
||||
const persistenceManager = this.getModule('persistence-manager');
|
||||
if (persistenceManager) {
|
||||
persistenceManager.updatePreference('tts', 'rate', this.speechRate);
|
||||
persistenceManager.updatePreference('tts', 'pitch', this.pitch);
|
||||
persistenceManager.updatePreference('tts', 'volume', this.volume);
|
||||
if (this.currentVoice) {
|
||||
persistenceManager.updatePreference('tts', `${this.id}_voice`, this.currentVoice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Speak text
|
||||
* @param {string} text - Text to speak
|
||||
* @param {Function} callback - Callback for when speech completes
|
||||
* @returns {boolean} - Success status
|
||||
*/
|
||||
speak(text, callback) {
|
||||
// To be implemented by subclasses
|
||||
console.error(`${this.name}: speak() method not implemented`);
|
||||
if (callback) {
|
||||
setTimeout(() => callback({ success: false, reason: 'not_implemented' }), 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop speaking
|
||||
* @returns {boolean} - Success status
|
||||
*/
|
||||
stop() {
|
||||
// To be implemented by subclasses
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate speech audio data
|
||||
* @param {string} text - Text to generate speech for
|
||||
* @param {Object} options - Generation options
|
||||
* @returns {Promise<Object>} - Resolves with audio data
|
||||
*/
|
||||
async generateSpeech(text, options = {}) {
|
||||
// To be implemented by subclasses
|
||||
return { success: false, reason: 'not_implemented' };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user