Add crunch presets, echo options, and streaming word mode

This commit is contained in:
Fisto
2026-09-21 12:31:43 +02:00
parent bbb580deea
commit c66d00ee59
11 changed files with 371 additions and 17 deletions
+35 -1
View File
@@ -40,6 +40,22 @@ export interface TtsOptions {
voxClean?: boolean;
/** Half-Life profile preset for Keith Bell: vox or hev. */
preset?: "vox" | "hev";
/** Echo delay in ms, 10-400. */
echoDelayMs?: number;
/** Echo output gain, 0-0.95. */
echoLevel?: number;
/** Lossy 1990s compression preset, applied as its own stage last. */
crunch?: "hl90" | "hl90hq" | "telephone" | "adpcm" | "crush";
/** Bit depth for the crunch stage, 1-16 (overrides the preset). */
crunchBits?: number;
/** Sample rate for the crunch stage, 4000-48000 (overrides the preset). */
crunchRate?: number;
/** Stream word mode: the wrapper writes the WAV while it synthesizes. */
stream?: boolean;
/** Fixed gain for streaming lines (the measurement pass is skipped). */
streamGainDb?: number;
/** Called with the output path as soon as it is chosen, before synthesis. */
onOutputPath?: (path: string) => void;
}
export interface TtsEngine {
@@ -336,6 +352,7 @@ export class Tts {
const out = this.nextPath("wav");
const textFile = this.nextPath("txt");
writeFileSync(textFile, text);
options.onOutputPath?.(out);
const parts = command
? command
@@ -357,6 +374,12 @@ export class Tts {
.replace("{vox}", options.vox ? "1" : "")
.replace("{vox_clean}", options.voxClean ? "1" : "")
.replace("{preset}", options.preset ?? "")
.replace("{echo_delay_ms}", options.echoDelayMs !== undefined ? String(options.echoDelayMs) : "")
.replace("{echo_level}", options.echoLevel !== undefined ? String(options.echoLevel) : "")
.replace("{crunch}", options.crunch ?? "")
.replace("{crunch_bits}", options.crunchBits !== undefined ? String(options.crunchBits) : "")
.replace("{crunch_rate}", options.crunchRate !== undefined ? String(options.crunchRate) : "")
.replace("{stream}", options.stream ? "1" : "")
)
: ["espeak-ng", ...(options.voice ? ["-v", options.voice] : []), "-w", out, "-f", textFile];
@@ -385,7 +408,18 @@ export class Tts {
// preset implication (which only fires when the variable is unset).
VESKSLOP_TTS_VOX: options.vox ? "1" : "0",
...(options.voxClean ? { VESKSLOP_TTS_VOX_CLEAN: "1" } : {}),
...(options.preset ? { VESKSLOP_TTS_PRESET: options.preset } : {})
...(options.preset ? { VESKSLOP_TTS_PRESET: options.preset } : {}),
...(options.echoDelayMs !== undefined
? { VESKSLOP_TTS_ECHO_DELAY_MS: String(options.echoDelayMs) }
: {}),
...(options.echoLevel !== undefined ? { VESKSLOP_TTS_ECHO_LEVEL: String(options.echoLevel) } : {}),
...(options.crunch ? { VESKSLOP_TTS_CRUNCH: options.crunch } : {}),
...(options.crunchBits !== undefined ? { VESKSLOP_TTS_CRUNCH_BITS: String(options.crunchBits) } : {}),
...(options.crunchRate !== undefined ? { VESKSLOP_TTS_CRUNCH_RATE: String(options.crunchRate) } : {}),
...(options.stream ? { VESKSLOP_TTS_STREAM: "1" } : {}),
...(options.streamGainDb !== undefined
? { VESKSLOP_TTS_STREAM_GAIN_DB: String(options.streamGainDb) }
: {})
},
stdio: ["ignore", "ignore", "pipe"]
});