| | import { env } from '@huggingface/transformers'; |
| | import { KokoroTTS } from 'kokoro-js'; |
| |
|
| | |
| | env.backends.onnx.wasm.wasmPaths = '/wasm/'; |
| |
|
| | let tts; |
| | let isInitialized = false; |
| | const DEFAULT_MODEL_ID = 'onnx-community/Kokoro-82M-v1.0-ONNX'; |
| |
|
| | self.onmessage = async (event) => { |
| | const { type, payload } = event.data; |
| |
|
| | if (type === 'init') { |
| | let { model_id, dtype } = payload; |
| | model_id = model_id || DEFAULT_MODEL_ID; |
| |
|
| | self.postMessage({ status: 'init:start' }); |
| |
|
| | try { |
| | tts = await KokoroTTS.from_pretrained(model_id, { |
| | dtype, |
| | device: !!navigator?.gpu ? 'webgpu' : 'wasm' |
| | }); |
| | isInitialized = true; |
| | self.postMessage({ status: 'init:complete' }); |
| | } catch (error) { |
| | isInitialized = false; |
| | self.postMessage({ status: 'init:error', error: error.message }); |
| | } |
| | } |
| |
|
| | if (type === 'generate') { |
| | if (!isInitialized || !tts) { |
| | |
| | self.postMessage({ status: 'generate:error', error: 'TTS model not initialized' }); |
| | return; |
| | } |
| |
|
| | const { text, voice } = payload; |
| | self.postMessage({ status: 'generate:start' }); |
| |
|
| | try { |
| | const rawAudio = await tts.generate(text, { voice }); |
| | const blob = await rawAudio.toBlob(); |
| | const blobUrl = URL.createObjectURL(blob); |
| | self.postMessage({ status: 'generate:complete', audioUrl: blobUrl }); |
| | } catch (error) { |
| | self.postMessage({ status: 'generate:error', error: error.message }); |
| | } |
| | } |
| |
|
| | if (type === 'status') { |
| | |
| | self.postMessage({ status: 'status:check', initialized: isInitialized }); |
| | } |
| | }; |
| |
|