{"record":{"id":"4ade32bb0bd3b1be","repo":"heygen-com/hyperframes","slug":"audio-fx-produced-no-samples-for-track-options-t","errorCode":null,"errorMessage":"Audio FX produced no samples for track ${options.trackId}","messagePattern":"Audio FX produced no samples for track (.+?)","errorType":"exception","errorClass":"AudioFxRenderError","httpStatus":null,"severity":"error","filePath":"packages/engine/src/services/audioFxRender.ts","lineNumber":274,"sourceCode":"        },\n        [\n          planes.map((plane) =>\n            Buffer.from(plane.buffer, plane.byteOffset, plane.length * 4).toString(\"base64\"),\n          ),\n          sampleRate,\n          JSON.stringify(chain),\n        ] as [string[], number, string],\n      )) as string[];\n\n      // byteOffset and byteLength matter: Node pools small allocations, so a\n      // short payload decodes into an 8 KiB pool and a view over the whole\n      // ArrayBuffer would read kilobytes of unrelated memory at the wrong length.\n      const outPlanes = rendered.map((b64) => {\n        const buf = Buffer.from(b64, \"base64\");\n        return new Float32Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));\n      });\n      if (outPlanes.length === 0 || (outPlanes[0]?.length ?? 0) === 0) {\n        throw new AudioFxRenderError(`Audio FX produced no samples for track ${options.trackId}`);\n      }\n      writeWav(outputWav, interleave(outPlanes), sampleRate, outPlanes.length);\n      return outputWav;\n    } finally {\n      await page.close().catch(() => undefined);\n    }\n  } catch (err) {\n    if (err instanceof AudioFxRenderError) throw err;\n    throw new AudioFxRenderError(\n      `Audio FX failed for track ${options.trackId}: ${(err as Error).message}`,\n    );\n  } finally {\n    rmSync(hostDir, { recursive: true, force: true });\n    await lease.release().catch(() => undefined);\n  }\n}\n\nexport type { HfAudioFxChain };","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/engine/src/services/audioFxRender.ts#L256-L292","documentation":"Thrown when the browser-side audio FX render returns zero output planes or an empty first plane. After decoding the base64-encoded Float32 arrays back from the page, the code checks outPlanes.length === 0 or outPlanes[0]?.length === 0. A successful render must produce at least one non-empty sample plane; silence or an empty result indicates the FX chain consumed all input without producing output.","triggerScenarios":"The page.evaluate call to api.render(channelB64, rate, chainJson) resolved successfully, but the returned array is empty or contains only empty Float32Arrays. This can happen if the FX runtime has a bug in its output encoding, if the chainJson describes a chain that produces zero-length output, or if a gain/node silences the signal to exactly zero samples.","commonSituations":"A custom AudioFxNode has a bug that returns an empty buffer. The chain JSON is malformed enough to pass validation but produces no output. The base64 round-trip between page and Node lost data (though that more likely causes a different decode error). A gate/expander node with extreme settings eliminates all samples.","solutions":["Log the chainJson and the number of input planes/samples to verify the chain is well-formed.","Test the FX chain in isolation in a browser with the same input WAV to see if output is genuinely empty.","Check enabledAudioFxNodes() output for unexpected or misconfigured nodes.","If a gain/gate effect is intentional, ensure it doesn't reduce output to exactly zero-length — a silence plane should still have sample-count matching input."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await applyAudioFxChain(inputWav, chain, outWav, opts);\n} catch (err) {\n  if (err instanceof AudioFxRenderError && err.message.includes('produced no samples')) {\n    // test chain in isolation, check for silencing nodes\n  }\n  throw err;\n}","preventionTips":["Validate the FX chain configuration before rendering: ensure no node has an extreme gain/gate that eliminates all samples.","Test FX chains with a short clip in a browser console before full render.","Log input sample count and compare with output to catch silent chains early."],"tags":["audio","fx-chain","browser","validation","data-integrity"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}