/** * TTS Provider Factory * * Creates and registers TTS providers based on speech configuration. * Reads enabled flags and URLs from config and instantiates the appropriate * provider for each tier. * * Each tier maps to a specific TTS engine: * - default: Kokoro-FastAPI (CPU, always available) * - premium: Chatterbox (GPU, voice cloning) * - fallback: Piper via OpenedAI Speech (ultra-lightweight CPU) * * Issue #391 */ import { Logger } from "@nestjs/common"; import { ChatterboxTTSProvider } from "./chatterbox-tts.provider"; import { KokoroTtsProvider } from "./kokoro-tts.provider"; import { PiperTtsProvider } from "./piper-tts.provider"; import type { ITTSProvider } from "../interfaces/tts-provider.interface"; import type { SpeechTier, AudioFormat } from "../interfaces/speech-types"; import type { SpeechConfig } from "../speech.config"; // ========================================== // Factory function // ========================================== const logger = new Logger("TTSProviderFactory"); /** * Create and register TTS providers based on the speech configuration. * * Only creates providers for tiers that are enabled in the config. * Returns a Map keyed by SpeechTier for use with the TTS_PROVIDERS injection token. * * @param config - Speech configuration with TTS tier settings * @returns Map of enabled TTS providers keyed by tier */ export function createTTSProviders(config: SpeechConfig): Map { const providers = new Map(); // Default tier: Kokoro if (config.tts.default.enabled) { const provider = new KokoroTtsProvider( config.tts.default.url, config.tts.default.voice, config.tts.default.format as AudioFormat ); providers.set("default", provider); logger.log(`Registered default TTS provider: kokoro at ${config.tts.default.url}`); } // Premium tier: Chatterbox if (config.tts.premium.enabled) { const provider = new ChatterboxTTSProvider(config.tts.premium.url); providers.set("premium", provider); logger.log(`Registered premium TTS provider: chatterbox at ${config.tts.premium.url}`); } // Fallback tier: Piper if (config.tts.fallback.enabled) { const provider = new PiperTtsProvider(config.tts.fallback.url); providers.set("fallback", provider); logger.log(`Registered fallback TTS provider: piper at ${config.tts.fallback.url}`); } if (providers.size === 0) { logger.warn("No TTS providers are enabled. TTS synthesis will not be available."); } else { const tierNames = Array.from(providers.keys()).join(", "); logger.log(`TTS providers ready: ${tierNames} (${String(providers.size)} total)`); } return providers; }