See More

import { mkdir } from "node:fs/promises"; import { dirname, resolve } from "node:path"; import { spawn } from "node:child_process"; export async function synthesize( text, output, { voice = "Ryan", language = "en", style = null, utterCommand = "utter" } = {}, ) { const absoluteOutput = resolve(output); await mkdir(dirname(absoluteOutput), { recursive: true }); const args = [ "speak", "--stdin", "--voice", voice, "--language", language, "--output", absoluteOutput, "--json", ]; if (style) args.push("--style", style); return await new Promise((resolvePromise, reject) => { const child = spawn(utterCommand, args); let stdout = ""; let stderr = ""; child.stdout.setEncoding("utf8").on("data", chunk => stdout += chunk); child.stderr.setEncoding("utf8").on("data", chunk => stderr += chunk); child.on("error", reject); child.on("close", code => { let payload; try { payload = JSON.parse(stdout); } catch (error) { reject(new Error(`Utter returned invalid JSON: ${stdout}\n${stderr}`)); return; } if (code !== 0) { reject(new Error( `Utter failed (${payload.error?.code}): ` + `${payload.error?.message}\n${stderr.trim()}`, )); return; } resolvePromise(payload.output); }); child.stdin.end(text, "utf8"); }); }