heygen-com/hyperframes · error · AudioFxRenderError
Audio FX input is missing: ${inputWav}
Error message
Audio FX input is missing: ${inputWav} What it means
Thrown by applyAudioFxChain() when existsSync(inputWav) returns false — the WAV file that the FX chain is supposed to process does not exist on disk. The comment above the function explains this is a fatal error, not a soft warning, because silently rendering the dry signal produces a mix that sounds plausible but is not what the author configured.
Source
Thrown at packages/engine/src/services/audioFxRender.ts:202
/**
* Run a chain over `inputWav`, writing `outputWav`. Resolves to the path to use
* downstream: `outputWav` when the chain did something, `inputWav` untouched
* when the chain was empty.
*
* Failure is fatal to the caller rather than a soft per-track warning: quietly
* rendering the dry signal ships a mix that sounds plausible and is not what
* the author set up.
*/
export async function applyAudioFxChain(
inputWav: string,
chain: HfAudioFxChain,
outputWav: string,
options: { trackId: string; signal?: AbortSignal },
): Promise<string> {
if (enabledAudioFxNodes(chain).length === 0) return inputWav;
if (!existsSync(inputWav)) {
throw new AudioFxRenderError(`Audio FX input is missing: ${inputWav}`);
}
const { samples, sampleRate, channels } = readWav(inputWav);
const planes = deinterleave(samples, channels);
// Audio processing needs no GPU or special capture mode; a plain sandboxed
// browser is enough, and the lease pool reuses one across tracks.
const lease = await acquireBrowser([
"--no-sandbox",
"--autoplay-policy=no-user-gesture-required",
]);
const hostDir = mkdtempSync(join(tmpdir(), "hf-fx-host-"));
try {
if (options.signal?.aborted) {
throw new AudioFxRenderError(`Audio FX cancelled for track ${options.trackId}`);
}
const page = await lease.browser.newPage();
try {View on GitHub (pinned to c2996c8626)
Solutions
- Check that the upstream render step for this track completed and wrote the WAV: verify with fs.existsSync(path) before calling applyAudioFxChain.
- Inspect the path for typos, wrong tmpdir, or missing directory components.
- If rendering in a serverless/container environment, ensure the temp volume is shared between the render and FX steps.
- Log the trackId and resolved path in the producer's track scheduler to catch mapping bugs early.
Example fix
// before
await applyAudioFxChain(inputWav, chain, outWav, opts);
// after
import { existsSync } from 'fs';
if (!existsSync(inputWav)) {
throw new Error(`Track ${opts.trackId}: upstream render did not produce ${inputWav}`);
}
await applyAudioFxChain(inputWav, chain, outWav, opts); Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, statSync } from 'fs';
function validateInputWav(path: string): void {
if (!existsSync(path)) {
throw new Error(`Input WAV not found: ${path}. Check upstream render step.`);
}
const stat = statSync(path);
if (stat.size < 44) {
throw new Error(`Input WAV too small (${stat.size} bytes): ${path}`);
}
}
validateInputWav(inputWav); Try / catch
try {
await applyAudioFxChain(inputWav, chain, outWav, opts);
} catch (err) {
if (err instanceof AudioFxRenderError && err.message.includes('input is missing')) {
// re-run upstream render, or mark track as failed
}
throw err;
} Prevention
- Add a post-render assertion in the producer that each track WAV exists and is non-empty before scheduling FX.
- Use deterministic temp paths derived from trackId to avoid path mapping bugs.
- In serverless environments, use a shared volume or EFS for intermediate WAV files.
When it happens
Trigger: applyAudioFxChain(inputWav, chain, outputWav, options) is called after enabledAudioFxNodes(chain).length > 0 confirms there are active FX nodes, but the inputWav path does not resolve to an existing file. The check runs before readWav().
Common situations: The upstream capture/render step that should have produced the track WAV failed or was skipped. A temp-file path was garbage-collected or used a different tmpdir than expected. The trackId-to-path mapping in the producer pipeline has a bug. A render was interrupted between scheduling and execution.
Related errors
- [s3Transport] upload source missing: ${localPath}
- [s3Transport] tar source must be an existing directory: ${so
- [s3Transport] tarball missing: ${tarballPath}
- [deploySite] projectDir is not a directory: ${opts.projectDi
- 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/734feab79e9b575d.
Report an issue: GitHub.