@cueframe/kernel 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. package/dist/_members/animate/index.d.ts +8 -2
  2. package/dist/_members/animate/layout/FlexLayout.d.ts +69 -0
  3. package/dist/_members/animate/layout/fit.d.ts +44 -0
  4. package/dist/_members/animate/layout/index.d.ts +3 -0
  5. package/dist/_members/animate/layout/solveFlex.d.ts +70 -0
  6. package/dist/_members/animate/media/MediaTileScene.d.ts +65 -0
  7. package/dist/_members/animate/media/recipes.d.ts +61 -0
  8. package/dist/_members/animate/scene/FocusPass.d.ts +76 -0
  9. package/dist/_members/animate/scene/UnlitPlane.d.ts +45 -0
  10. package/dist/_members/animate/scene/__oracle__/cssProjection.d.ts +24 -0
  11. package/dist/_members/animate/scene/assets.d.ts +21 -0
  12. package/dist/_members/animate/scene/backdrop.d.ts +7 -0
  13. package/dist/_members/animate/scene/coordinates.d.ts +58 -0
  14. package/dist/_members/animate/scene/deviceOpacity.d.ts +18 -0
  15. package/dist/_members/animate/scene/errors.d.ts +14 -0
  16. package/dist/_members/animate/scene/finishing.d.ts +69 -0
  17. package/dist/_members/animate/scene/finishingMath.d.ts +60 -0
  18. package/dist/_members/animate/scene/finishingPass.d.ts +35 -0
  19. package/dist/_members/animate/scene/focusBlur.d.ts +56 -0
  20. package/dist/_members/animate/scene/focusResources.d.ts +190 -0
  21. package/dist/_members/animate/scene/focusShaders.d.ts +68 -0
  22. package/dist/_members/animate/scene/fontReadiness.d.ts +27 -0
  23. package/dist/_members/animate/scene/grainNoise.d.ts +118 -0
  24. package/dist/_members/animate/scene/index.d.ts +19 -0
  25. package/dist/_members/animate/scene/internal.d.ts +29 -0
  26. package/dist/_members/animate/scene/planeFit.d.ts +46 -0
  27. package/dist/_members/animate/scene/preparedWorldText.d.ts +25 -0
  28. package/dist/_members/animate/scene/rasterCache.d.ts +30 -0
  29. package/dist/_members/animate/scene/rasterReadiness.d.ts +33 -0
  30. package/dist/_members/animate/scene/readiness.d.ts +69 -0
  31. package/dist/_members/animate/scene/redraw.d.ts +10 -0
  32. package/dist/_members/animate/scene/render.d.ts +9 -0
  33. package/dist/_members/animate/scene/scaling.d.ts +13 -0
  34. package/dist/_members/animate/scene/text.d.ts +40 -0
  35. package/dist/_members/animate/scene/textLayout.d.ts +78 -0
  36. package/dist/_members/animate/scene/textureImageSize.d.ts +4 -0
  37. package/dist/_members/animate/scene/useSceneImageTexture.d.ts +21 -0
  38. package/dist/_members/animate/scene/useWorldTextTexture.d.ts +21 -0
  39. package/dist/_members/animate/scene/v2/MeasuredPlaneGeometry.d.ts +7 -0
  40. package/dist/_members/animate/scene/v2/PhotographicStudioRig.d.ts +11 -0
  41. package/dist/_members/animate/scene/v2/PreparedSceneShotV1.d.ts +12 -0
  42. package/dist/_members/animate/scene/v2/SceneShotV2.d.ts +59 -0
  43. package/dist/_members/animate/scene/v2/builders.d.ts +170 -0
  44. package/dist/_members/animate/scene/v2/finishes.d.ts +152 -0
  45. package/dist/_members/animate/scene/v2/lighting.d.ts +119 -0
  46. package/dist/_members/animate/scene/v2/observePmremTargets.d.ts +4 -0
  47. package/dist/_members/animate/scene/v2/preparationFacts.d.ts +32 -0
  48. package/dist/_members/animate/scene/v2/preparedSurface.d.ts +17 -0
  49. package/dist/_members/animate/scene/v2/projectedResolution.d.ts +2 -0
  50. package/dist/_members/animate/scene/v2/renderTargetObserver.d.ts +5 -0
  51. package/dist/_members/animate/scene/v2/runtimeAllocations.d.ts +55 -0
  52. package/dist/_members/animate/scene/v2/shadow.d.ts +23 -0
  53. package/dist/_members/animate/scene/v2/slabGeometry.d.ts +134 -0
  54. package/dist/_members/animate/scene/v2/slots.d.ts +73 -0
  55. package/dist/_members/animate/scene/v2/videoBinding.d.ts +39 -0
  56. package/dist/_members/animate/scene/worldBounds.d.ts +19 -0
  57. package/dist/_members/animate/scene/worldTextRaster.d.ts +87 -0
  58. package/dist/_members/animate/scene/worldTextTexture.d.ts +32 -0
  59. package/dist/_members/animate/stage/PerspectiveStage.d.ts +73 -0
  60. package/dist/_members/animate/stage/camera.d.ts +143 -0
  61. package/dist/_members/animate/stage/dof.d.ts +9 -0
  62. package/dist/_members/animate/stage/index.d.ts +6 -0
  63. package/dist/_members/animate/stage/presets.d.ts +17 -0
  64. package/dist/_members/animate/three/DeviceMesh.d.ts +256 -0
  65. package/dist/_members/animate/three/SceneCameraRig.d.ts +12 -0
  66. package/dist/_members/animate/three/StageCameraRig.d.ts +7 -0
  67. package/dist/_members/animate/three/StudioRig.d.ts +228 -0
  68. package/dist/_members/animate/three/ThreeCanvas.d.ts +22 -0
  69. package/dist/_members/animate/three/defaultScreen.d.ts +23 -0
  70. package/dist/_members/animate/three/index.d.ts +7 -1
  71. package/dist/_members/animate/three/textureLifecycle.d.ts +29 -0
  72. package/dist/_members/animate/three/toneMapping.d.ts +113 -0
  73. package/dist/_members/animate/three/useImageTexture.d.ts +17 -0
  74. package/dist/_members/authoring/index.d.ts +2 -0
  75. package/dist/_members/authoring/scene/index.d.ts +6 -0
  76. package/dist/_members/authoring/scene/materialize.d.ts +47 -0
  77. package/dist/_members/authoring/scene/validate.d.ts +80 -0
  78. package/dist/_members/authoring/scene/wrapper.d.ts +41 -0
  79. package/dist/_members/component-runtime/allowedImports.d.ts +3 -0
  80. package/dist/_members/component-runtime/allowedImports.d.ts.map +1 -0
  81. package/dist/_members/component-runtime/bake.d.ts +8 -0
  82. package/dist/_members/component-runtime/bake.d.ts.map +1 -1
  83. package/dist/_members/component-runtime/browserFirewall.d.ts +7 -1
  84. package/dist/_members/component-runtime/browserFirewall.d.ts.map +1 -1
  85. package/dist/_members/component-runtime/browserOptions.d.ts +59 -3
  86. package/dist/_members/component-runtime/browserOptions.d.ts.map +1 -1
  87. package/dist/_members/component-runtime/canonicalIdentity.d.ts +14 -0
  88. package/dist/_members/component-runtime/canonicalIdentity.d.ts.map +1 -1
  89. package/dist/_members/component-runtime/contracts.d.ts +341 -1
  90. package/dist/_members/component-runtime/contracts.d.ts.map +1 -1
  91. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts +5 -0
  92. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts.map +1 -0
  93. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts +5 -0
  94. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts.map +1 -0
  95. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts +8 -0
  96. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts.map +1 -0
  97. package/dist/_members/component-runtime/importPolicy.d.ts +3 -2
  98. package/dist/_members/component-runtime/importPolicy.d.ts.map +1 -1
  99. package/dist/_members/component-runtime/index.d.ts +3 -0
  100. package/dist/_members/component-runtime/index.d.ts.map +1 -1
  101. package/dist/_members/component-runtime/livePreviewProxy.d.ts +7 -0
  102. package/dist/_members/component-runtime/livePreviewProxy.d.ts.map +1 -0
  103. package/dist/_members/component-runtime/localRoot.d.ts +37 -0
  104. package/dist/_members/component-runtime/localRoot.d.ts.map +1 -0
  105. package/dist/_members/component-runtime/mediaResolution.d.ts +25 -0
  106. package/dist/_members/component-runtime/mediaResolution.d.ts.map +1 -0
  107. package/dist/_members/component-runtime/render.d.ts +151 -13
  108. package/dist/_members/component-runtime/render.d.ts.map +1 -1
  109. package/dist/_members/component-runtime/renderDiagnostics.d.ts +14 -0
  110. package/dist/_members/component-runtime/renderDiagnostics.d.ts.map +1 -0
  111. package/dist/_members/component-runtime/sceneAdmission.d.ts +47 -0
  112. package/dist/_members/component-runtime/sceneAdmission.d.ts.map +1 -0
  113. package/dist/_members/component-runtime/sourceWorkspace.d.ts +8 -0
  114. package/dist/_members/component-runtime/sourceWorkspace.d.ts.map +1 -1
  115. package/dist/_members/component-runtime/webglProbe.d.ts +191 -0
  116. package/dist/_members/component-runtime/webglProbe.d.ts.map +1 -0
  117. package/dist/_members/compose/primitiveRegistry.d.ts +2 -6
  118. package/dist/_members/composition/fonts/bundledFaces.d.ts +150 -0
  119. package/dist/_members/composition/fonts/captionFaces.d.ts +268 -0
  120. package/dist/_members/composition/fonts.d.ts +11 -4
  121. package/dist/_members/composition/graphics-plan/schemas.d.ts +4 -4
  122. package/dist/_members/composition/ops/types.d.ts +1 -1
  123. package/dist/_members/composition/primitive-catalog/index.d.ts +4 -0
  124. package/dist/_members/composition/primitive-catalog/types.d.ts +1 -0
  125. package/dist/_members/composition/projection/behind-readiness.d.ts +3 -0
  126. package/dist/_members/composition/projection/brandKit.d.ts +6 -0
  127. package/dist/_members/composition/projection/composition-floor.d.ts +2 -1
  128. package/dist/_members/composition/scene/animation.d.ts +25 -0
  129. package/dist/_members/composition/scene/budget.d.ts +29 -0
  130. package/dist/_members/composition/scene/budgetPolicy.d.mts +13 -0
  131. package/dist/_members/composition/scene/clipRules.d.ts +119 -0
  132. package/dist/_members/composition/scene/constraints.d.ts +61 -0
  133. package/dist/_members/composition/scene/device.d.ts +21 -0
  134. package/dist/_members/composition/scene/examples.d.ts +11 -0
  135. package/dist/_members/composition/scene/index.d.ts +11 -0
  136. package/dist/_members/composition/scene/photographicRig.d.ts +242 -0
  137. package/dist/_members/composition/scene/preparedRender.d.ts +239 -0
  138. package/dist/_members/composition/scene/resolution.d.ts +178 -0
  139. package/dist/_members/composition/scene/schema.d.ts +351 -0
  140. package/dist/_members/composition/scene/videoSchedule.d.ts +43 -0
  141. package/dist/_members/composition/validators/brandKit.d.ts +1 -0
  142. package/dist/_members/composition/validators/render.d.ts +2 -0
  143. package/dist/_members/composition-ops/index.d.ts +45 -0
  144. package/dist/_members/composition-ops/opRecorder.d.ts +1 -1
  145. package/dist/_members/core/render/compositionRender.d.ts +41 -9
  146. package/dist/_members/core/render/index.d.ts +9 -2
  147. package/dist/_members/core/render/sceneCaptureIdentity.d.ts +14 -0
  148. package/dist/_members/core/render/sceneShotPlan.d.ts +142 -0
  149. package/dist/_members/core/render/sceneShotPreparation.d.ts +57 -0
  150. package/dist/_members/core/render/slabDescriptor.d.ts +21 -0
  151. package/dist/_members/core/render/trackProjection.d.ts +33 -0
  152. package/dist/_members/core/render/types.d.ts +142 -0
  153. package/dist/_members/errors/registry.d.ts +6 -0
  154. package/dist/_members/mcp/adapter.d.ts +5 -0
  155. package/dist/_members/mcp/generated/harness.d.ts +1 -1
  156. package/dist/_members/mcp/generated/sceneContract.d.ts +155 -0
  157. package/dist/_members/mcp/sceneShot.d.ts +38 -0
  158. package/dist/_members/mcp/sceneShotExample.d.ts +22 -0
  159. package/dist/_members/media-model/api.d.ts +1 -0
  160. package/dist/_members/media-model/media-kind.d.ts +1 -1
  161. package/dist/_members/media-model/testing/mediaStoreContract.d.ts +1 -1
  162. package/dist/_members/primitives/effects/index.d.ts +1 -0
  163. package/dist/_members/primitives/effects/stage-camera/config.d.ts +50 -0
  164. package/dist/_members/primitives/effects/stage-camera/index.d.ts +31 -0
  165. package/dist/_members/primitives/layouts/flex-layout/config.d.ts +73 -0
  166. package/dist/_members/primitives/layouts/flex-layout/index.d.ts +4 -0
  167. package/dist/_members/primitives/layouts/index.d.ts +1 -0
  168. package/dist/_members/primitives/layouts/picture-in-picture/config.d.ts +1 -1
  169. package/dist/_members/primitives/lib/frameScale.d.ts +4 -0
  170. package/dist/_members/primitives/lib/index.d.ts +1 -0
  171. package/dist/_members/primitives/lib/palette.d.ts +30 -30
  172. package/dist/_members/primitives/lib/text/contrast.d.ts +2 -1
  173. package/dist/_members/primitives/lib/text/spec.d.ts +0 -8
  174. package/dist/_members/primitives/lib/types.d.ts +2 -0
  175. package/dist/_members/primitives/scenes/device-showcase/config.d.ts +41 -0
  176. package/dist/_members/primitives/scenes/device-showcase/index.d.ts +36 -0
  177. package/dist/_members/primitives/scenes/hero-device-assemble/config.d.ts +1 -0
  178. package/dist/_members/primitives/scenes/hero-device-assemble/index.d.ts +2 -1
  179. package/dist/_members/primitives/scenes/index.d.ts +1 -0
  180. package/dist/_members/primitives/ui-blocks/badge-pop/config.d.ts +1 -1
  181. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/config.d.ts +1 -0
  182. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/index.d.ts +2 -1
  183. package/dist/_members/primitives/ui-blocks/terminal-simulator/config.d.ts +1 -1
  184. package/dist/_members/primitives/ui-blocks/toast-notification/config.d.ts +1 -1
  185. package/dist/_members/render-harness/cardAssetAdmission.d.ts.map +1 -1
  186. package/dist/_members/render-harness/cardRender.d.ts.map +1 -1
  187. package/dist/_members/render-harness/css-tree-subpaths.d.ts +11 -0
  188. package/dist/_members/render-harness/extractSegments.d.ts +1 -0
  189. package/dist/_members/render-harness/extractSegments.d.ts.map +1 -1
  190. package/dist/_members/render-harness/imageHeader.d.ts +14 -0
  191. package/dist/_members/render-harness/imageHeader.d.ts.map +1 -0
  192. package/dist/_members/render-harness/index.d.ts +6 -0
  193. package/dist/_members/render-harness/index.d.ts.map +1 -1
  194. package/dist/_members/render-harness/materializeSources.d.ts +46 -2
  195. package/dist/_members/render-harness/materializeSources.d.ts.map +1 -1
  196. package/dist/_members/render-harness/nodeScenePreparation.d.ts +97 -0
  197. package/dist/_members/render-harness/nodeScenePreparation.d.ts.map +1 -0
  198. package/dist/_members/render-harness/remotion-runtime.d.ts +16 -2
  199. package/dist/_members/render-harness/renderInputAssets.d.ts +1 -1
  200. package/dist/_members/render-harness/renderInputAssets.d.ts.map +1 -1
  201. package/dist/_members/render-harness/resolveAssets.d.ts +2 -2
  202. package/dist/_members/render-harness/resolveAssets.d.ts.map +1 -1
  203. package/dist/_members/render-harness/sceneShotAssets.d.ts +17 -0
  204. package/dist/_members/render-harness/sceneShotAssets.d.ts.map +1 -0
  205. package/dist/animate/preparation-facts.d.ts +1 -0
  206. package/dist/animate/preparation-facts.js +22 -0
  207. package/dist/animate.js +336 -1005
  208. package/dist/authoring/build-tools.js +7 -6
  209. package/dist/authoring/context.js +5 -4
  210. package/dist/authoring/prompts.js +1 -1
  211. package/dist/authoring/scene.d.ts +1 -0
  212. package/dist/authoring/scene.js +50 -0
  213. package/dist/authoring/tools.js +6 -5
  214. package/dist/authoring.js +49 -29
  215. package/dist/chunk-2L7PYYJK.js +23 -0
  216. package/dist/chunk-5DJ3IEJR.js +4424 -0
  217. package/dist/chunk-6BVVCRRD.js +26488 -0
  218. package/dist/{chunk-DQKSCHFC.js → chunk-6EWRIAZA.js} +187 -66
  219. package/dist/{chunk-YQ7FFW3G.js → chunk-6VWICHOZ.js} +26 -5
  220. package/dist/{chunk-C5SEPOWD.js → chunk-7AZLFN26.js} +1798 -702
  221. package/dist/{chunk-6ID2J64H.js → chunk-7W6ZIKWV.js} +162 -25
  222. package/dist/{chunk-RETQFTGY.js → chunk-A74FZCPY.js} +42 -5
  223. package/dist/chunk-BVA3537Z.js +63 -0
  224. package/dist/{chunk-DHKQ47Q6.js → chunk-DAARYRNT.js} +6 -1
  225. package/dist/chunk-DQLYWNLC.js +2063 -0
  226. package/dist/{chunk-HXKTZPRH.js → chunk-E7GIZEPS.js} +1 -1
  227. package/dist/chunk-EBIBLL7E.js +3619 -0
  228. package/dist/{chunk-M2TLRXEO.js → chunk-EXY4JJPH.js} +1 -1
  229. package/dist/{chunk-AWT3P5ZN.js → chunk-FVDFPJHT.js} +1 -1
  230. package/dist/{chunk-EMGFZ3PR.js → chunk-FWSJLHSV.js} +5 -1
  231. package/dist/{chunk-TMIBBD5E.js → chunk-I5QWBM3M.js} +280 -113
  232. package/dist/{chunk-IBMJ33EL.js → chunk-I5RX2QZT.js} +1 -1
  233. package/dist/{chunk-4FOOBSEE.js → chunk-J3DIUG24.js} +1 -0
  234. package/dist/{chunk-AD5HWBCE.js → chunk-JX53CVJV.js} +14 -5
  235. package/dist/{chunk-LNBVTDFR.js → chunk-L2AHS3AW.js} +1 -1
  236. package/dist/{chunk-BDMTUEEZ.js → chunk-LT4PWSR2.js} +2 -2
  237. package/dist/chunk-MH3UPKWR.js +3415 -0
  238. package/dist/{chunk-RFXR7ATW.js → chunk-MN6D3U5N.js} +13 -1
  239. package/dist/{chunk-IJ7PVJTK.js → chunk-ODUWCQI3.js} +3 -2
  240. package/dist/chunk-QAGGJHAF.js +16 -0
  241. package/dist/chunk-QS36DMFG.js +332 -0
  242. package/dist/{chunk-G5BFI32U.js → chunk-RAXHCRVV.js} +1 -1
  243. package/dist/{chunk-BIBYZJL3.js → chunk-RL5SO653.js} +3 -3
  244. package/dist/{chunk-ZSZABOE5.js → chunk-S5H6GH6M.js} +1 -1
  245. package/dist/{chunk-EEXCDFY5.js → chunk-SD25VQDE.js} +1 -1
  246. package/dist/chunk-TARKDVP6.js +430 -0
  247. package/dist/{chunk-XVBOSPZI.js → chunk-TBNTAQJA.js} +6 -6
  248. package/dist/{chunk-IHFREGFA.js → chunk-TCHPRGC5.js} +18 -2
  249. package/dist/{chunk-ZCAQHNPI.js → chunk-UKGNHZS4.js} +1 -1
  250. package/dist/{chunk-ZN6P3KOJ.js → chunk-UN6NY2E6.js} +3 -3
  251. package/dist/{chunk-WQSGVRFU.js → chunk-UY77TMKD.js} +31 -44
  252. package/dist/chunk-VKATKWWR.js +1462 -0
  253. package/dist/{chunk-U5LBYS3N.js → chunk-VLJOIUHL.js} +341 -274
  254. package/dist/{chunk-CX2IIQ4R.js → chunk-W2245F6G.js} +29 -29
  255. package/dist/{chunk-GEGRJKKO.js → chunk-W6B7BMLO.js} +1 -1
  256. package/dist/{chunk-XHUYWVYK.js → chunk-WBNFSG6T.js} +1 -1
  257. package/dist/chunk-WIHXXF3X.js +221 -0
  258. package/dist/{chunk-7KEUL3FI.js → chunk-XF2QMKRG.js} +9 -1
  259. package/dist/{chunk-HFC3MKXA.js → chunk-Y4HPN4BC.js} +1 -0
  260. package/dist/{chunk-D43J23QX.js → chunk-YFSBFCXO.js} +1018 -42
  261. package/dist/{chunk-KKEY5MIW.js → chunk-ZS3A3QUM.js} +16 -16
  262. package/dist/{chunk-LQUWKBST.js → chunk-ZVG446DJ.js} +139 -10
  263. package/dist/component-runtime/browserOptions.js +14 -3
  264. package/dist/component-runtime/contracts.js +35 -3
  265. package/dist/component-runtime/identity/browser.js +1 -1
  266. package/dist/component-runtime/identity.js +2 -2
  267. package/dist/component-runtime/importPolicy.js +2 -2
  268. package/dist/component-runtime/mediaResolution.d.ts +1 -0
  269. package/dist/component-runtime/mediaResolution.js +11 -0
  270. package/dist/component-runtime/render.js +38 -5
  271. package/dist/component-runtime.js +118 -14
  272. package/dist/compose.js +192 -33
  273. package/dist/composition/fonts.js +64 -67
  274. package/dist/composition/graphics-plan.js +3 -2
  275. package/dist/composition/ops.js +4 -3
  276. package/dist/composition/primitive-catalog.js +3 -1
  277. package/dist/composition/projection.js +10 -3
  278. package/dist/composition/scene/budget-policy.d.ts +1 -0
  279. package/dist/composition/scene/budget-policy.js +17 -0
  280. package/dist/composition/scene/schema.json +2757 -0
  281. package/dist/composition/scene.d.ts +1 -0
  282. package/dist/composition/scene.js +275 -0
  283. package/dist/composition/validators.js +3 -2
  284. package/dist/composition-ops.js +103 -13
  285. package/dist/composition.js +12 -5
  286. package/dist/{context-4GSDBFT3.js → context-IUPQ54V4.js} +5 -4
  287. package/dist/core/render.js +54 -3
  288. package/dist/core/select.js +2 -2
  289. package/dist/core.js +6 -3
  290. package/dist/director/ai-sdk.js +3 -3
  291. package/dist/director/domain.js +2 -2
  292. package/dist/director.js +3 -3
  293. package/dist/errors.js +1 -1
  294. package/dist/mcp/adapter.js +4 -4
  295. package/dist/mcp/core.js +1 -1
  296. package/dist/mcp/curation.js +1 -1
  297. package/dist/mcp/server.js +4 -4
  298. package/dist/mcp.js +4 -4
  299. package/dist/media-model/media-kind.js +2 -0
  300. package/dist/media-model/testing.js +16 -11
  301. package/dist/media-model.js +1 -1
  302. package/dist/nle-export.js +1 -27
  303. package/dist/primitives/backgrounds.js +2 -2
  304. package/dist/primitives/captions.js +21 -11
  305. package/dist/primitives/effects.js +14 -4
  306. package/dist/primitives/graphics.json +3 -0
  307. package/dist/primitives/hero-text.js +4 -3
  308. package/dist/primitives/layouts.js +9 -2
  309. package/dist/primitives/lib/frameScale.d.ts +1 -0
  310. package/dist/primitives/lib/frameScale.js +11 -0
  311. package/dist/primitives/lib/index.js +18 -10
  312. package/dist/primitives/lib/palette.js +1 -1
  313. package/dist/primitives/lib/text/contrast.js +2 -1
  314. package/dist/primitives/lib/text/typeface.js +1 -1
  315. package/dist/primitives/lib.js +18 -10
  316. package/dist/primitives/params-required.json +3 -0
  317. package/dist/primitives/scenes.js +12 -3
  318. package/dist/primitives/text.js +5 -5
  319. package/dist/primitives/transitions.js +2 -2
  320. package/dist/primitives/ui-blocks.js +7 -6
  321. package/dist/primitives/version-map.json +5 -2
  322. package/dist/primitives.js +23 -16
  323. package/dist/render-harness/cardAssetAdmission.js +2 -2
  324. package/dist/render-harness/renderInputAssets.js +2 -2
  325. package/dist/render-harness.js +874 -124
  326. package/package.json +48 -14
  327. package/dist/_members/animate/three/drei.d.ts +0 -6
  328. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts +0 -9
  329. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts.map +0 -1
  330. package/dist/chunk-5OTQ7M43.js +0 -718
  331. package/dist/chunk-7REW2MW3.js +0 -202
  332. package/dist/chunk-CGHTMZNC.js +0 -6
  333. package/dist/chunk-KVMVYRXX.js +0 -9527
  334. package/dist/chunk-WYQX4QIK.js +0 -544
  335. /package/dist/{chunk-H5LMJKZU.js → chunk-JVDUSOYG.js} +0 -0
