WellNuo/services/sherpaTTS.ts

118 lines
2.6 KiB
TypeScript

/**
* Sherpa TTS Service - STUB for Expo Go development
* The real implementation requires native modules which don't work in Expo Go
* This stub returns "not available" so the app falls back to expo-speech
*/
// Available Piper neural voices - kept for type compatibility
export interface PiperVoice {
id: string;
name: string;
description: string;
modelDir: string;
onnxFile: string;
gender: 'male' | 'female';
accent: string;
}
export const AVAILABLE_VOICES: PiperVoice[] = [
{
id: 'lessac',
name: 'Lessac',
description: 'American Female (Natural)',
modelDir: 'vits-piper-en_US-lessac-medium',
onnxFile: 'en_US-lessac-medium.onnx',
gender: 'female',
accent: 'US',
},
];
interface SherpaTTSState {
initialized: boolean;
initializing: boolean;
error: string | null;
}
let currentState: SherpaTTSState = {
initialized: false,
initializing: false,
error: 'Sherpa TTS disabled for Expo Go development',
};
// State listeners
const stateListeners: ((state: SherpaTTSState) => void)[] = [];
function notifyListeners() {
stateListeners.forEach(listener => listener({ ...currentState }));
}
export function addStateListener(listener: (state: SherpaTTSState) => void) {
stateListeners.push(listener);
listener({ ...currentState });
return () => {
const index = stateListeners.indexOf(listener);
if (index >= 0) stateListeners.splice(index, 1);
};
}
export function getState(): SherpaTTSState {
return { ...currentState };
}
// Stub implementations - always return false/unavailable
export async function initializeSherpaTTS(): Promise<boolean> {
console.log('[SherpaTTS STUB] Sherpa TTS disabled for Expo Go - using expo-speech instead');
return false;
}
export async function speak(
text: string,
options?: {
speed?: number;
speakerId?: number;
onStart?: () => void;
onDone?: () => void;
onError?: (error: Error) => void;
}
): Promise<void> {
options?.onError?.(new Error('Sherpa TTS disabled for Expo Go'));
}
export function stop(): void {
// No-op
}
export function deinitialize(): void {
// No-op
}
export function isAvailable(): boolean {
return false;
}
export function getCurrentVoice(): PiperVoice {
return AVAILABLE_VOICES[0];
}
export async function setVoice(voiceId: string): Promise<boolean> {
return false;
}
export async function loadSavedVoice(): Promise<PiperVoice> {
return AVAILABLE_VOICES[0];
}
export default {
initialize: initializeSherpaTTS,
speak,
stop,
deinitialize,
isAvailable,
addStateListener,
getState,
getVoices: () => AVAILABLE_VOICES,
getCurrentVoice,
setVoice,
loadSavedVoice,
};