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) { 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, 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(); let infos: { file: number; text: string }[]; try { infos = Bun.JSONL.parse(decoded) as { file: number; text: string }[]; } catch { console.log(decoded); continue; } for (const info of infos) { const file = `${home}/.ttsc/${info.file}.wav`; console.log(`\n${chalk.blue(file)}:\n${info.text}`); 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", "--pause", "output.wav"], cwd, stdin: "ignore", stdout: "inherit", stderr: "inherit", }).exited;