@@ -4,33 +4,71 @@ import {
4
4
  assetUrlKey,
5
5
  isRemoteUrl,
6
6
  renderInputAssets
7
- } from "./chunk-RFXR7ATW.js";
7
+ } from "./chunk-MN6D3U5N.js";
8
8
  import {
9
9
  assertCardHtmlAssetFree
10
- } from "./chunk-IJ7PVJTK.js";
11
- import "./chunk-WQSGVRFU.js";
10
+ } from "./chunk-ODUWCQI3.js";
11
+ import "./chunk-UY77TMKD.js";
12
+ import "./chunk-BVA3537Z.js";
12
13
  import {
14
+ COMPONENT_STILL_RUNTIME_IDENTITY,
15
+ componentStillDependencyIdentity,
16
+ componentStillRasterAffectingFlags,
17
+ createComponentStillSession,
13
18
  importFromRenderEntry,
14
- resolveRenderEntryRoot
15
- } from "./chunk-5OTQ7M43.js";
19
+ readMaterializedComponentSource,
20
+ resolveRenderEntryRoot,
21
+ verifyLocalStagedBrowser
22
+ } from "./chunk-DQLYWNLC.js";
16
23
  import "./chunk-WB2VFDQZ.js";
17
24
  import {
18
- COMPONENT_CHROMIUM_OPTIONS
19
- } from "./chunk-CGHTMZNC.js";
20
- import "./chunk-M2TLRXEO.js";
21
- import "./chunk-DHKQ47Q6.js";
22
- import "./chunk-RETQFTGY.js";
23
- import "./chunk-LQUWKBST.js";
24
- import "./chunk-C5SEPOWD.js";
25
+ sourceVersionId
26
+ } from "./chunk-EXY4JJPH.js";
27
+ import "./chunk-DAARYRNT.js";
28
+ import "./chunk-A74FZCPY.js";
29
+ import {
30
+ componentBrowserBackend
31
+ } from "./chunk-WIHXXF3X.js";
32
+ import "./chunk-ZVG446DJ.js";
33
+ import {
34
+ generatedStudioPreparationFactsV1,
35
+ scenePresetBuilderDescriptorV1
36
+ } from "./chunk-VKATKWWR.js";
37
+ import "./chunk-7AZLFN26.js";
38
+ import {
39
+ SCENE_SHOT_PREPARATION_STAGE,
40
+ createSceneBuilderDescriptorRegistryV1,
41
+ parseSceneComponentCaptureIntentV1,
42
+ prepareSceneShotRenderInput,
43
+ readSceneShotManifest
44
+ } from "./chunk-YFSBFCXO.js";
45
+ import "./chunk-QH3YI3ND.js";
46
+ import "./chunk-QISFYLBB.js";
47
+ import "./chunk-L2AHS3AW.js";
48
+ import "./chunk-VZ7TYX6Z.js";
49
+ import "./chunk-DENF4TPI.js";
50
+ import "./chunk-KYRDKK2D.js";
51
+ import "./chunk-WREYUH2E.js";
52
+ import {
53
+ CueframeError
54
+ } from "./chunk-J3DIUG24.js";
25
55
  import "./chunk-7PA7FGLD.js";
