heygen-com/hyperframes · error
${err instanceof Error ? err.message : String(err)}${detail}
Error message
${err instanceof Error ? err.message : String(err)}${detail} What it means
Thrown by detectOnPage() as a catch-all wrapper around any failure from page.evaluate(inPageAnalyze). It takes the underlying error's message (or String(err)) and appends collected page-error/console-error strings in parentheses so the cause of an opaque CDP rejection is visible. Common underlying causes: AudioContext.decodeAudioData rejected (unsupported codec, corrupt audio), __hfAnalyze threw, or the page crashed.
Source
Thrown at packages/cli/src/beats/headlessAnalyzer.ts:125
}
// Load the analyzer bundle into the page, run analysis, and surface in-page
// errors (decode/codec failures, missing global) instead of an opaque rejection.
async function detectOnPage(page: Page, bundle: string, b64: string): Promise<HeadlessBeatResult> {
const pageErrors: string[] = [];
page.on("pageerror", (e) => {
pageErrors.push((e as Error).message);
});
page.on("console", (m) => {
if (m.type() === "error") pageErrors.push(m.text());
});
await page.setContent("<!doctype html><html><body></body></html>");
await page.addScriptTag({ content: bundle });
try {
return (await page.evaluate(inPageAnalyze, b64)) as HeadlessBeatResult;
} catch (err) {
const detail = pageErrors.length ? ` (${pageErrors.join("; ")})` : "";
throw new Error(`${err instanceof Error ? err.message : String(err)}${detail}`);
}
}
/** Decode + analyze the given audio bytes in headless Chrome. */
export async function analyzeBeatsHeadless(audioBytes: Buffer): Promise<HeadlessBeatResult> {
if (audioBytes.length > MAX_AUDIO_BYTES) {
const mb = Math.round(audioBytes.length / 1e6);
throw new Error(
`Audio file too large for headless analysis (${mb}MB > ${MAX_AUDIO_BYTES / 1e6}MB).`,
);
}
const bundle = await buildAnalyzerBundle();
const { ensureBrowser } = await import("../browser/manager.js");
const puppeteer = await import("puppeteer-core");
const browser = await ensureBrowser();
const chrome: Browser = await puppeteer.default.launch({
headless: true,
executablePath: browser.executablePath,View on GitHub (pinned to c2996c8626)
Solutions
- Read the parenthesized detail in the message — it carries the in-page error (e.g. 'Failed to decode audio data').
- Convert the audio to a broadly supported format: `ffmpeg -i in.wma -c:a libmp3lame -q:a 2 out.mp3` or to WAV.
- Verify the file is a valid audio container: `ffprobe in.mp3`.
Example fix
# before — Chrome cannot decode WMA $ bunx hyperframes beats clip.wma # convert to mp3 $ ffmpeg -i clip.wma -c:a libmp3lame -q:a 2 clip.mp3 $ bunx hyperframes beats clip.mp3
Defensive patterns
Strategy: try-catch
Validate before calling
import { execFileSync } from 'node:child_process';
function audioDecodes(p: string): boolean {
try {
execFileSync('ffprobe', ['-v', 'error', '-select_streams', 'a', '-show_entries', 'stream=codec_name', '-of', 'csv=p=0', p], { encoding: 'utf-8' });
return true;
} catch { return false; }
}
if (!audioDecodes(inputPath)) throw new Error('Audio file is not decodable; convert to mp3/wav.'); Try / catch
try {
await analyzeBeatsHeadless(buf);
} catch (err) {
const msg = (err as Error).message;
if (/decode|audio/i.test(msg)) {
// convert to mp3 and retry
}
throw err;
} Prevention
- Feed mp3, wav, m4a, or ogg — formats Chrome's Web Audio decodes reliably.
- Validate the audio with ffprobe before analysis.
- Read the parenthesized page-error detail in the wrapped message to find the decode cause.
When it happens
Trigger: analyzeBeatsHeadless() calls detectOnPage(page, bundle, b64); page.evaluate throws because the audio bytes could not be decoded by the Web Audio decoder (e.g. a .wma or obscure codec), or inPageAnalyze threw for any reason.
Common situations: Input audio is in a format Chrome's Web Audio cannot decode (e.g. WMA, ATRAC, some FLAC variants on older Chrome); the audio buffer is truncated/corrupt; a transient page-level JS error occurred during analysis.
Related errors
- beat analyzer not loaded
- Model did not return output '${outputName}'
- No frames produced from ${inputPath}. Decoder stderr: ${deco
- Failed to bundle beat analyzer
- Audio file too large for headless analysis (${mb}MB > ${MAX_
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/f1ef177e65f83c37.
Report an issue: GitHub.