diff --git a/tts.ts b/tts.ts index ea0dbff..deeab18 100644 --- a/tts.ts +++ b/tts.ts @@ -1,20 +1,51 @@ import os from "node:os"; +import { parseArgs } from "node:util"; +import { $, which } from "bun"; import chalk from "chalk"; +const { values: args } = parseArgs({ + args: Bun.argv, + options: { + wait: { type: "boolean" }, + w: { type: "boolean" }, + }, + strict: true, + allowPositionals: true, +}); + +const wait = args.wait ?? args.w; const text = await Bun.stdin.text(); -if (!text) process.exit(1); +if (!text) { + console.error("No input given."); + process.exit(1); +} const home = os.homedir(); +const cwd = `${home}/.ttsc/`; +$.cwd(cwd); + +await $`rm *.wav`.nothrow(); + +console.log(chalk.blue("Welcome to TTSC!")); +console.log( + chalk.yellow( + "Beginning TTS processing... (This will take extra time the first time)", + ), +); const koko = Bun.spawn({ cmd: ["uv", "run", "--", "python", "-u", "main.py"], - cwd: `${home}/.ttsc/`, + cwd, stdin: Buffer.from(text), stdout: "pipe", stderr: "inherit", }); +if (!wait) { + koko.exited.then(() => console.log(chalk.green("\nProcessing finished."))); +} + const decoder = new TextDecoder(); for await (const line of koko.stdout) { const decoded = decoder.decode(line).trim(); @@ -28,16 +59,40 @@ for await (const line of koko.stdout) { } for (const info of infos) { - console.log(`\n${chalk.blue(info.file)}: ${info.text}\n`); + const file = `${home}/.ttsc/${info.file}.wav`; + console.log(`\n${chalk.blue(file)}:\n${info.text}`); - await Bun.spawn({ - cmd: ["mpv", `${info.file}.wav`], - cwd: `${home}/.ttsc/`, - stdin: "ignore", - stdout: "inherit", - stderr: "inherit", - }).exited; + if (!wait) { + await Bun.spawn({ + cmd: ["mpv", file], + cwd, + stdin: "ignore", + stdout: "inherit", + stderr: "inherit", + }).exited; + } } } await koko.exited; +if (!wait) process.exit(); + +console.log(chalk.green("\nProcessing finished.")); + +console.log(chalk.yellow(`Combining audio with sox...`)); +if (which("sox")) { + await $`sox *.wav output.wav`; + console.log(chalk.green(`Playing audio from ${cwd}output.wav`)); +} else { + console.error("Sox not found. Unable to combine outputs."); + console.log(chalk.yellow(`Audio available in ${cwd}`)); + process.exit(); +} + +await Bun.spawn({ + cmd: ["mpv", "output.wav"], + cwd, + stdin: "ignore", + stdout: "inherit", + stderr: "inherit", +}).exited; diff --git a/tts/main.py b/tts/main.py index c988ac8..abee7bd 100755 --- a/tts/main.py +++ b/tts/main.py @@ -9,5 +9,5 @@ pipeline = KPipeline(lang_code="a", repo_id="hexgrad/Kokoro-82M") generator = pipeline(text, voice="af_heart", speed=1.2) for i, (gs, ps, audio) in enumerate(generator): - print(json.dumps({"file": i, "text": gs})) sf.write(f"{i}.wav", audio, 24000) + print(json.dumps({"file": i, "text": gs}))