bennylam's picture
Upload 5 files
c58e311 verified
Raw
History Blame Contribute Delete
1.97 kB
import { HFModelConfig_v1, InterfaceHF } from "outetts";
// Check if WebGPU is supported
let fp16_supported = false;
try {
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
throw new Error("WebGPU is not supported (no adapter found)");
}
fp16_supported = adapter.features.has("shader-f16");
self.postMessage({ status: "feature-success" });
} catch (e) {
self.postMessage({
status: "feature-error",
data: e.toString(),
});
throw e;
}
// Configure the model
const model_config = new HFModelConfig_v1({
model_path: "onnx-community/OuteTTS-0.2-500M",
language: "en", // Supported languages in v0.2: en, zh, ja, ko
dtype: fp16_supported ? "q4f16" : "q4", // Supported dtypes: fp32, fp16, q8, q4, q4f16
device: "webgpu", // Supported devices: webgpu, wasm
});
// Initialize the interface
const tts_interface = await InterfaceHF({
model_version: "0.2",
cfg: model_config,
});
self.postMessage({ status: "ready" });
// Listen for messages from the main thread
self.addEventListener("message", async (e) => {
const { text, speaker_id } = e.data;
// Load a default speaker
const speaker =
speaker_id === "random"
? null
: tts_interface.load_default_speaker(speaker_id);
// Generate speech
const output = await tts_interface.generate({
text,
temperature: 0.1, // Lower temperature values may result in a more stable tone
repetition_penalty: 1.1,
max_length: 4096,
// Optional: Use a speaker profile for consistent voice characteristics
// Without a speaker profile, the model will generate a voice with random characteristics
speaker,
});
// Send the audio file back to the main thread
const buffer = output.to_wav("output.wav");
const blob = new Blob([buffer], { type: "audio/wav" });
self.postMessage({
status: "complete",
audio: URL.createObjectURL(blob),
text,
});
});