26
- import "./chunk-4FOOBSEE.js";
56
+ import "./chunk-TARKDVP6.js";
57
+ import {
58
+ evaluateScene,
59
+ parseSceneShotSpecV2,
60
+ photographicSceneRigFactsV1,
61
+ sceneCameraPlanesV2
62
+ } from "./chunk-MH3UPKWR.js";
63
+ import "./chunk-2L7PYYJK.js";
27
64
  import "./chunk-2ESYSVXG.js";
28
65
 
29
66
  // ../execution/render-harness/src/materializeSources.ts
30
- import { join as join4, basename } from "path";
31
- import { mkdir, copyFile } from "fs/promises";
67
+ import { join as join5, basename } from "path";
68
+ import { createHash as createHash4 } from "crypto";
69
+ import { mkdir, copyFile, readFile as readFile3 } from "fs/promises";
32
70
  import { createWriteStream, existsSync as existsSync4 } from "fs";
33
- import { fileURLToPath } from "url";
71
+ import { fileURLToPath as fileURLToPath3 } from "url";
34
72
  import { Readable } from "stream";
35
73
  import { pipeline } from "stream/promises";
36
74
 
@@ -117,6 +155,7 @@ import { tmpdir } from "os";
117
155
  import { rm } from "fs/promises";
118
156
  var exec = promisify(execFile);
119
157
  async function extractSegments(clips, sourceFiles, opts) {
158
+ opts?.signal?.throwIfAborted();
120
159
  const padding = opts?.padding ?? 1;
121
160
  const dir = mkdtempSync(join2(tmpdir(), "cueframe-segments-"));
122
161
  const segments = {};
@@ -129,6 +168,10 @@ async function extractSegments(clips, sourceFiles, opts) {
129
168
  clipsBySource.set(clip.poolItemId, list);
130
169
  }
131
170
  for (const [poolItemId, sourceClips] of clipsBySource) {
171
+ if (opts?.signal?.aborted) {
172
+ await rm(dir, { recursive: true, force: true });
173
+ opts.signal.throwIfAborted();
174
+ }
132
175
  const sourcePath = sourceFiles[poolItemId];
133
176
  const remote = /^https?:\/\//i.test(sourcePath);
134
177
  if (!remote && !existsSync2(sourcePath)) {
@@ -153,11 +196,15 @@ async function extractSegments(clips, sourceFiles, opts) {
153
196
  "-movflags",
154
197
  "+faststart",
155
198
  segmentPath
156
- ], { timeout: remote ? 12e4 : 6e4 });
199
+ ], { timeout: remote ? 12e4 : 6e4, signal: opts?.signal });
157
200
  segments[poolItemId] = segmentPath;
158
201
  origins[poolItemId] = minStart;
159
202
  console.log(`[extractSegments] ${poolItemId}: ${minStart.toFixed(1)}s-${maxEnd.toFixed(1)}s \u2192 ${segmentPath}`);
