fix(hyperframes-media): surface the real reason a TTS line failed [P2] (#1999)

* fix(hyperframes-media): surface the real reason a TTS line failed

synthesizeHeygen() swallowed every failure into a bare { ok:false }: a thrown
HTTP error (e.g. 402 plan_upgrade_required from heygenJSON) was caught and
discarded, a missing audio_url / failed audio fetch / failed transcode all
returned nothing. audio.mjs then logged 'TTS failed — omitted' for every line
with zero detail, so the actual cause took a hand-rolled repro to find.

Each failure path now returns an { error } string (the caught message, the HTTP
status, or the specific stage that failed), and audio.mjs appends it to the
anomaly. The subprocess providers (elevenlabs/kokoro) get the same treatment via
a shared synthResult() helper. synthesizeHeygen takes an injectable deps arg so
the failure paths are unit-tested (thrown 402, non-ok fetch, missing audio_url).

* fix(media-use): report wav transcode failures accurately

* chore: regenerate skills manifest
This commit is contained in:
Miguel Ángel
2026-07-11 18:32:08 -04:00
committed by GitHub
parent fecd7dc1d3
commit 9c98c1e82a
4 changed files with 113 additions and 17 deletions
+2 -2
View File
@@ -145,7 +145,7 @@ if (only.has("tts") && lines.length) {
}
const rel = `assets/voice/${id}.wav`;
const abs = join(hyperframesDir, rel);
const { ok, words } = await synthesizeOne({
const { ok, words, error } = await synthesizeOne({
provider: ttsProvider,
text,
voiceId,
@@ -155,7 +155,7 @@ if (only.has("tts") && lines.length) {
hyperframesDir,
});
if (!ok) {
anomalies.push(`line ${id}: TTS failed — omitted`);
anomalies.push(`line ${id}: TTS failed — omitted${error ? ` (${error})` : ""}`);
return null;
}
let wordArr = words; // heygen: native; else transcribe