diff --git a/kokoro.ts b/kokoro.ts index 2ecdbc8..29c9e84 100644 --- a/kokoro.ts +++ b/kokoro.ts @@ -3,14 +3,14 @@ * 2. Modify onnxruntime-node/dist/binding.js for bun * 3. Profit */ import os from "node:os"; -import { $ } from "bun"; +import { $, which } from "bun"; import chalk from "chalk"; import { KokoroTTS, TextSplitterStream } from "kokoro-js"; const model_id = "onnx-community/Kokoro-82M-v1.0-ONNX"; const tts = await KokoroTTS.from_pretrained(model_id, { - dtype: "fp32", // Options: "fp32", "fp16", "q8", "q4", "q4f16" - device: "cpu", // Options: "wasm", "webgpu" (web) or "cpu" (node). If using "webgpu", we recommend using dtype="fp32". + dtype: "fp32", // fp32 and q8 work best; fp16 results in silent segments + device: "cpu", }); const stream = new TextSplitterStream(); @@ -21,46 +21,46 @@ if (!input) { } stream.push(input); +console.log(chalk.blue("Welcome to aitts!\n")); +console.log(input); + await $`rm -r ${os.homedir()}/.aitts/`.nothrow(); await $`mkdir ${os.homedir()}/.aitts/`.nothrow(); let fileId = 0; -let buffer = ""; -for (const text of stream) { - buffer += ` ${text}`; - if (buffer.length < 100) continue; +const files: string[] = []; - console.log(`${chalk.blue(fileId)}:${buffer}`); - const audio = await tts.generate(buffer, { - voice: "af_heart", +const processText = async (text: string) => { + const audio = await tts.generate(text, { + voice: "af_bella", speed: 1.2, }); const file = `${os.homedir()}/.aitts/${fileId}.wav`; audio.save(file); - + files.push(file); fileId++; - buffer = ""; +}; + +const play = async () => { + for (const file of files) { + console.log(chalk.green(`Playing ${file}`)); + await Bun.spawn({ + cmd: ["mpv", file], + stdout: "inherit", + }).exited; + process.stdout.moveCursor(-9999, -5); + process.stdout.clearScreenDown(); + } +}; + +let playing: Promise | undefined; +for (const text of stream) { + await processText(text); + + if (!playing && which("mpv")) { + playing = play(); + } } -if (buffer) { - console.log(`${chalk.blue(fileId)}:${buffer}`); - const audio = await tts.generate(buffer, { - voice: "af_heart", - speed: 1.2, - }); - - const file = `${os.homedir()}/.aitts/${fileId}.wav`; - audio.save(file); -} - -console.log(chalk.yellow("Combine wav file with sox...")); -await $`sox ${os.homedir()}/.aitts/* ${os.homedir()}/.aitts/all.wav`; -console.log(chalk.green("Success: ~/.aitts/all.wav")); - -console.log(chalk.yellow("Listening with mpv...")); -await Bun.spawn({ - cmd: ["mpv", `${os.homedir()}/.aitts/all.wav`], - stdout: "inherit", -}).exited; -console.log(chalk.green("Have a nice day!")); +await playing;