160
203
  } catch (err) {
204
+ if (opts?.signal?.aborted) {
205
+ await rm(dir, { recursive: true, force: true });
206
+ throw err;
207
+ }
161
208
  console.error(`[extractSegments] Failed for ${poolItemId}:`, err);
162
209
  if (!remote) {
163
210
  segments[poolItemId] = sourcePath;
@@ -180,26 +227,37 @@ async function extractSegments(clips, sourceFiles, opts) {
180
227
  import { existsSync as existsSync3 } from "fs";
181
228
  import { join as join3, extname as extname2 } from "path";
182
229
  import { createHash } from "crypto";
183
- async function resolveAssets(renderInput, tempDir, mediaServerUrl, download) {
230
+ async function resolveAssets(renderInput, tempDir, mediaServerUrl, download, signal) {
184
231
  const urlMap = {};
185
232
  const seen = /* @__PURE__ */ new Set();
186
233
  async function resolve(url) {
234
+ signal?.throwIfAborted();
187
235
  if (!url) return url;
188
- if (!isRemoteUrl(url)) return url;
236
+ const embedded = /^data:([^;,]+);base64,/.exec(url);
237
+ if (!isRemoteUrl(url) && !embedded) return url;
189
238
  if (seen.has(url)) return urlMap[url] ?? url;
190
239
  seen.add(url);
191
240
  const hash = createHash("md5").update(url).digest("hex").slice(0, 12);
192
- const ext = extname2(new URL(url).pathname) || ".bin";
241
+ const embeddedExtension = {
242
+ "audio/mp4": ".m4a",
243
+ "audio/mpeg": ".mp3",
244
+ "audio/wav": ".wav",
245
+ "image/png": ".png",
246
+ "image/jpeg": ".jpg",
247
+ "image/webp": ".webp",
248
+ "image/svg+xml": ".svg"
249
+ };
250
+ const ext = embedded ? embeddedExtension[embedded[1]] : extname2(new URL(url).pathname);
251
+ if (!ext) throw new Error(`Unsupported embedded render asset MIME '${embedded?.[1] ?? "unknown"}'.`);
193
252
  const filename = `asset_${hash}${ext}`;
194
- const localPath = join3(tempDir, filename);
195
- if (!existsSync3(localPath)) {
253
+ const localPath2 = join3(tempDir, filename);
254
+ if (!existsSync3(localPath2)) {
196
255
  try {
197
- await download(url, localPath);
256
+ await download(url, localPath2, signal);
198
257
  } catch (err) {
199
- throw new Error(
200
- `Failed to materialize required render asset ${new URL(url).origin}${new URL(url).pathname}`,
201
- { cause: err }
202
- );
258
+ if (signal?.aborted) throw err;
259
+ const label = embedded ? `embedded ${embedded[1]} asset` : `${new URL(url).origin}${new URL(url).pathname}`;
260
+ throw new Error(`Failed to materialize required render asset ${label}`, { cause: err });
203
261
  }
204
262
  }
205
263
  const localUrl = `${mediaServerUrl}/${filename}`;
@@ -232,11 +290,616 @@ async function resolveAssets(renderInput, tempDir, mediaServerUrl, download) {
232
290
  }
233
291
 
234
292
  // ../execution/render-harness/src/materializeSources.ts
293
+ import sharp2 from "sharp";
294
+
295
+ // ../execution/render-harness/src/sceneShotAssets.ts
296
+ import { readFile } from "fs/promises";
297
+ import { createHash as createHash2 } from "crypto";
298
+ import { join as join4 } from "path";
299
+ import { fileURLToPath } from "url";
300
+
301
+ // ../execution/render-harness/src/imageHeader.ts
302
+ var PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
303
+ function ascii(bytes, offset, length) {
304
+ let out = "";
305
+ for (let i = 0; i < length; i++) out += String.fromCharCode(bytes[offset + i]);
306
+ return out;
307
+ }
308
+ function u16be(bytes, offset) {
309
+ return bytes[offset] << 8 | bytes[offset + 1];
310
+ }
311
+ function u32be(bytes, offset) {
312
+ return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
313
+ }
314
+ function u16le(bytes, offset) {
315
+ return bytes[offset] | bytes[offset + 1] << 8;
316
+ }
317
+ function u24le(bytes, offset) {
318
+ return bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16;
319
+ }
320
+ function u32le(bytes, offset) {
321
+ return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;
322
+ }
323
+ function png(bytes) {
324
+ if (bytes.length < 24) return null;
325
+ for (let i = 0; i < PNG_SIGNATURE.length; i++) if (bytes[i] !== PNG_SIGNATURE[i]) return null;
326
+ if (u32be(bytes, 8) !== 13 || ascii(bytes, 12, 4) !== "IHDR") return null;
327
+ const width = u32be(bytes, 16);
328
+ const height = u32be(bytes, 20);
329
+ if (width === 0 || height === 0) return null;
330
+ return { mimeType: "image/png", width, height };
331
+ }
332
+ function isStartOfFrame(code) {
333
+ return code >= 192 && code <= 195 || code >= 197 && code <= 199 || code >= 201 && code <= 203 || code >= 205 && code <= 207;
334
+ }
335
+ function jpeg(bytes) {
336
+ if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216) return null;
337
+ let offset = 2;
338
+ while (offset + 4 <= bytes.length) {
339
+ if (bytes[offset] !== 255) return null;
340
+ let code = bytes[offset + 1];
341
+ while (code === 255 && offset + 2 < bytes.length) {
342
+ offset += 1;
343
+ code = bytes[offset + 1];
344
+ }
345
+ offset += 2;
346
+ if (code === 216 || code >= 208 && code <= 215 || code === 1) continue;
347
+ if (code === 217 || code === 218) return null;
348
+ if (offset + 2 > bytes.length) return null;
349
+ const length = u16be(bytes, offset);
350
+ if (length < 2) return null;
351
+ if (isStartOfFrame(code)) {
352
+ if (offset + 7 > bytes.length) return null;
353
+ const height = u16be(bytes, offset + 3);
354
+ const width = u16be(bytes, offset + 5);
355
+ if (width === 0 || height === 0) return null;
356
+ return { mimeType: "image/jpeg", width, height };
357
+ }
358
+ offset += length;
359
+ }
360
+ return null;
361
+ }
362
+ function webp(bytes) {
363
+ if (bytes.length < 30 || ascii(bytes, 0, 4) !== "RIFF" || ascii(bytes, 8, 4) !== "WEBP") return null;
364
+ const chunk = ascii(bytes, 12, 4);
365
+ const size = u32le(bytes, 16);
366
+ const data = 20;
367
+ if (chunk === "VP8 ") {
368
+ if (size < 10 || data + 10 > bytes.length) return null;
369
+ if (bytes[data + 3] !== 157 || bytes[data + 4] !== 1 || bytes[data + 5] !== 42) return null;
370
+ const width = u16le(bytes, data + 6) & 16383;
371
+ const height = u16le(bytes, data + 8) & 16383;
372
+ if (width === 0 || height === 0) return null;
373
+ return { mimeType: "image/webp", width, height };
374
+ }
375
+ if (chunk === "VP8L") {
376
+ if (size < 5 || data + 5 > bytes.length || bytes[data] !== 47) return null;
377
+ const bits = u32le(bytes, data + 1);
378
+ return { mimeType: "image/webp", width: (bits & 16383) + 1, height: (bits >>> 14 & 16383) + 1 };
379
+ }
380
+ if (chunk === "VP8X") {
381
+ if (size < 10 || data + 10 > bytes.length) return null;
382
+ return { mimeType: "image/webp", width: u24le(bytes, data + 4) + 1, height: u24le(bytes, data + 7) + 1 };
383
+ }
384
+ return null;
385
+ }
386
+ function readImageHeader(bytes) {
387
+ return png(bytes) ?? jpeg(bytes) ?? webp(bytes);
388
+ }
389
+
390
+ // ../execution/render-harness/src/sceneShotAssets.ts
391
+ function localHandleReader(opts) {
392
+ return async (handle) => {
393
+ if (opts.baseUrl && opts.workDir && handle.startsWith(`${opts.baseUrl}/`)) {
394
+ const name = decodeURIComponent(handle.slice(opts.baseUrl.length + 1).split("?")[0]);
395
+ return readFile(join4(opts.workDir, name));
396
+ }
397
+ if (handle.startsWith("file://")) return readFile(fileURLToPath(handle));
398
+ if (handle.startsWith("/")) return readFile(handle);
399
+ let url;
400
+ try {
401
+ url = new URL(handle);
402
+ } catch {
403
+ throw new Error(`handle "${handle}" is not a readable local asset`);
404
+ }
405
+ if ((url.protocol === "http:" || url.protocol === "https:") && ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname)) {
406
+ const response = await fetch(handle);
407
+ if (!response.ok) throw new Error(`loopback fetch ${response.status} for ${handle}`);
408
+ return new Uint8Array(await response.arrayBuffer());
409
+ }
410
+ throw new Error(`handle "${handle}" is not a readable local asset`);
411
+ };
412
+ }
413
+ async function verifySceneShotAssetBytes(renderInput, read) {
414
+ for (const overlay of renderInput.overlays ?? []) {
415
+ if (overlay.template !== "component" || !overlay.sceneShot) continue;
416
+ const context = { stage: SCENE_SHOT_PREPARATION_STAGE, clipId: overlay.id, componentId: overlay.componentId };
417
+ for (const surface of overlay.sceneShot.plan.surfaces) {
418
+ if (surface.realized.source === "color") continue;
419
+ const slot = surface.slot;
420
+ const binding = surface.realized.source === "video" ? surface.realized.video : surface.realized.image;
421
+ const path = surface.path;
422
+ const handle = binding.handle;
423
+ if (typeof handle !== "string" || handle.length === 0) {
424
+ throw new CueframeError(
425
+ "component_asset_unavailable",
426
+ `Scene-shot preparation refused for clip '${overlay.id}': slot "${slot}" (at ${path}) has no bound screenshot handle after materialization.`,
427
+ void 0,
428
+ { ...context, path, slot }
429
+ );
430
+ }
431
+ let bytes;
432
+ try {
433
+ bytes = await read(handle);
434
+ } catch (error) {
435
+ throw new CueframeError(
436
+ "component_asset_unavailable",
437
+ `Scene-shot preparation refused for clip '${overlay.id}': slot "${slot}" (at ${path}) could not be read for verification: ${error instanceof Error ? error.message : String(error)}.`,
438
+ void 0,
439
+ { ...context, path, slot }
440
+ );
441
+ }
442
+ if (surface.realized.source === "video") {
443
+ const digest2 = createHash2("sha256").update(bytes).digest("hex");
444
+ if (bytes.byteLength !== surface.realized.video.byteLength || digest2 !== surface.realized.video.encodedSha256) throw new CueframeError("component_asset_integrity_failed", `Scene-shot preparation refused for clip '${overlay.id}': video slot "${slot}" (at ${path}) changed after PTS admission.`, void 0, { ...context, path, slot });
445
+ continue;
446
+ }
447
+ const header = readImageHeader(bytes);
448
+ if (!header) {
449
+ throw new CueframeError(
450
+ "component_asset_integrity_failed",
451
+ `Scene-shot preparation refused for clip '${overlay.id}': slot "${slot}" (at ${path}) is not an admitted image format; the bytes are not PNG, JPEG or WebP. GIF, SVG and video need an explicit conversion.`,
452
+ void 0,
453
+ { ...context, path, slot }
454
+ );
455
+ }
456
+ if (header.mimeType !== binding.mimeType) {
457
+ throw new CueframeError(
458
+ "component_asset_integrity_failed",
459
+ `Scene-shot preparation refused for clip '${overlay.id}': slot "${slot}" (at ${path}) was admitted as ${binding.mimeType} but its bytes are ${header.mimeType}.`,
460
+ void 0,
461
+ { ...context, path, slot, admitted: binding.mimeType, actual: header.mimeType }
462
+ );
463
+ }
464
+ if (header.width !== binding.width || header.height !== binding.height) {
465
+ throw new CueframeError(
466
+ "component_asset_integrity_failed",
467
+ `Scene-shot preparation refused for clip '${overlay.id}': slot "${slot}" (at ${path}) was admitted at ${binding.width}x${binding.height} but decodes to ${header.width}x${header.height}.`,
468
+ void 0,
469
+ { ...context, path, slot, admitted: `${binding.width}x${binding.height}`, actual: `${header.width}x${header.height}` }
470
+ );
471
+ }
472
+ }
473
+ }
474
+ }
475
+
476
+ // ../execution/render-harness/src/nodeScenePreparation.ts
477
+ import { createHash as createHash3 } from "crypto";
478
+ import { execFile as execFile2 } from "child_process";
479
+ import { promisify as promisify2 } from "util";
480
+ import { readFile as readFile2 } from "fs/promises";
481
+ import { fileURLToPath as fileURLToPath2 } from "url";
482
+ import sharp from "sharp";
483
+ function localPath(handle) {
484
+ if (handle.startsWith("file://")) return fileURLToPath2(handle);
485
+ if (handle.startsWith("/")) return handle;
486
+ throw new Error(`scene_component_asset_not_localized: ${handle}`);
487
+ }
488
+ async function digest(handle) {
489
+ let bytes;
490
+ if (/^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::\d+)?\//.test(handle)) {
491
+ const response = await fetch(handle);
492
+ if (!response.ok) throw new Error(`scene_component_asset_not_localized: loopback handle returned ${response.status}.`);
493
+ bytes = Buffer.from(await response.arrayBuffer());
494
+ } else {
495
+ bytes = await readFile2(localPath(handle));
496
+ }
497
+ return { bytes, sha256: createHash3("sha256").update(bytes).digest("hex") };
498
+ }
499
+ function matchingRow(input, componentId, sourceVersionId2) {
500
+ const rows = Object.values(input.componentSources ?? {}).filter(
501
+ (row) => row.source.componentId === componentId && row.sourceVersionId === sourceVersionId2
502
+ );
503
+ if (rows.length === 0) throw new Error(`scene_component_facts_missing: expected a pinned row for ${componentId}@${sourceVersionId2}.`);
504
+ const canonical = (row) => JSON.stringify({ source: row.source, assets: row.assets });
505
+ if (rows.some((row) => canonical(row) !== canonical(rows[0]))) {
506
+ throw new Error(`scene_component_facts_conflict: conflicting pinned rows for ${componentId}@${sourceVersionId2}.`);
507
+ }
508
+ return rows[0];
509
+ }
510
+ function selectNestedComponentRowV1(input, overlayId, path, componentId, sourceVersionId2, selections) {
511
+ const selectedKey = selections?.[overlayId]?.[path];
512
+ if (selectedKey) {
513
+ const selected = input.componentSources?.[selectedKey];
514
+ if (!selected || selected.source.componentId !== componentId || selected.sourceVersionId !== sourceVersionId2) throw new Error(`scene_component_facts_missing: selected row ${selectedKey} does not pin ${componentId}@${sourceVersionId2} for ${overlayId}:${path}.`);
515
+ return selected;
516
+ }
517
+ const candidates = Object.values(input.componentSources ?? {}).filter((row) => row.source.componentId === componentId && row.sourceVersionId === sourceVersionId2);
518
+ if (!candidates.length) throw new Error(`scene_component_facts_missing: no pinned row for ${componentId}@${sourceVersionId2} at ${overlayId}:${path}.`);
519
+ const assetless = candidates.every((row) => Object.keys(row.assets).length === 0 && Object.keys(row.source.manifest?.assets ?? {}).length === 0);
520
+ if (!assetless) throw new Error(`scene_component_asset_binding_required: ${overlayId}:${path} requires an explicit nested component row selection.`);
521
+ return matchingRow(input, componentId, sourceVersionId2);
522
+ }
523
+ async function stableAssetFacts(row) {
524
+ return Object.fromEntries(await Promise.all(Object.entries(row.assets).sort(([a], [b]) => a.localeCompare(b)).map(async ([slot, asset]) => {
525
+ const content = await digest(asset.handle);
526
+ if (asset.kind === "image") {
527
+ const metadata = await sharp(content.bytes).metadata();
528
+ const mime = metadata.format === "png" ? "image/png" : metadata.format === "jpeg" ? "image/jpeg" : metadata.format === "webp" ? "image/webp" : null;
529
+ if (mime !== asset.mimeType || metadata.width !== asset.width || metadata.height !== asset.height) {
530
+ throw new Error(`scene_component_asset_integrity_failed: pinned image ${slot} disagrees with decoded bytes.`);
531
+ }
532
+ }
533
+ return [slot, {
534
+ kind: asset.kind,
535
+ mimeType: asset.mimeType,
536
+ width: asset.width ?? null,
537
+ height: asset.height ?? null,
538
+ durationSec: asset.durationSec ?? null,
539
+ byteLength: content.bytes.byteLength,
540
+ encodedSha256: content.sha256
541
+ }];
542
+ })));
543
+ }
544
+ function componentBindings(objects, prefix = "layers") {
545
+ const found = [];
546
+ objects.forEach((object, index) => {
547
+ const path = `${prefix}.${index}`;
548
+ if (object.kind === "group") found.push(...componentBindings(object.children, `${path}.children`));
549
+ for (const [slot, binding] of Object.entries("surfaces" in object ? object.surfaces ?? {} : {})) {
550
+ if (binding.source === "component") found.push({ path: `${path}.surfaces.${slot}`, binding });
551
+ }
552
+ });
553
+ return found;
554
+ }
555
+ var execFileAsync = promisify2(execFile2);
556
+ async function nodeVideoPresentationFactsV1(handle, ffprobeExecutable = "ffprobe", signal) {
557
+ let raw;
558
+ try {
559
+ const source = /^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::\d+)?\//.test(handle) ? handle : localPath(handle);
560
+ raw = (await execFileAsync(ffprobeExecutable, ["-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height,time_base:frame=best_effort_timestamp", "-show_frames", "-of", "json", source], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024, timeout: 3e4, signal })).stdout;
561
+ } catch (error) {
562
+ throw new Error(`video_presentation_index_missing: ffprobe could not verify presentation timestamps. Render or transcode this asset to CFR with the existing media tools, then prepare the scene again.`, { cause: error });
563
+ }
564
+ const probe = JSON.parse(raw);
565
+ const stream = probe.streams?.[0];
566
+ const parts = stream?.time_base?.split("/").map(Number);
567
+ const pts = probe.frames?.map((frame) => Number(frame.best_effort_timestamp));
568
+ if (!stream || !parts || parts.length !== 2 || !pts || pts.some((value) => !Number.isSafeInteger(value))) throw new Error("video_presentation_index_missing: ffprobe returned no exact presentation-frame index. Render or transcode this asset to CFR with the existing media tools, then prepare the scene again.");
569
+ return { pts, timeBase: { num: parts[0], den: parts[1] }, width: stream.width, height: stream.height };
570
+ }
571
+ function nodePhotographicRigFactsV1(scene, width, height) {
572
+ if (scene.environment.kind !== "photographic-studio-v1") return null;
573
+ const facts = photographicSceneRigFactsV1(height / scene.referenceSize.height, width, height);
574
+ return { identity: JSON.parse(JSON.stringify(facts.identity)), allocations: facts.allocations.map((row) => ({ ...row })) };
575
+ }
576
+ function nodeCameraClipPlanesV1(scene, frame, durationInFrames, outputHeight) {
577
+ const scale = outputHeight / scene.referenceSize.height;
578
+ return sceneCameraPlanesV2(scene.referenceSize.height, evaluateScene(scene, frame, durationInFrames).camera.fov, scale);
579
+ }
580
+ function createNodeScenePreparationV1(options) {
581
+ const canonical = (value) => JSON.parse(JSON.stringify(value ?? {}));
582
+ const provider = createMaterializedSceneCaptureProvider({
583
+ workspace: options.workspace,
584
+ workspaceForSource: options.workspaceForSource,
585
+ renderEntryRoot: options.renderEntryRoot,
586
+ allowedAssetOrigins: options.allowedAssetOrigins,
587
+ publishVerifiedPng: options.publishVerifiedPng,
588
+ async resolveAssets(intent) {
589
+ const candidates = Object.values(options.input.componentSources ?? {}).filter((row2) => row2.source.componentId === intent.componentId && row2.sourceVersionId === intent.sourceVersionId);
590
+ const matching = [];
591
+ for (const candidate of candidates) if (JSON.stringify(await stableAssetFacts(candidate)) === JSON.stringify(intent.assetBindings)) matching.push(candidate);
592
+ if (!matching.length) throw new Error(`scene_component_asset_integrity_failed: no localized row matches the sealed asset facts for ${intent.componentId}@${intent.sourceVersionId}.`);
593
+ const row = matching[0];
594
+ return Object.fromEntries(Object.entries(row.assets).map(([slot, asset]) => [slot, asset.handle]));
595
+ }
596
+ });
597
+ const outputHeight = options.input.outputHeight ?? options.input.height;
598
+ const descriptors = createSceneBuilderDescriptorRegistryV1((object, context) => {
599
+ if (object.kind === "group" || object.kind === "text" && object.space === "screen") return null;
600
+ return scenePresetBuilderDescriptorV1(object, context);
601
+ });
602
+ const dependencies = {
603
+ descriptors,
604
+ async resolveComponentFacts(scene, { overlay }) {
605
+ const facts = {};
606
+ for (const { path, binding } of componentBindings(scene.layers)) {
607
+ const row = selectNestedComponentRowV1(options.input, overlay.id, path, binding.component.componentId, binding.component.sourceVersionId, options.nestedComponentRowKeys);
608
+ const execution = await provider.resolveExecutionFacts(binding.component);
609
+ const assets = await stableAssetFacts(row);
610
+ facts[path] = {
611
+ durationInFrames: overlay.durationInFrames,
612
+ seed: `${binding.component.componentId}:${binding.component.sourceVersionId}`,
613
+ params: binding.params ?? {},
614
+ assetBindings: assets,
615
+ brandFacts: canonical(options.input.brandKit),
616
+ fontFacts: canonical(options.input.brandKit?.fontAssets ?? []),
617
+ mediaFacts: assets,
618
+ ...execution
619
+ };
620
+ }
621
+ return facts;
622
+ },
623
+ resolveRigFacts(scene, bounds) {
624
+ const width = options.input.outputWidth ?? options.input.width;
625
+ if (scene.environment.kind !== "photographic-studio-v1") return generatedStudioPreparationFactsV1(scene.environment, outputHeight / scene.referenceSize.height, bounds, width, outputHeight);
626
+ return nodePhotographicRigFactsV1(scene, width, outputHeight);
627
+ },
628
+ resolveCameraClipPlanes(scene, frame, durationInFrames) {
629
+ return nodeCameraClipPlanesV1(scene, frame, durationInFrames, outputHeight);
630
+ },
631
+ realization: {
632
+ capture: provider,
633
+ async sha256(value) {
634
+ return createHash3("sha256").update(value).digest("hex");
635
+ },
636
+ async resolveImage() {
637
+ return null;
638
+ },
639
+ async resolveVideo() {
640
+ return null;
641
+ },
642
+ signal: options.signal
643
+ },
644
+ realizationForOverlay({ input, overlay }) {
645
+ const row = input.componentSources?.[overlay.id];
646
+ if (!row) throw new Error(`scene_component_facts_missing: no pinned row for clip ${overlay.id}.`);
647
+ return {
648
+ capture: provider,
649
+ async sha256(value) {
650
+ return createHash3("sha256").update(value).digest("hex");
651
+ },
652
+ async resolveImage(binding) {
653
+ const asset = row.assets[binding.assetSlot];
654
+ if (!asset || !["image/png", "image/jpeg", "image/webp"].includes(asset.mimeType)) return null;
655
+ const encoded = await digest(asset.handle);
656
+ const image = sharp(encoded.bytes);
657
+ const metadata = await image.metadata();
658
+ const actualMime = metadata.format === "png" ? "image/png" : metadata.format === "jpeg" ? "image/jpeg" : metadata.format === "webp" ? "image/webp" : null;
659
+ if (actualMime !== asset.mimeType || metadata.width !== asset.width || metadata.height !== asset.height) {
660
+ throw new Error(`scene_image_facts_missing: clip ${overlay.id} slot ${binding.assetSlot} disagrees with decoded bytes.`);
661
+ }
662
+ const decoded = await image.ensureAlpha().raw().toBuffer({ resolveWithObject: true });
663
+ return { image: {
664
+ handle: asset.handle,
665
+ mimeType: actualMime,
666
+ byteLength: encoded.bytes.byteLength,
667
+ width: decoded.info.width,
668
+ height: decoded.info.height,
669
+ decodedSha256: createHash3("sha256").update(decoded.data).digest("hex")
670
+ }, release: async () => {
671
+ } };
672
+ },
673
+ signal: options.signal,
674
+ async resolveVideo(binding, _path, signal) {
675
+ const asset = row.assets[binding.mediaId];
676
+ if (!asset || asset.kind !== "video" || !["video/mp4", "video/webm"].includes(asset.mimeType)) return null;
677
+ const encoded = await digest(asset.handle);
678
+ const probe = await nodeVideoPresentationFactsV1(asset.handle, options.ffprobeExecutable, signal);
679
+ if (probe.width !== asset.width || probe.height !== asset.height) throw new Error(`scene_video_facts_missing: clip ${overlay.id} media ${binding.mediaId} disagrees with decoded dimensions.`);
680
+ return { video: { handle: asset.handle, mimeType: asset.mimeType, byteLength: encoded.bytes.byteLength, width: probe.width, height: probe.height, encodedSha256: encoded.sha256, presentationIndex: { pts: probe.pts, timeBase: probe.timeBase } }, release: async () => {
681
+ } };
682
+ }
683
+ };
684
+ }
685
+ };
686
+ return { dependencies, close: () => provider.close() };
687
+ }
688
+
689
+ // ../execution/render-harness/src/materializeSources.ts
690
+ function materializedCaptureFilename(png2, encoded) {
691
+ const encodedSha256 = createHash4("sha256").update(encoded).digest("hex");
692
+ return `scene-capture-${png2.decodedSha256}-${encodedSha256}.png`;
693
+ }
694
+ async function verifyDecodedComponentStill(png2, expected) {
695
+ const bytes = await localHandleReader({})(png2.handle);
696
+ const encodedSha256 = createHash4("sha256").update(bytes).digest("hex");
697
+ if (bytes.byteLength !== png2.byteLength || encodedSha256 !== png2.encodedSha256) {
698
+ throw new Error("scene_component_capture_integrity_failed: captured PNG bytes changed before decode.");
699
+ }
700
+ let decoded;
701
+ try {
702
+ decoded = await sharp2(bytes).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
703
+ } catch (error) {
704
+ throw new Error(
705
+ `scene_component_capture_decode_failed: ${error instanceof Error ? error.message : String(error)}`
706
+ );
707
+ }
708
+ const { width, height } = decoded.info;
709
+ if (width !== png2.width || height !== png2.height || width !== expected.width || height !== expected.height) {
710
+ throw new Error(
711
+ `scene_component_capture_dimensions_mismatch: expected ${expected.width}x${expected.height}, runtime reported ${png2.width}x${png2.height}, decoded ${width}x${height}.`
712
+ );
713
+ }
714
+ return {
715
+ handle: png2.handle,
716
+ mimeType: "image/png",
717
+ byteLength: bytes.byteLength,
718
+ width,
719
+ height,
720
+ decodedSha256: createHash4("sha256").update(decoded.data).digest("hex")
721
+ };
722
+ }
723
+ function abortError() {
724
+ const error = new Error("scene_component_capture_cancelled");
725
+ error.name = "AbortError";
726
+ return error;
727
+ }
728
+ function throwIfAborted(signal) {
729
+ if (signal?.aborted) throw abortError();
730
+ }
731
+ function captureSessionKey(intent) {
732
+ return JSON.stringify({
733
+ componentId: intent.componentId,
734
+ sourceVersionId: intent.sourceVersionId,
735
+ layoutWidth: intent.layoutWidth,
736
+ layoutHeight: intent.layoutHeight,
737
+ bakeScale: intent.bakeScale,
738
+ durationInFrames: intent.durationInFrames,
739
+ fps: intent.fps,
740
+ requestedGlBackend: intent.requestedGlBackend,
741
+ runtimeIdentity: intent.runtimeIdentity,
742
+ dependencyIdentity: intent.dependencyIdentity,
743
+ rasterAffectingFlags: intent.rasterAffectingFlags
744
+ });
745
+ }
746
+ function stableJson(value) {
747
+ if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
748
+ if (value !== null && typeof value === "object") {
749
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(",")}}`;
750
+ }
751
+ return JSON.stringify(value);
752
+ }
753
+ function createMaterializedSceneCaptureProvider(options) {
754
+ const sessions = /* @__PURE__ */ new Map();
755
+ const captures = /* @__PURE__ */ new Map();
756
+ const createSession = options.createSession ?? createComponentStillSession;
757
+ const resolveDependencyIdentity = options.resolveDependencyIdentity ?? componentStillDependencyIdentity;
758
+ let closed = false;
759
+ let closePromise = null;
760
+ const source = (componentId, expectedSourceVersionId) => {
761
+ const workspace = options.workspaceForSource?.(componentId, expectedSourceVersionId) ?? options.workspace;
762
+ const materialized = readMaterializedComponentSource(workspace, componentId);
763
+ if (!materialized) throw new Error(`scene_component_source_unavailable: ${componentId}`);
764
+ const actualSourceVersionId = sourceVersionId(materialized);
765
+ if (expectedSourceVersionId !== actualSourceVersionId) {
766
+ throw new Error(
767
+ `scene_component_source_pin_mismatch: ${componentId} expected ${expectedSourceVersionId}, actual ${actualSourceVersionId}`
768
+ );
769
+ }
770
+ return { materialized, actualSourceVersionId, workspace };
771
+ };
772
+ const resolveExecutionFacts = async (request, signal) => {
773
+ throwIfAborted(signal);
774
+ const { materialized } = source(request.componentId, request.sourceVersionId);
775
+ const graphics = materialized.manifest.graphics;
776
+ const renderEntryRoot = resolveRenderEntryRoot(options.renderEntryRoot);
777
+ const dependencyIdentity = await resolveDependencyIdentity(
778
+ renderEntryRoot
779
+ );
780
+ throwIfAborted(signal);
781
+ return {
782
+ runtimeIdentity: COMPONENT_STILL_RUNTIME_IDENTITY,
783
+ dependencyIdentity,
784
+ requestedGlBackend: componentBrowserBackend(graphics).chromiumOptions.gl,
785
+ rasterAffectingFlags: componentStillRasterAffectingFlags(graphics)
786
+ };
787
+ };
788
+ const provider = {
789
+ resolveExecutionFacts,
790
+ async openSession(rawIntent, signal) {
791
+ if (closed) throw new Error("scene_component_capture_provider_closed");
792
+ throwIfAborted(signal);
793
+ const intent = parseSceneComponentCaptureIntentV1(rawIntent);
794
+ if (intent.params === null || Array.isArray(intent.params) || typeof intent.params !== "object") {
795
+ throw new Error("scene_component_params_invalid: params must be an object.");
796
+ }
797
+ const execution = await resolveExecutionFacts(intent, signal);
798
+ if (closed) throw new Error("scene_component_capture_provider_closed");
799
+ for (const field of ["runtimeIdentity", "dependencyIdentity", "requestedGlBackend", "rasterAffectingFlags"]) {
800
+ if (stableJson(intent[field]) !== stableJson(execution[field])) {
801
+ throw new Error(`scene_component_execution_fact_mismatch: ${field}`);
802
+ }
803
+ }
804
+ const { materialized, workspace } = source(intent.componentId, intent.sourceVersionId);
805
+ const key = captureSessionKey(intent);
806
+ let opened = sessions.get(key);
807
+ if (!opened) {
808
+ opened = (async () => {
809
+ const session = await createSession({
810
+ ws: workspace,
811
+ id: intent.componentId,
812
+ params: intent.params,
813
+ assets: await options.resolveAssets(intent),
814
+ seed: intent.seed,
815
+ graphics: materialized.manifest.graphics,
816
+ width: intent.layoutWidth,
817
+ height: intent.layoutHeight,
818
+ scale: intent.bakeScale,
819
+ fps: intent.fps.num / intent.fps.den,
820
+ durationInFrames: intent.durationInFrames,
821
+ revision: intent.sourceVersionId,
822
+ renderEntryRoot: options.renderEntryRoot,
823
+ allowedAssetOrigins: options.allowedAssetOrigins,
824
+ captureAttestation: true
825
+ });
826
+ return session;
827
+ })();
828
+ sessions.set(key, opened);
829
+ void opened.catch(() => sessions.delete(key));
830
+ }
831
+ const runtimeSession = await opened;
832
+ throwIfAborted(signal);
833
+ return {
834
+ async capture(nextRaw, captureSignal) {
835
+ if (closed) throw new Error("scene_component_capture_provider_closed");
836
+ throwIfAborted(captureSignal);
837
+ const next = parseSceneComponentCaptureIntentV1(nextRaw);
838
+ if (captureSessionKey(next) !== key) {
839
+ throw new Error("scene_component_capture_session_mismatch");
840
+ }
841
+ const captureKey = stableJson(next);
842
+ let pending = captures.get(captureKey);
843
+ if (!pending) {
844
+ pending = (async () => {
845
+ const rendered = await runtimeSession.renderVerifiedFrame({
846
+ frame: next.captureFrame,
847
+ params: next.params,
848
+ assets: await options.resolveAssets(next),
849
+ seed: next.seed,
850
+ expectedRevision: next.sourceVersionId
851
+ });
852
+ let png2 = await verifyDecodedComponentStill(rendered.png, {
853
+ width: next.rasterWidth,
854
+ height: next.rasterHeight
855
+ });
856
+ if (options.publishVerifiedPng) png2 = await options.publishVerifiedPng(png2);
857
+ return { attestation: rendered.attestation, png: png2, cacheScope: "session" };
858
+ })();
859
+ captures.set(captureKey, pending);
860
+ void pending.catch(() => captures.delete(captureKey));
861
+ }
862
+ const result = await pending;
863
+ throwIfAborted(captureSignal);
864
+ return result;
865
+ },
866
+ // The provider owns this shared browser across preparation leases. Consumer cleanup calls
867
+ // provider.close after every plan using its retained handles has finished.
868
+ async close() {
869
+ }
870
+ };
871
+ },
872
+ async close() {
873
+ if (closePromise) return closePromise;
874
+ closed = true;
875
+ closePromise = (async () => {
876
+ const opened = await Promise.allSettled(sessions.values());
877
+ const cancellation = Promise.allSettled(
878
+ opened.flatMap((result) => result.status === "fulfilled" ? [result.value.cancel()] : [])
879
+ );
880
+ const [completedCaptures, cleanup] = await Promise.all([
881
+ Promise.allSettled(captures.values()),
882
+ cancellation
883
+ ]);
884
+ sessions.clear();
885
+ captures.clear();
886
+ const failures = [
887
+ ...completedCaptures.flatMap((result) => result.status === "rejected" ? [result.reason] : []),
888
+ ...opened.flatMap((result) => result.status === "rejected" ? [result.reason] : []),
889
+ ...cleanup.flatMap((result) => result.status === "rejected" && result.reason?.code !== "ENOENT" ? [result.reason] : [])
890
+ ];
891
+ if (failures.length) throw new AggregateError(failures, "scene_component_capture_cleanup_failed");
892
+ })();
893
+ return closePromise;
894
+ }
895
+ };
896
+ return provider;
897
+ }
235
898
  function localFilePath(u) {
236
899
  if (typeof u !== "string" || u.length === 0) return null;
237
900
  if (/^https?:\/\//i.test(u)) return null;
238
901
  let p;
239
- if (u.startsWith("file://")) p = fileURLToPath(u);
902
+ if (u.startsWith("file://")) p = fileURLToPath3(u);
240
903
  else if (u.startsWith("/")) p = u;
241
904
  else return null;
242
905
  return existsSync4(p) ? p : null;
@@ -247,122 +910,200 @@ function hasLocalFileRefs(input) {
247
910
  }
248
911
  return false;
249
912
  }
250
- async function httpDownload(url, destPath) {
251
- const r = await fetch(url);
913
+ async function httpDownload(url, destPath, signal) {
914
+ const r = await fetch(url, { signal });
252
915
  if (!r.ok) throw new Error(`download ${r.status} for ${assetUrlKey(url)}`);
253
916
  if (!r.body) throw new Error(`download empty body for ${assetUrlKey(url)}`);
254
917
  await pipeline(
255
918
  Readable.fromWeb(r.body),
256
- createWriteStream(destPath)
919
+ createWriteStream(destPath),
920
+ { signal }
257
921
  );
258
922
  }
923
+ function admitSceneMaterializationInput(renderInput) {
924
+ let found = false;
925
+ for (const overlay of renderInput.overlays ?? []) {
926
+ const row = renderInput.componentSources?.[overlay.id];
927
+ const authoredVersion = overlay.params?.scene?.version;
928
+ const declaredVersion = row?.source.manifest?.sceneShot?.version;
929
+ if (authoredVersion !== 2 && declaredVersion === void 0) continue;
930
+ found = true;
931
+ if (!overlay.componentId || !overlay.sourceVersionId || !row || row.source.componentId !== overlay.componentId || row.sourceVersionId !== overlay.sourceVersionId) {
932
+ throw new Error(`scene_component_facts_missing: pinned source facts do not match scene candidate ${overlay.id}.`);
933
+ }
934
+ if (!readSceneShotManifest(row.source.manifest, { clipId: overlay.id, componentId: overlay.componentId })) {
935
+ throw new Error(`scene_component_facts_missing: ${overlay.id} does not declare a scene source.`);
936
+ }
937
+ parseSceneShotSpecV2(overlay.params.scene);
938
+ }
939
+ return found;
940
+ }
259
941
  async function materializeSources(renderInput, workDir, log = () => {
260
- }) {
942
+ }, options = {}) {
943
+ throwIfAborted(options.signal);
261
944
  assertCardHtmlAssetFree(renderInput);
262
- if (renderInputAssets(renderInput).length === 0 && !hasLocalFileRefs(renderInput)) {
945
+ const needsScenePreparation = admitSceneMaterializationInput(renderInput);
946
+ if (!needsScenePreparation && renderInputAssets(renderInput).length === 0 && !hasLocalFileRefs(renderInput)) {
947
+ await verifySceneShotAssetBytes(renderInput, localHandleReader({}));
263
948
  return { renderInput, close: async () => {
264
949
  } };
265
950
  }
266
951
  await mkdir(workDir, { recursive: true });
267
952
  const server = startMediaServer(workDir);
268
953
  const fps = Number(renderInput.fps) || 30;
269
- const cleanups = [];
270
- const clips = renderInput.clips ?? [];
271
- const remoteClips = clips.filter(
272
- (c) => isRemoteUrl(c.src) && (c.mediaType === void 0 || c.mediaType === "video")
273
- );
274
- if (remoteClips.length > 0) {
275
- const PADDING = 1;
276
- const sourceUrls = {};
277
- const idByKey = /* @__PURE__ */ new Map();
278
- let i = 0;
279
- for (const clip of remoteClips) {
280
- const key = assetUrlKey(clip.src);
281
- if (idByKey.has(key)) continue;
282
- const id = `src${i++}`;
283
- sourceUrls[id] = clip.src;
284
- idByKey.set(key, id);
285
- }
286
- const ranges = remoteClips.map((c) => {
287
- const id = idByKey.get(assetUrlKey(c.src));
288
- const sourceInSec = (Number(c.sourceInFrames) || 0) / fps;
289
- const durSec = (Number(c.durationInFrames) || 0) / fps;
290
- return { poolItemId: id, sourceIn: sourceInSec, sourceOut: sourceInSec + durSec };
291
- });
292
- const { segments, origins, cleanup } = await extractSegments(ranges, sourceUrls, {
293
- padding: PADDING
294
- });
295
- cleanups.push(cleanup);
296
- log(`[materialize] range-read-trimmed ${Object.keys(segments).length} source(s)`);
297
- const servedById = {};
298
- for (const [id, segPath] of Object.entries(segments)) {
299
- const fname = `${id}.seg.mp4`;
300
- await copyFile(segPath, join4(workDir, fname));
301
- servedById[id] = fname;
302
- }
303
- for (const clip of remoteClips) {
304
- const id = idByKey.get(assetUrlKey(clip.src));
305
- if (!id || !servedById[id]) {
306
- throw new Error(
307
- `source trim failed for ${assetUrlKey(clip.src)} \u2014 video source not range-readable`
308
- );
954
+ const cleanups = [async () => {
955
+ server.close();
956
+ }];
957
+ let closePromise = null;
958
+ const cleanupAll = () => closePromise ??= Promise.allSettled([...cleanups].reverse().map((cleanup) => cleanup())).then((results) => {
959
+ const failures = results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
960
+ if (failures.length) throw new AggregateError(failures, "materialize_sources_cleanup_failed");
961
+ });
962
+ try {
963
+ const clips = renderInput.clips ?? [];
964
+ const remoteClips = clips.filter(
965
+ (c) => isRemoteUrl(c.src) && (c.mediaType === void 0 || c.mediaType === "video")
966
+ );
967
+ if (remoteClips.length > 0) {
968
+ const PADDING = 1;
969
+ const sourceUrls = {};
970
+ const idByKey = /* @__PURE__ */ new Map();
971
+ let i = 0;
972
+ for (const clip of remoteClips) {
973
+ const key = assetUrlKey(clip.src);
974
+ if (idByKey.has(key)) continue;
975
+ const id = `src${i++}`;
976
+ sourceUrls[id] = clip.src;
977
+ idByKey.set(key, id);
978
+ }
979
+ const ranges = remoteClips.map((c) => {
980
+ const id = idByKey.get(assetUrlKey(c.src));
981
+ const sourceInSec = (Number(c.sourceInFrames) || 0) / fps;
982
+ const durSec = (Number(c.durationInFrames) || 0) / fps;
983
+ return { poolItemId: id, sourceIn: sourceInSec, sourceOut: sourceInSec + durSec };
984
+ });
985
+ const { segments, origins, cleanup } = await extractSegments(ranges, sourceUrls, {
986
+ padding: PADDING,
987
+ signal: options.signal
988
+ });
989
+ cleanups.push(cleanup);
990
+ log(`[materialize] range-read-trimmed ${Object.keys(segments).length} source(s)`);
991
+ const servedById = {};
992
+ for (const [id, segPath] of Object.entries(segments)) {
993
+ throwIfAborted(options.signal);
994
+ const fname = `${id}.seg.mp4`;
995
+ await copyFile(segPath, join5(workDir, fname));
996
+ throwIfAborted(options.signal);
997
+ servedById[id] = fname;
309
998
  }
310
- const shiftFrames = Math.round((origins[id] ?? 0) * fps);
311
- if (shiftFrames !== 0) {
312
- clip.sourceInFrames = (Number(clip.sourceInFrames) || 0) - shiftFrames;
313
- clip.trimStartFrames = (Number(clip.trimStartFrames) || 0) - shiftFrames;
314
- if (typeof clip.sourceOutFrames === "number") {
315
- clip.sourceOutFrames -= shiftFrames;
999
+ for (const clip of remoteClips) {
1000
+ const id = idByKey.get(assetUrlKey(clip.src));
1001
+ if (!id || !servedById[id]) {
1002
+ throw new Error(
1003
+ `source trim failed for ${assetUrlKey(clip.src)} \u2014 video source not range-readable`
1004
+ );
1005
+ }
1006
+ const shiftFrames = Math.round((origins[id] ?? 0) * fps);
1007
+ if (shiftFrames !== 0) {
1008
+ clip.sourceInFrames = (Number(clip.sourceInFrames) || 0) - shiftFrames;
1009
+ clip.trimStartFrames = (Number(clip.trimStartFrames) || 0) - shiftFrames;
1010
+ if (typeof clip.sourceOutFrames === "number") {
1011
+ clip.sourceOutFrames -= shiftFrames;
1012
+ }
316
1013
  }
1014
+ clip.src = `${server.baseUrl}/${servedById[id]}`;
317
1015
  }
318
- clip.src = `${server.baseUrl}/${servedById[id]}`;
319
1016
  }
320
- }
321
- const assets = await resolveAssets(renderInput, workDir, server.baseUrl, httpDownload);
322
- if (assets.count > 0) log(`[materialize] resolved ${assets.count} overlay/audio asset(s)`);
323
- const remaining = renderInputAssets(renderInput);
324
- if (remaining.length > 0) {
325
- const localByKey = /* @__PURE__ */ new Map();
326
- for (const ref of remaining) {
327
- await httpDownload(ref.url, join4(workDir, ref.filename));
328
- localByKey.set(assetUrlKey(ref.url), `${server.baseUrl}/${ref.filename}`);
1017
+ const assets = await resolveAssets(renderInput, workDir, server.baseUrl, httpDownload, options.signal);
1018
+ if (assets.count > 0) log(`[materialize] resolved ${assets.count} overlay/audio asset(s)`);
1019
+ const remaining = renderInputAssets(renderInput);
1020
+ if (remaining.length > 0) {
1021
+ const localByKey = /* @__PURE__ */ new Map();
1022
+ for (const ref of remaining) {
1023
+ await httpDownload(ref.url, join5(workDir, ref.filename), options.signal);
1024
+ localByKey.set(assetUrlKey(ref.url), `${server.baseUrl}/${ref.filename}`);
1025
+ }
1026
+ for (const slot of assetSlots(renderInput)) {
1027
+ const url = slot.get();
1028
+ if (typeof url !== "string" || !isRemoteUrl(url)) continue;
1029
+ const local = localByKey.get(assetUrlKey(url));
1030
+ if (local) slot.set(local);
1031
+ }
1032
+ log(`[materialize] downloaded ${remaining.length} matte/trajectory/other asset(s)`);
329
1033
  }
1034
+ const bundledFonts = {
1035
+ "/fonts/zodiak.woff2": "81bf124d17416df8fb656393c46fb34bb74e5d472f07cec9ab295269f372098a",
1036
+ "/fonts/dm-sans.woff2": "468d56b6b25b05b70190b6c233d773f6f1770e8579827ce022a57f03fa8002fb"
1037
+ };
1038
+ const admittedRenderEntryRoot = options.renderEntryRoot ?? process.env.RENDER_ENTRY_ROOT;
1039
+ const renderEntryPublic = admittedRenderEntryRoot ? join5(admittedRenderEntryRoot, "public") : null;
330
1040
  for (const slot of assetSlots(renderInput)) {
331
1041
  const url = slot.get();
332
- if (typeof url !== "string" || !isRemoteUrl(url)) continue;
333
- const local = localByKey.get(assetUrlKey(url));
334
- if (local) slot.set(local);
1042
+ if (slot.role !== "font" || typeof url !== "string" || !(url in bundledFonts)) continue;
1043
+ if (!renderEntryPublic) throw new Error(`font_not_reproducible: App font '${url}' has no packaged render-entry root.`);
1044
+ const source = join5(renderEntryPublic, url.slice(1));
1045
+ const bytes = await readFile3(source);
1046
+ const observed = createHash4("sha256").update(bytes).digest("hex");
1047
+ if (observed !== bundledFonts[url]) {
1048
+ throw new Error(`font_not_reproducible: App font '${url}' digest mismatch (${observed}).`);
1049
+ }
1050
+ const filename = `app-font-${basename(url)}`;
1051
+ await copyFile(source, join5(workDir, filename));
1052
+ throwIfAborted(options.signal);
1053
+ slot.set(`${server.baseUrl}/${filename}`);
335
1054
  }
336
- log(`[materialize] downloaded ${remaining.length} matte/trajectory/other asset(s)`);
337
- }
338
- const localByPath = /* @__PURE__ */ new Map();
339
- for (const slot of assetSlots(renderInput)) {
340
- const p = localFilePath(slot.get());
341
- if (!p) continue;
342
- let served = localByPath.get(p);
343
- if (!served) {
344
- const fname = `local-${localByPath.size}-${basename(p)}`;
345
- await copyFile(p, join4(workDir, fname));
346
- served = `${server.baseUrl}/${fname}`;
347
- localByPath.set(p, served);
1055
+ const localByPath = /* @__PURE__ */ new Map();
1056
+ for (const slot of assetSlots(renderInput)) {
1057
+ throwIfAborted(options.signal);
1058
+ const p = localFilePath(slot.get());
1059
+ if (!p) continue;
1060
+ let served = localByPath.get(p);
1061
+ if (!served) {
1062
+ const fname = `local-${localByPath.size}-${basename(p)}`;
1063
+ await copyFile(p, join5(workDir, fname));
1064
+ throwIfAborted(options.signal);
1065
+ served = `${server.baseUrl}/${fname}`;
1066
+ localByPath.set(p, served);
1067
+ }
1068
+ slot.set(served);
348
1069
  }
349
- slot.set(served);
350
- }
351
- if (localByPath.size > 0) log(`[materialize] served ${localByPath.size} local-file asset(s) over loopback`);
352
- assertNoRemoteRefs(renderInput);
353
- return {
354
- renderInput,
355
- close: async () => {
356
- server.close();
357
- for (const c of cleanups) await c().catch(() => {
1070
+ if (localByPath.size > 0) log(`[materialize] served ${localByPath.size} local-file asset(s) over loopback`);
1071
+ if (needsScenePreparation) {
1072
+ throwIfAborted(options.signal);
1073
+ if (!options.workspace) throw new Error("scene_prepared_plan_required: a workspace is required for V2 scene materialization.");
1074
+ const host = createNodeScenePreparationV1({
1075
+ ...options,
1076
+ input: renderInput,
1077
+ workspace: options.workspace,
1078
+ async publishVerifiedPng(png2) {
1079
+ throwIfAborted(options.signal);
1080
+ const encoded = await readFile3(png2.handle);
1081
+ throwIfAborted(options.signal);
1082
+ const filename = materializedCaptureFilename(png2, encoded);
1083
+ await copyFile(png2.handle, join5(workDir, filename));
1084
+ throwIfAborted(options.signal);
1085
+ return { ...png2, handle: `${server.baseUrl}/${filename}` };
1086
+ }
358
1087
  });
1088
+ cleanups.push(host.close);
1089
+ const prepared = await prepareSceneShotRenderInput(renderInput, host.dependencies);
1090
+ cleanups.push(prepared.cleanup);
1091
+ renderInput = prepared.input;
359
1092
  }
360
- };
1093
+ await verifySceneShotAssetBytes(renderInput, localHandleReader({ workDir, baseUrl: server.baseUrl }));
1094
+ assertNoRemoteRefs(renderInput);
1095
+ return { renderInput, close: cleanupAll };
1096
+ } catch (error) {
1097
+ await cleanupAll().catch((cleanupError) => {
1098
+ if (error instanceof Error && error.cause === void 0) error.cause = cleanupError;
1099
+ });
1100
+ throw error;
1101
+ }
361
1102
  }
362
1103
 
363
1104
  // ../execution/render-harness/src/cardRender.ts
364
1105
  import { mkdirSync, writeFileSync } from "fs";
365
- import { join as join5 } from "path";
1106
+ import { join as join6 } from "path";
366
1107
  var CARD_COMPOSITION_ID = "CueFrameCardStill";
367
1108
  var CARD_ROOT_FILENAME = "card.Root.local.tsx";
368
1109
  var CARD_ENTRY_FILENAME = "card.entry.local.tsx";
@@ -408,7 +1149,7 @@ function buildCardWebpackOverride(renderEntryRoot) {
408
1149
  ...config,
409
1150
  resolve: {
410
1151
  ...config.resolve,
411
- modules: [join5(renderEntryRoot, "node_modules"), ...config.resolve?.modules ?? ["node_modules"]]
1152
+ modules: [join6(renderEntryRoot, "node_modules"), ...config.resolve?.modules ?? ["node_modules"]]
412
1153
  }
413
1154
  });
414
1155
  }
@@ -418,29 +1159,34 @@ async function renderCardStill(opts) {
418
1159
  const fps = opts.fps ?? 30;
419
1160
  const frame = opts.frame ?? 0;
420
1161
  const renderEntryRoot = resolveRenderEntryRoot(opts.renderEntryRoot);
421
- const browserExecutable = process.env.REMOTION_CHROME_EXECUTABLE || void 0;
1162
+ const browserExecutable = (await verifyLocalStagedBrowser(renderEntryRoot)).path;
422
1163
  mkdirSync(opts.outDir, { recursive: true });
423
- writeFileSync(join5(opts.outDir, CARD_ROOT_FILENAME), generateCardRootSource({ width, height, fps }));
424
- const entryPoint = join5(opts.outDir, CARD_ENTRY_FILENAME);
1164
+ writeFileSync(join6(opts.outDir, CARD_ROOT_FILENAME), generateCardRootSource({ width, height, fps }));
1165
+ const entryPoint = join6(opts.outDir, CARD_ENTRY_FILENAME);
425
1166
  writeFileSync(entryPoint, generateCardEntrySource());
426
1167
  const { bundle } = await importFromRenderEntry(
427
1168
  renderEntryRoot,
428
1169
  "@remotion/bundler"
429
1170
  );
430
- const serveUrl = await bundle({ entryPoint, webpackOverride: buildCardWebpackOverride(renderEntryRoot) });
1171
+ const serveUrl = await bundle({
1172
+ entryPoint,
1173
+ outDir: join6(opts.outDir, "remotion-bundle"),
1174
+ webpackOverride: buildCardWebpackOverride(renderEntryRoot)
1175
+ });
431
1176
  const { selectComposition, renderStill } = await importFromRenderEntry(
432
1177
  renderEntryRoot,
433
1178
  "@remotion/renderer"
434
1179
  );
435
1180
  const inputProps = { html: opts.html, cssVars: opts.cssVars ?? {} };
1181
+ const { chromiumOptions } = componentBrowserBackend({ api: "canvas2d", required: true, accelerationPreference: "software-allowed" });
436
1182
  const composition = await selectComposition({
437
1183
  serveUrl,
438
1184
  id: CARD_COMPOSITION_ID,
439
1185
  inputProps,
440
1186
  browserExecutable,
441
- chromiumOptions: COMPONENT_CHROMIUM_OPTIONS
1187
+ chromiumOptions
442
1188
  });
443
- const pngPath = join5(opts.outDir, "card-still.png");
1189
+ const pngPath = join6(opts.outDir, "card-still.png");
444
1190
  await renderStill({
445
1191
  composition,
446
1192
  serveUrl,
@@ -448,7 +1194,7 @@ async function renderCardStill(opts) {
448
1194
  output: pngPath,
449
1195
  frame,
450
1196
  browserExecutable,
451
- chromiumOptions: COMPONENT_CHROMIUM_OPTIONS,
1197
+ chromiumOptions,
452
1198
  timeoutInMilliseconds: 12e4
453
1199
  });
454
1200
  return { pngPath };
@@ -462,13 +1208,17 @@ export {
462
1208
  assetSlots,
463
1209
  assetUrlKey,
464
1210
  buildCardWebpackOverride,
1211
+ createNodeScenePreparationV1,
465
1212
  extractSegments,
466
1213
  generateCardEntrySource,
467
1214
  generateCardRootSource,
468
1215
  isRemoteUrl,
1216
+ localHandleReader,
469
1217
  materializeSources,
1218
+ readImageHeader,
470
1219
  renderCardStill,
471
1220
  renderInputAssets,
472
1221
  resolveAssets,
473
- startMediaServer
1222
+ startMediaServer,
1223
+ verifySceneShotAssetBytes
474
1224
  };