|
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 }); |
|
} |
|
}; |
|
|