{"record":{"id":"c0b1f71bade3705c","repo":"heygen-com/hyperframes","slug":"unable-to-bake-required-browser-media-proxies-s","errorCode":null,"errorMessage":"Unable to bake required browser media proxies (${summary})","messagePattern":"Unable to bake required browser media proxies \\((.+?)\\)","errorType":"exception","errorClass":"ProxyBakeError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/utils/publishProxyBake.ts","lineNumber":134,"sourceCode":"        const proxyPath = await waitForProxy(\n          resolveProxy(absProjectDir, absoluteSourcePath, proxyVariantFor(facts)),\n          TRANSCODE_TIMEOUT_MS,\n        );\n        const archivePath = `${PROXY_ARCHIVE_PREFIX}/${basename(proxyPath)}`;\n        fileContents.set(archivePath, await readFile(proxyPath));\n        proxyByAbsolutePath.set(absoluteSourcePath, archivePath);\n        manifest.proxied.push(pathname);\n      } catch (err) {\n        const reason = err instanceof ProxyTranscodeError ? err.message : String(err);\n        manifest.failed.push({ path: pathname, error: reason });\n      }\n    }),\n  );\n\n  manifest.proxied.sort();\n  manifest.skippedAlpha.sort();\n  manifest.failed.sort((a, b) => a.path.localeCompare(b.path));\n  if (manifest.failed.length > 0) throw new ProxyBakeError(manifest);\n  if (proxyByAbsolutePath.size === 0) return manifest;\n\n  for (const [entryPath, content] of htmlEntries) {\n    const { document } = parseHTML(content.toString(\"utf-8\"));\n    const referrerAbsDir = resolve(absProjectDir, dirname(entryPath));\n    const modified = rewriteHtmlAttributes(\n      document,\n      referrerAbsDir,\n      entryPath,\n      (rawValue) => {\n        const cleaned = cleanAssetUrl(rawValue);\n        if (!cleaned || isRemoteOrInlineUrl(cleaned)) return null;\n        // Resolve the raw attribute value the same way the scan did\n        // (rewriteAssetPath to root-relative, then decodeUrlPathVariants via\n        // resolveLocalAssetCandidates) so percent-encoded and root-absolute\n        // srcs match the map keys the scan produced.\n        const rootRelativeSrc = rewriteAssetPath(entryPath, cleaned, (path) =>\n          existsSync(resolve(absProjectDir, path)),","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/utils/publishProxyBake.ts#L116-L152","documentation":"Thrown as a ProxyBakeError when one or more browser-hostile codec video files (HEVC, ProRes, AV1, etc.) could not be transcoded into browser-compatible proxy files during publish. Published pages are static with no server-side proxy negotiation, so hostile codecs must be pre-baked. Each failure is collected into a manifest.failed array; if any entry failed, publish is aborted with a structured summary rather than silently shipping an unplayable asset.","triggerScenarios":"A <video src> in the composition references a local file with a browser-hostile codec; the proxy transcoder (running via the studio-server transcoder) times out after TRANSCODE_TIMEOUT_MS, crashes, or the source file is unreadable. The catch block records the reason and, after all transcodes settle, throws if manifest.failed is non-empty.","commonSituations":"The transcoder ffmpeg/FFmpeg is missing or an incompatible version; the source video is corrupted or has an unusual codec profile; running publish in a CI environment without the studio-server's transcoder dependencies installed; a very large 4K HEVC file exceeding the transcode timeout.","solutions":["Check the manifest summary in the error — it lists each failed path and the specific transcode error reason.","Ensure ffmpeg is installed and accessible (run hyperframes check) — the proxy transcoder depends on it.","Pre-convert hostile-codec videos to H.264/AAC MP4 manually before publishing to bypass the bake step entirely.","If a specific file is the problem, replace or re-encode it locally and re-run publish."],"exampleFix":"// before: <video src=\"intro.mov\"></video> (ProRes — bake fails)\n// after: pre-convert to H.264 and reference the MP4 instead\n//   ffmpeg -i intro.mov -c:v libx264 -c:a aac intro.mp4\n//   <video src=\"intro.mp4\"></video>","handlingStrategy":"validation","validationCode":"import { scanProjectMediaCodecMap } from \"@hyperframes/studio-server/media-codec-map\";\n\n// Scan for hostile codecs before publish to pre-warn the user\nasync function checkHostileCodecs(projectDir: string, html: string): Promise<string[]> {\n  const codecMap = await scanProjectMediaCodecMap(projectDir, [{ html, compSrcPath: \"index.html\" }]);\n  return Object.entries(codecMap)\n    .filter(([, facts]) => facts.browserHostile)\n    .map(([pathname]) => pathname);\n}","typeGuard":null,"tryCatchPattern":"import { ProxyBakeError } from \"./publishProxyBake.js\";\n\ntry {\n  await bakeProxies(fileContents, projectDir);\n} catch (err) {\n  if (err instanceof ProxyBakeError) {\n    for (const f of err.manifest.failed) {\n      console.error(`Failed to proxy ${f.path}: ${f.error}`);\n    }\n    // Option: skip baking and publish with original files (risk: unplayable in some browsers)\n  } else throw err;\n}","preventionTips":["Pre-encode all video assets as H.264/AAC MP4 before composing — this eliminates the need for proxy baking entirely.","Run a local codec scan before publish to identify hostile codecs early.","Ensure ffmpeg is installed and accessible so the proxy transcoder can run."],"tags":["publish","media","codec","transcode","ffmpeg"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}