// Pre-flight for the two media elements the audio renderer rejects. // // RCA `issue-mp4-audio-export-html5audio-silent-degrade`: `renderMediaOnWeb` — // the ONLY export path that can mux an audio track — supports only // `@remotion/media` media elements. `remotion`'s `Audio` (which IS // `Html5Audio`) and `OffthreadVideo` are both rejected at render time. The shim // catches the throw and degrades to the video-only frame-step path, so the // export "succeeds" muted — and ~40x slower (measured: ~37 min vs ~45 s on the // sibling artboard). // // DDR-157's blanket "degrade on ANY renderer failure" is right for the class it // was built for: the recursion overflow is data-dependent, manifests late, and // the author cannot fix it. `` is the opposite — decidable from // source before a browser is ever launched, always fails, one-line remedy stated // in the error itself. Swallowing THAT into a generic fallback turns a fixable // mistake into a mysterious one, so we decide it here instead. // // Deliberately a regex-over-known-vocabulary scan rather than a real parser, // matching the house style of `bin/_canvas-rects-static.mjs`: the vocabulary is // fixed (two symbols, one module specifier) and a parser dependency for this // would cost more than it buys. import { existsSync, readFileSync } from 'node:fs'; import path from 'node:path'; /** The elements `@remotion/web-renderer` refuses, and what to do about each. */ export type UnsupportedElement = 'Audio' | 'OffthreadVideo'; export interface UnsupportedFinding { element: UnsupportedElement; /** Where the `from 'remotion'` import actually lives — the canvas, or a barrel it re-exports through. */ sourceFile: string; /** True when the canvas reached it through a re-export barrel rather than directly. */ viaBarrel: boolean; /** The name the JSX mounts it under — differs from `element` when aliased. */ localName: string; } const CANDIDATE_EXTS = ['.tsx', '.ts', '.jsx', '.js']; /** * Named bindings imported from the bare `remotion` specifier. * * Matches `import { A, B as C } from 'remotion'` and the `export { A } from * 'remotion'` re-export form, single or double quoted. Deliberately anchored to * the EXACT specifier: `@remotion/media` and `@remotion/transitions` are the * supported packages and must never match. */ function bindingsFromRemotion(src: string): Map { // originalName -> localName. Both halves matter and they are NOT // interchangeable: the ORIGINAL name identifies which element this is, but the // LOCAL name is what the JSX actually mounts. `import { Audio as Sound }` // renders ``, so checking for `