framefields 2.4.0 → 2.4.2

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 (429) hide show
  1. package/README.md +11 -33
  2. package/dist/audio/index.d.mts +4 -4
  3. package/dist/audio/index.mjs +10 -10
  4. package/dist/{audio-DXwNhi1z.mjs → audio-Bb31xJuX.mjs} +4 -4
  5. package/dist/{audio-DXwNhi1z.mjs.map → audio-Bb31xJuX.mjs.map} +1 -1
  6. package/dist/{audio-C6toT7F3.d.mts → audio-DHuEMOtQ.d.mts} +3 -3
  7. package/dist/{audio-C6toT7F3.d.mts.map → audio-DHuEMOtQ.d.mts.map} +1 -1
  8. package/dist/{dist-fjKpBYkc.mjs → dist-ClyC_d66.mjs} +9 -2
  9. package/dist/dist-ClyC_d66.mjs.map +1 -0
  10. package/dist/{dist-DRB6Vg5u.mjs → dist-CspOG4V1.mjs} +25 -8
  11. package/dist/dist-CspOG4V1.mjs.map +1 -0
  12. package/dist/{dist-Cl0mvShy.mjs → dist-CxGfrigI.mjs} +222 -60
  13. package/dist/dist-CxGfrigI.mjs.map +1 -0
  14. package/dist/{dist-BY0bIWgr.mjs → dist-SB9qfAko.mjs} +2 -2
  15. package/dist/{dist-BY0bIWgr.mjs.map → dist-SB9qfAko.mjs.map} +1 -1
  16. package/dist/effects/index.d.mts +4 -4
  17. package/dist/effects/index.mjs +35 -35
  18. package/dist/{effects-lBqG-vd1.mjs → effects-BOk_2kzM.mjs} +3 -3
  19. package/dist/{effects-lBqG-vd1.mjs.map → effects-BOk_2kzM.mjs.map} +1 -1
  20. package/dist/fonts/index.mjs +2 -2
  21. package/dist/{fonts-DlRJD6NS.mjs → fonts-CsMDfqv9.mjs} +2 -2
  22. package/dist/{fonts-DlRJD6NS.mjs.map → fonts-CsMDfqv9.mjs.map} +1 -1
  23. package/dist/{gpu-DOQX1W2q.mjs → gpu-DtT5I4ME.mjs} +2 -2
  24. package/dist/{gpu-DOQX1W2q.mjs.map → gpu-DtT5I4ME.mjs.map} +1 -1
  25. package/dist/{index-CaiZ5p6q.d.mts → index-B1XcyMm8.d.mts} +2 -2
  26. package/dist/{index-CaiZ5p6q.d.mts.map → index-B1XcyMm8.d.mts.map} +1 -1
  27. package/dist/{index-Cf1pVxn0.d.mts → index-B2Xesdug.d.mts} +4 -4
  28. package/dist/{index-Cf1pVxn0.d.mts.map → index-B2Xesdug.d.mts.map} +1 -1
  29. package/dist/{index-BONyHjZX.d.mts → index-B3-gwjK6.d.mts} +16 -4
  30. package/dist/index-B3-gwjK6.d.mts.map +1 -0
  31. package/dist/{index-BHqdtJbN.d.mts → index-BTPLbjt4.d.mts} +41 -12
  32. package/dist/index-BTPLbjt4.d.mts.map +1 -0
  33. package/dist/{index-DN9oXO-X.d.mts → index-D-l-yCv6.d.mts} +3 -3
  34. package/dist/{index-DN9oXO-X.d.mts.map → index-D-l-yCv6.d.mts.map} +1 -1
  35. package/dist/{index-DEODKaL6.d.mts → index-DujpgUUq.d.mts} +7 -2
  36. package/dist/index-DujpgUUq.d.mts.map +1 -0
  37. package/dist/index.d.mts +15 -11
  38. package/dist/index.d.mts.map +1 -1
  39. package/dist/index.mjs +52 -52
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/preview/index.d.mts +2 -2
  42. package/dist/preview/index.mjs +10 -10
  43. package/dist/{preview-Ca4tF5Ro.mjs → preview-DyGw2b3_.mjs} +2 -2
  44. package/dist/{preview-Ca4tF5Ro.mjs.map → preview-DyGw2b3_.mjs.map} +1 -1
  45. package/dist/preview-engine/audio.mjs +1 -1
  46. package/dist/preview-engine/{chunk-SZW5J72T.mjs → chunk-2DDBSI75.mjs} +1 -1
  47. package/dist/preview-engine/{chunk-QXCY2ATH.mjs → chunk-2GIWWDE4.mjs} +1 -1
  48. package/dist/preview-engine/{chunk-U4JIFQRR.mjs → chunk-34ACEGNW.mjs} +1 -1
  49. package/dist/preview-engine/{chunk-AY7UX37L.mjs → chunk-3ACCCPBN.mjs} +1 -1
  50. package/dist/preview-engine/{chunk-T2FE5VOW.mjs → chunk-5RQHNB6Y.mjs} +1 -1
  51. package/dist/preview-engine/{chunk-TS3JI3BH.mjs → chunk-67SSYK7D.mjs} +1 -1
  52. package/dist/preview-engine/{chunk-PL4IH5V4.mjs → chunk-6K7US2WD.mjs} +1 -1
  53. package/dist/preview-engine/{chunk-PEWYB6WP.mjs → chunk-7LVOSEGN.mjs} +1 -1
  54. package/dist/preview-engine/{chunk-PSRQA3QW.mjs → chunk-A5OVKZ52.mjs} +1 -1
  55. package/dist/preview-engine/{chunk-VGZZSPDN.mjs → chunk-AQNTIWTK.mjs} +1 -1
  56. package/dist/preview-engine/{chunk-PXT52LEH.mjs → chunk-C6Z7H2RZ.mjs} +1 -1
  57. package/dist/preview-engine/chunk-CPFPY35C.mjs +1 -0
  58. package/dist/preview-engine/{chunk-7EPIRODI.mjs → chunk-DOCSX45C.mjs} +1 -1
  59. package/dist/preview-engine/{chunk-GSFN4WCH.mjs → chunk-FFGBUS76.mjs} +1 -1
  60. package/dist/preview-engine/{chunk-IR5DNNWR.mjs → chunk-FFMPC7QA.mjs} +1 -1
  61. package/dist/preview-engine/{chunk-IUPDOATX.mjs → chunk-FHKBALVI.mjs} +1 -1
  62. package/dist/preview-engine/{chunk-HE4R7EZM.mjs → chunk-G4J662EL.mjs} +1 -1
  63. package/dist/preview-engine/{chunk-5W4AFQP7.mjs → chunk-GNG4YH2W.mjs} +1 -1
  64. package/dist/preview-engine/{chunk-L6BH5J4P.mjs → chunk-GQLZXCW3.mjs} +1 -1
  65. package/dist/preview-engine/{chunk-EVXWDOCL.mjs → chunk-HDGFNBYK.mjs} +1 -1
  66. package/dist/preview-engine/{chunk-JXNG2ACR.mjs → chunk-HNNIVJ2K.mjs} +1 -1
  67. package/dist/preview-engine/{chunk-FU7AIAMM.mjs → chunk-HUKAC5MJ.mjs} +1 -1
  68. package/dist/preview-engine/{chunk-44CQSOYE.mjs → chunk-JX22B2FS.mjs} +1 -1
  69. package/dist/preview-engine/{chunk-DIGIQ5MJ.mjs → chunk-KAQUNOVB.mjs} +1 -1
  70. package/dist/preview-engine/{chunk-MLY5M7Y5.mjs → chunk-KT35IPCF.mjs} +1 -1
  71. package/dist/preview-engine/{chunk-VXS5SIEC.mjs → chunk-LIQA5OOU.mjs} +1 -1
  72. package/dist/preview-engine/{chunk-SGPRLTNF.mjs → chunk-LK3T65RB.mjs} +1 -1
  73. package/dist/preview-engine/{chunk-YQZOGEPZ.mjs → chunk-LLDIDE5Q.mjs} +1 -1
  74. package/dist/preview-engine/chunk-NNQUIVTE.mjs +5 -0
  75. package/dist/preview-engine/{chunk-5AUB4Y3L.mjs → chunk-NRAZV5OA.mjs} +1 -1
  76. package/dist/preview-engine/{chunk-BSOJR4JU.mjs → chunk-O6NRIXS5.mjs} +1 -1
  77. package/dist/preview-engine/{chunk-OKH2VU2U.mjs → chunk-PZF6T7DM.mjs} +1 -1
  78. package/dist/preview-engine/{chunk-OJ2PKBXE.mjs → chunk-QJZKIY4H.mjs} +1 -1
  79. package/dist/preview-engine/{chunk-WFGJXCZT.mjs → chunk-R26SY5D4.mjs} +1 -1
  80. package/dist/preview-engine/{chunk-EYWPOCZW.mjs → chunk-RDP6QROU.mjs} +1 -1
  81. package/dist/preview-engine/{chunk-VK2CVMWJ.mjs → chunk-RHRMEBNK.mjs} +1 -1
  82. package/dist/preview-engine/{chunk-J2R5R7YY.mjs → chunk-RKVB47IA.mjs} +1 -1
  83. package/dist/preview-engine/{chunk-PAQNDZQB.mjs → chunk-SWXVITCQ.mjs} +1 -1
  84. package/dist/preview-engine/{chunk-KERW7QJ4.mjs → chunk-UZBVCYRY.mjs} +1 -1
  85. package/dist/preview-engine/chunk-VONDRBA2.mjs +1 -0
  86. package/dist/preview-engine/{chunk-Q22PJXFJ.mjs → chunk-WACWOKEP.mjs} +1 -1
  87. package/dist/preview-engine/{chunk-AXHB4J37.mjs → chunk-WCZ5DKZ4.mjs} +1 -1
  88. package/dist/preview-engine/{chunk-WH5Q2NFN.mjs → chunk-WJJIISQJ.mjs} +1 -1
  89. package/dist/preview-engine/chunk-XDMZP3E2.mjs +1 -0
  90. package/dist/preview-engine/{chunk-7G3XIOP7.mjs → chunk-Z6UKUHPU.mjs} +1 -1
  91. package/dist/preview-engine/{chunk-WUKH7BD7.mjs → chunk-ZKPQGQE3.mjs} +1 -1
  92. package/dist/preview-engine/effects.mjs +1 -1
  93. package/dist/preview-engine/framefields.mjs +4 -4
  94. package/dist/preview-engine/player.mjs +1 -1
  95. package/dist/preview-engine/{renderers-2P6KXWEZ.mjs → renderers-3CXFGRE7.mjs} +1 -1
  96. package/dist/preview-engine/{renderers-KZWGSKRF.mjs → renderers-3FC3WCJN.mjs} +1 -1
  97. package/dist/preview-engine/renderers-3S2FM33K.mjs +1 -0
  98. package/dist/preview-engine/{renderers-5FQA2DP4.mjs → renderers-4AJWVIJG.mjs} +1 -1
  99. package/dist/preview-engine/renderers-53ZTBI3C.mjs +1 -0
  100. package/dist/preview-engine/renderers-5USBVCMQ.mjs +1 -0
  101. package/dist/preview-engine/renderers-65G6BLEA.mjs +1 -0
  102. package/dist/preview-engine/{renderers-PYWXELLG.mjs → renderers-6JZ4HYIU.mjs} +1 -1
  103. package/dist/preview-engine/{renderers-3GHEWWVX.mjs → renderers-75TL7RLS.mjs} +1 -1
  104. package/dist/preview-engine/{renderers-U6KY34TP.mjs → renderers-7CPYTCNW.mjs} +1 -1
  105. package/dist/preview-engine/renderers-7XU7BXE7.mjs +1 -0
  106. package/dist/preview-engine/{renderers-2VN3AH45.mjs → renderers-AZYJFJLO.mjs} +1 -1
  107. package/dist/preview-engine/{renderers-TR2V2HZ2.mjs → renderers-BDWVXYTW.mjs} +1 -1
  108. package/dist/preview-engine/renderers-BFXM32BC.mjs +1 -0
  109. package/dist/preview-engine/renderers-CDXHCWWK.mjs +1 -0
  110. package/dist/preview-engine/{renderers-N7FR54V2.mjs → renderers-CK3ZL3GM.mjs} +1 -1
  111. package/dist/preview-engine/renderers-CLUN7WU6.mjs +1 -0
  112. package/dist/preview-engine/renderers-DTB4HEXU.mjs +1 -0
  113. package/dist/preview-engine/renderers-EFKNRLYF.mjs +1 -0
  114. package/dist/preview-engine/{renderers-HQEKSUNR.mjs → renderers-EI6MQ2EL.mjs} +1 -1
  115. package/dist/preview-engine/{renderers-UPTJJE5F.mjs → renderers-FADYGSLK.mjs} +1 -1
  116. package/dist/preview-engine/{renderers-I5E2RSV4.mjs → renderers-FKH5S64C.mjs} +1 -1
  117. package/dist/preview-engine/{renderers-BSKZXITT.mjs → renderers-FM6A5YR4.mjs} +1 -1
  118. package/dist/preview-engine/renderers-G2K7ZA5O.mjs +1 -0
  119. package/dist/preview-engine/{renderers-D6T6IPER.mjs → renderers-GAIUTII6.mjs} +1 -1
  120. package/dist/preview-engine/renderers-GTUO5LIV.mjs +1 -0
  121. package/dist/preview-engine/{renderers-A6HM64UZ.mjs → renderers-GUPEJK3O.mjs} +1 -1
  122. package/dist/preview-engine/{renderers-IWQ3V6AJ.mjs → renderers-HSJIVP57.mjs} +1 -1
  123. package/dist/preview-engine/{renderers-4GRVAW2W.mjs → renderers-HZHEGONW.mjs} +1 -1
  124. package/dist/preview-engine/{renderers-NWHS7N2L.mjs → renderers-IHACBWXI.mjs} +1 -1
  125. package/dist/preview-engine/{renderers-3YCJOINH.mjs → renderers-IHRFEZNP.mjs} +1 -1
  126. package/dist/preview-engine/{renderers-A7VH3ON5.mjs → renderers-IJDQJEE5.mjs} +1 -1
  127. package/dist/preview-engine/{renderers-OT7D3BUA.mjs → renderers-IO3BVVJ7.mjs} +1 -1
  128. package/dist/preview-engine/renderers-IR772VSN.mjs +1 -0
  129. package/dist/preview-engine/{renderers-EJWPVVQR.mjs → renderers-K7B5PQBT.mjs} +1 -1
  130. package/dist/preview-engine/renderers-L6TRJOXA.mjs +1 -0
  131. package/dist/preview-engine/{renderers-N7TS5562.mjs → renderers-LVLVJHOL.mjs} +1 -1
  132. package/dist/preview-engine/{renderers-FK72LKQC.mjs → renderers-MBSOKWKB.mjs} +1 -1
  133. package/dist/preview-engine/{renderers-NC64EQDE.mjs → renderers-N6H6RSF2.mjs} +1 -1
  134. package/dist/preview-engine/{renderers-ZHZMGMLN.mjs → renderers-NJLGPPX7.mjs} +1 -1
  135. package/dist/preview-engine/renderers-O5NFQYRQ.mjs +1 -0
  136. package/dist/preview-engine/renderers-O6V3OEKX.mjs +1 -0
  137. package/dist/preview-engine/renderers-OODA27UH.mjs +1 -0
  138. package/dist/preview-engine/{renderers-6CG7DBTB.mjs → renderers-R4WMM6IX.mjs} +1 -1
  139. package/dist/preview-engine/renderers-RIGW33ZI.mjs +1 -0
  140. package/dist/preview-engine/{renderers-RLHTNLRE.mjs → renderers-RKZGYWDG.mjs} +1 -1
  141. package/dist/preview-engine/renderers-RUZRBQ4K.mjs +1 -0
  142. package/dist/preview-engine/renderers-SKB2GGKS.mjs +1 -0
  143. package/dist/preview-engine/{renderers-6OGFUSH6.mjs → renderers-SW7FIEKO.mjs} +1 -1
  144. package/dist/preview-engine/renderers-T4D2TASM.mjs +1 -0
  145. package/dist/preview-engine/renderers-T74XV36Q.mjs +1 -0
  146. package/dist/preview-engine/{renderers-F55XFVMP.mjs → renderers-TCNPEANL.mjs} +1 -1
  147. package/dist/preview-engine/renderers-TOPW2UM3.mjs +1 -0
  148. package/dist/preview-engine/{renderers-5YEIUTVN.mjs → renderers-TY7DVI7E.mjs} +1 -1
  149. package/dist/preview-engine/{renderers-YMPXGYRU.mjs → renderers-UDOBX433.mjs} +1 -1
  150. package/dist/preview-engine/{renderers-CRRLV7IO.mjs → renderers-UMPOVFRA.mjs} +1 -1
  151. package/dist/preview-engine/renderers-UO5G3Y2G.mjs +1 -0
  152. package/dist/preview-engine/renderers-UOV7VOJJ.mjs +1 -0
  153. package/dist/preview-engine/{renderers-MON4QFRF.mjs → renderers-UWKSTSTA.mjs} +1 -1
  154. package/dist/preview-engine/renderers-VHPAOUTA.mjs +1 -0
  155. package/dist/preview-engine/{renderers-E76OKK66.mjs → renderers-WR6MKT5S.mjs} +1 -1
  156. package/dist/preview-engine/{renderers-MCECHPCL.mjs → renderers-XKHNBARD.mjs} +1 -1
  157. package/dist/preview-engine/renderers-YEQRQJFC.mjs +1 -0
  158. package/dist/preview-engine/{renderers-RJO6H4FC.mjs → renderers-YRZ3WODX.mjs} +1 -1
  159. package/dist/preview-engine/renderers-YUTFGVRY.mjs +1 -0
  160. package/dist/preview-engine/{renderers-3SRG77SC.mjs → renderers-YXOTRKPA.mjs} +1 -1
  161. package/dist/preview-engine/renderers-ZOU5ARVD.mjs +1 -0
  162. package/dist/preview-engine/renderers-ZW75LQTR.mjs +1 -0
  163. package/dist/preview-engine/signals.mjs +1 -1
  164. package/dist/{program-CJEg2wMa.mjs → program-C2cJayA1.mjs} +4 -4
  165. package/dist/{program-CJEg2wMa.mjs.map → program-C2cJayA1.mjs.map} +1 -1
  166. package/dist/renderer/index.d.mts +2 -2
  167. package/dist/renderer/index.mjs +2 -2
  168. package/dist/{renderer-CCu1Q8ib.mjs → renderer--ruTGlPo.mjs} +3 -3
  169. package/dist/{renderer-CCu1Q8ib.mjs.map → renderer--ruTGlPo.mjs.map} +1 -1
  170. package/dist/{renderer-D-IcBLT0.mjs → renderer-7y5Cj8rV.mjs} +3 -3
  171. package/dist/{renderer-D-IcBLT0.mjs.map → renderer-7y5Cj8rV.mjs.map} +1 -1
  172. package/dist/{renderer-Dg5yLAM9.mjs → renderer-92eLJg24.mjs} +4 -4
  173. package/dist/{renderer-Dg5yLAM9.mjs.map → renderer-92eLJg24.mjs.map} +1 -1
  174. package/dist/{renderer-CduDa1qf.mjs → renderer-B0gPTXhe.mjs} +3 -3
  175. package/dist/{renderer-CduDa1qf.mjs.map → renderer-B0gPTXhe.mjs.map} +1 -1
  176. package/dist/{renderer-CjTxu89O.mjs → renderer-B1QREs7J.mjs} +3 -3
  177. package/dist/{renderer-CjTxu89O.mjs.map → renderer-B1QREs7J.mjs.map} +1 -1
  178. package/dist/{renderer-DVaVVz-D.mjs → renderer-B3e4LSE6.mjs} +3 -3
  179. package/dist/{renderer-DVaVVz-D.mjs.map → renderer-B3e4LSE6.mjs.map} +1 -1
  180. package/dist/{renderer-CxSH3F_n.mjs → renderer-B4RpSd4A.mjs} +2 -2
  181. package/dist/{renderer-CxSH3F_n.mjs.map → renderer-B4RpSd4A.mjs.map} +1 -1
  182. package/dist/renderer-BAhZeUUn.mjs +5 -0
  183. package/dist/{renderer-BZCLdb8F.mjs → renderer-BBAbZfBl.mjs} +4 -4
  184. package/dist/{renderer-BZCLdb8F.mjs.map → renderer-BBAbZfBl.mjs.map} +1 -1
  185. package/dist/{renderer-DZndEvZN.mjs → renderer-BDCy8NgT.mjs} +3 -3
  186. package/dist/{renderer-DZndEvZN.mjs.map → renderer-BDCy8NgT.mjs.map} +1 -1
  187. package/dist/renderer-BHAE_dKq.mjs +5 -0
  188. package/dist/{renderer-i4RJ-_sx.mjs → renderer-BMKFzfSQ.mjs} +3 -3
  189. package/dist/{renderer-i4RJ-_sx.mjs.map → renderer-BMKFzfSQ.mjs.map} +1 -1
  190. package/dist/renderer-BNYZY3FE.mjs +5 -0
  191. package/dist/{renderer-BtJ6XYN7.mjs → renderer-BPixWnmY.mjs} +3 -3
  192. package/dist/{renderer-BtJ6XYN7.mjs.map → renderer-BPixWnmY.mjs.map} +1 -1
  193. package/dist/renderer-BSvubMvI.mjs +5 -0
  194. package/dist/{renderer-CoN2JgLO.mjs → renderer-BTd2sWDC.mjs} +3 -3
  195. package/dist/{renderer-CoN2JgLO.mjs.map → renderer-BTd2sWDC.mjs.map} +1 -1
  196. package/dist/{renderer-DautVsW4.mjs → renderer-BTigwMQp.mjs} +3 -3
  197. package/dist/{renderer-DautVsW4.mjs.map → renderer-BTigwMQp.mjs.map} +1 -1
  198. package/dist/{renderer-B8v8iEkB.mjs → renderer-BV48PFjX.mjs} +6 -6
  199. package/dist/{renderer-B8v8iEkB.mjs.map → renderer-BV48PFjX.mjs.map} +1 -1
  200. package/dist/renderer-B_M_yhTc.mjs +5 -0
  201. package/dist/renderer-B_xSsTuy.mjs +5 -0
  202. package/dist/renderer-BePHurAU.mjs +5 -0
  203. package/dist/renderer-BfZquJrW.mjs +5 -0
  204. package/dist/{renderer-DAFi5TC_.mjs → renderer-Bi6W4RSn.mjs} +2 -2
  205. package/dist/{renderer-DAFi5TC_.mjs.map → renderer-Bi6W4RSn.mjs.map} +1 -1
  206. package/dist/{renderer-Edn9xltT.mjs → renderer-BjCHW9Jp.mjs} +2 -2
  207. package/dist/{renderer-CJmZURPQ.mjs → renderer-BjvNEbML.mjs} +2 -2
  208. package/dist/{renderer-CJmZURPQ.mjs.map → renderer-BjvNEbML.mjs.map} +1 -1
  209. package/dist/{renderer-C2ZIAhdJ.mjs → renderer-BkWd4-YO.mjs} +2 -2
  210. package/dist/{renderer-C2ZIAhdJ.mjs.map → renderer-BkWd4-YO.mjs.map} +1 -1
  211. package/dist/{renderer-Cfto0m0-.mjs → renderer-Bkrk0M0r.mjs} +3 -3
  212. package/dist/{renderer-Cfto0m0-.mjs.map → renderer-Bkrk0M0r.mjs.map} +1 -1
  213. package/dist/{renderer-h9sJnoxw.mjs → renderer-BljMOvry.mjs} +3 -3
  214. package/dist/{renderer-h9sJnoxw.mjs.map → renderer-BljMOvry.mjs.map} +1 -1
  215. package/dist/renderer-BuY5ypB2.mjs +5 -0
  216. package/dist/renderer-BvOQgFHo.mjs +5 -0
  217. package/dist/{renderer-DqgduGiO.mjs → renderer-BwpgDLYO.mjs} +3 -3
  218. package/dist/{renderer-DqgduGiO.mjs.map → renderer-BwpgDLYO.mjs.map} +1 -1
  219. package/dist/{renderer-DaV95CAd.mjs → renderer-BwwZB2mt.mjs} +4 -4
  220. package/dist/{renderer-DaV95CAd.mjs.map → renderer-BwwZB2mt.mjs.map} +1 -1
  221. package/dist/{renderer-DA1brg35.mjs → renderer-ByCX4JYg.mjs} +3 -3
  222. package/dist/{renderer-DA1brg35.mjs.map → renderer-ByCX4JYg.mjs.map} +1 -1
  223. package/dist/{renderer-Tf1AS1aO.mjs → renderer-C1E5Rt5q.mjs} +3 -3
  224. package/dist/{renderer-Tf1AS1aO.mjs.map → renderer-C1E5Rt5q.mjs.map} +1 -1
  225. package/dist/renderer-C7NkSvUz.mjs +5 -0
  226. package/dist/{renderer-CG4TmDWH.mjs → renderer-CCGzT6bX.mjs} +2 -2
  227. package/dist/{renderer-wFyrVuuj.mjs → renderer-CDOobs18.mjs} +3 -3
  228. package/dist/{renderer-wFyrVuuj.mjs.map → renderer-CDOobs18.mjs.map} +1 -1
  229. package/dist/{renderer-BaHEN_Kv.mjs → renderer-CDUxAtsk.mjs} +4 -4
  230. package/dist/{renderer-BaHEN_Kv.mjs.map → renderer-CDUxAtsk.mjs.map} +1 -1
  231. package/dist/renderer-CIuxV2q1.mjs +5 -0
  232. package/dist/{renderer-DY8fPeH3.mjs → renderer-CJ4bxCld.mjs} +2 -2
  233. package/dist/renderer-CKp97tSQ.mjs +5 -0
  234. package/dist/{renderer-BTJyO6ov.mjs → renderer-CNuVJ4nG.mjs} +2 -2
  235. package/dist/{renderer-BTJyO6ov.mjs.map → renderer-CNuVJ4nG.mjs.map} +1 -1
  236. package/dist/renderer-CY89dTFR.mjs +5 -0
  237. package/dist/renderer-C_B_4Bl0.mjs +5 -0
  238. package/dist/{renderer-Dk0dnuHr.mjs → renderer-Cbsnj9vV.mjs} +3 -3
  239. package/dist/{renderer-Dk0dnuHr.mjs.map → renderer-Cbsnj9vV.mjs.map} +1 -1
  240. package/dist/{renderer-B6UqWjtH.mjs → renderer-CcoUNzlQ.mjs} +3 -3
  241. package/dist/{renderer-B6UqWjtH.mjs.map → renderer-CcoUNzlQ.mjs.map} +1 -1
  242. package/dist/renderer-Cd87JOjP.mjs +5 -0
  243. package/dist/{renderer-BZF48o1T.mjs → renderer-CeiCJCg4.mjs} +3 -3
  244. package/dist/{renderer-BZF48o1T.mjs.map → renderer-CeiCJCg4.mjs.map} +1 -1
  245. package/dist/renderer-Cev6orIK.mjs +6 -0
  246. package/dist/renderer-Cewf6UPh.mjs +5 -0
  247. package/dist/renderer-CnHsMLIv.mjs +5 -0
  248. package/dist/{renderer-TyZu7nQ2.mjs → renderer-CoWfz-9p.mjs} +441 -177
  249. package/dist/renderer-CoWfz-9p.mjs.map +1 -0
  250. package/dist/renderer-CoxuAr7b.mjs +5 -0
  251. package/dist/{renderer-D4E8Yf61.mjs → renderer-CqtIbe5n.mjs} +2 -2
  252. package/dist/{renderer-D4E8Yf61.mjs.map → renderer-CqtIbe5n.mjs.map} +1 -1
  253. package/dist/renderer-CrdG7trA.mjs +5 -0
  254. package/dist/{renderer-C-La-IAt.mjs → renderer-Csss5GFQ.mjs} +2 -2
  255. package/dist/{renderer-C-La-IAt.mjs.map → renderer-Csss5GFQ.mjs.map} +1 -1
  256. package/dist/renderer-Cu5MFgbk.mjs +5 -0
  257. package/dist/renderer-CuOjhtoo.mjs +5 -0
  258. package/dist/{renderer-BhZutM8K.mjs → renderer-Cv4lchUP.mjs} +3 -3
  259. package/dist/{renderer-BhZutM8K.mjs.map → renderer-Cv4lchUP.mjs.map} +1 -1
  260. package/dist/{renderer-CgZ1G37H.mjs → renderer-Cw6Sagih.mjs} +3 -3
  261. package/dist/{renderer-CgZ1G37H.mjs.map → renderer-Cw6Sagih.mjs.map} +1 -1
  262. package/dist/{renderer-Dim2ZlfK.d.mts → renderer-CxqPeATd.d.mts} +2 -2
  263. package/dist/{renderer-Dim2ZlfK.d.mts.map → renderer-CxqPeATd.d.mts.map} +1 -1
  264. package/dist/{renderer-yGARXwV0.mjs → renderer-CzRqzp8P.mjs} +3 -3
  265. package/dist/{renderer-yGARXwV0.mjs.map → renderer-CzRqzp8P.mjs.map} +1 -1
  266. package/dist/{renderer-eWBBsCv2.mjs → renderer-D0vom99O.mjs} +2 -2
  267. package/dist/{renderer-eWBBsCv2.mjs.map → renderer-D0vom99O.mjs.map} +1 -1
  268. package/dist/{renderer-C9pl21Zb.mjs → renderer-D2-V9nQq.mjs} +3 -3
  269. package/dist/{renderer-C9pl21Zb.mjs.map → renderer-D2-V9nQq.mjs.map} +1 -1
  270. package/dist/renderer-D2_0g6Oi.mjs +5 -0
  271. package/dist/renderer-D62FwolD.mjs +5 -0
  272. package/dist/{renderer-445i0uxs.mjs → renderer-D6BXR7P4.mjs} +2 -2
  273. package/dist/{renderer-445i0uxs.mjs.map → renderer-D6BXR7P4.mjs.map} +1 -1
  274. package/dist/renderer-DDNY9N7I.mjs +5 -0
  275. package/dist/{renderer-5tQ7ImPk.mjs → renderer-DFJQ6v0F.mjs} +2 -2
  276. package/dist/{renderer-5tQ7ImPk.mjs.map → renderer-DFJQ6v0F.mjs.map} +1 -1
  277. package/dist/renderer-DF_ONJ3v.mjs +5 -0
  278. package/dist/{renderer-CoO2j8AC.mjs → renderer-DILUmb-e.mjs} +3 -3
  279. package/dist/{renderer-CoO2j8AC.mjs.map → renderer-DILUmb-e.mjs.map} +1 -1
  280. package/dist/{renderer-CduL1AOK.mjs → renderer-DKfwlE4e.mjs} +3 -3
  281. package/dist/{renderer-CduL1AOK.mjs.map → renderer-DKfwlE4e.mjs.map} +1 -1
  282. package/dist/{renderer-DFX2V9Dp.mjs → renderer-DScyMHpJ.mjs} +2 -2
  283. package/dist/{renderer-DFX2V9Dp.mjs.map → renderer-DScyMHpJ.mjs.map} +1 -1
  284. package/dist/{renderer-BZvWlGsa.mjs → renderer-DTw-W0Yz.mjs} +3 -3
  285. package/dist/{renderer-BZvWlGsa.mjs.map → renderer-DTw-W0Yz.mjs.map} +1 -1
  286. package/dist/{renderer-BFWRUTov.mjs → renderer-DZJJHCtm.mjs} +3 -3
  287. package/dist/{renderer-BFWRUTov.mjs.map → renderer-DZJJHCtm.mjs.map} +1 -1
  288. package/dist/{renderer-Cz9fzS11.mjs → renderer-DaSxr9fM.mjs} +3 -3
  289. package/dist/{renderer-Cz9fzS11.mjs.map → renderer-DaSxr9fM.mjs.map} +1 -1
  290. package/dist/{renderer-CoX23zo_.mjs → renderer-DaqWTx7s.mjs} +3 -3
  291. package/dist/{renderer-CoX23zo_.mjs.map → renderer-DaqWTx7s.mjs.map} +1 -1
  292. package/dist/renderer-DbzrVHEE.mjs +5 -0
  293. package/dist/{renderer-CN3iCli4.mjs → renderer-DcBGYN3V.mjs} +3 -3
  294. package/dist/{renderer-CN3iCli4.mjs.map → renderer-DcBGYN3V.mjs.map} +1 -1
  295. package/dist/{renderer-CCCitH4J.mjs → renderer-DjBCWxYy.mjs} +3 -3
  296. package/dist/{renderer-CCCitH4J.mjs.map → renderer-DjBCWxYy.mjs.map} +1 -1
  297. package/dist/{renderer-gbBgGPNL.mjs → renderer-DjwITRvg.mjs} +2 -2
  298. package/dist/renderer-DlYchp1v.mjs +5 -0
  299. package/dist/renderer-DqcUNP8J.mjs +5 -0
  300. package/dist/renderer-DqvFhEQj.mjs +5 -0
  301. package/dist/{renderer-B4JmNa_T.mjs → renderer-DwVOxdzC.mjs} +3 -3
  302. package/dist/{renderer-B4JmNa_T.mjs.map → renderer-DwVOxdzC.mjs.map} +1 -1
  303. package/dist/{renderer-BZWiY6Jw.mjs → renderer-Dwu_zfdL.mjs} +3 -3
  304. package/dist/{renderer-BZWiY6Jw.mjs.map → renderer-Dwu_zfdL.mjs.map} +1 -1
  305. package/dist/renderer-DxBav2bE.mjs +5 -0
  306. package/dist/{renderer-DkYiOWPJ.mjs → renderer-DyyIXLQK.mjs} +3 -3
  307. package/dist/{renderer-DkYiOWPJ.mjs.map → renderer-DyyIXLQK.mjs.map} +1 -1
  308. package/dist/{renderer-D-e3vDnO.mjs → renderer-DzSMeQBC.mjs} +3 -3
  309. package/dist/{renderer-D-e3vDnO.mjs.map → renderer-DzSMeQBC.mjs.map} +1 -1
  310. package/dist/{renderer-DOZJeWM4.mjs → renderer-EZp_IIPK.mjs} +3 -3
  311. package/dist/{renderer-DOZJeWM4.mjs.map → renderer-EZp_IIPK.mjs.map} +1 -1
  312. package/dist/{renderer-DkM_wN8j.mjs → renderer-G1pMJH5C.mjs} +2 -2
  313. package/dist/{renderer-DkM_wN8j.mjs.map → renderer-G1pMJH5C.mjs.map} +1 -1
  314. package/dist/renderer-GvSRoQje.mjs +5 -0
  315. package/dist/{renderer-DQtk282o.mjs → renderer-If8JOkBi.mjs} +2 -2
  316. package/dist/{renderer-DQtk282o.mjs.map → renderer-If8JOkBi.mjs.map} +1 -1
  317. package/dist/{renderer-BL36f2IQ.mjs → renderer-JvcR1vYI.mjs} +2 -2
  318. package/dist/{renderer-BL36f2IQ.mjs.map → renderer-JvcR1vYI.mjs.map} +1 -1
  319. package/dist/renderer-KP7Ita9g.mjs +5 -0
  320. package/dist/{renderer-DOkEalxy.mjs → renderer-NizuhHsH.mjs} +3 -3
  321. package/dist/{renderer-DOkEalxy.mjs.map → renderer-NizuhHsH.mjs.map} +1 -1
  322. package/dist/renderer-Pc8dyNXt.mjs +5 -0
  323. package/dist/{renderer-fXRwAdO2.mjs → renderer-RDCax5CK.mjs} +3 -3
  324. package/dist/{renderer-fXRwAdO2.mjs.map → renderer-RDCax5CK.mjs.map} +1 -1
  325. package/dist/{renderer-BOvCstdU.mjs → renderer-UcdqCarR.mjs} +3 -3
  326. package/dist/{renderer-BOvCstdU.mjs.map → renderer-UcdqCarR.mjs.map} +1 -1
  327. package/dist/{renderer-BaBluD-r.mjs → renderer-V5uEyDFz.mjs} +3 -3
  328. package/dist/{renderer-BaBluD-r.mjs.map → renderer-V5uEyDFz.mjs.map} +1 -1
  329. package/dist/{renderer-BzgnTEvf.mjs → renderer-X0eKSD7v.mjs} +3 -3
  330. package/dist/{renderer-BzgnTEvf.mjs.map → renderer-X0eKSD7v.mjs.map} +1 -1
  331. package/dist/{renderer-Ai5nZsof.mjs → renderer-Za4D9hej.mjs} +3 -3
  332. package/dist/{renderer-Ai5nZsof.mjs.map → renderer-Za4D9hej.mjs.map} +1 -1
  333. package/dist/{renderer-q971j1BW.mjs → renderer-apeDrNXM.mjs} +3 -3
  334. package/dist/{renderer-q971j1BW.mjs.map → renderer-apeDrNXM.mjs.map} +1 -1
  335. package/dist/renderer-ezRCmU09.mjs +3 -0
  336. package/dist/{renderer-CNS8LA2_.mjs → renderer-gRMkQabv.mjs} +3 -3
  337. package/dist/{renderer-CNS8LA2_.mjs.map → renderer-gRMkQabv.mjs.map} +1 -1
  338. package/dist/renderer-h6ev1ogx.mjs +5 -0
  339. package/dist/{renderer-nMnE_T2y.mjs → renderer-rXgqgAjw.mjs} +3 -3
  340. package/dist/{renderer-nMnE_T2y.mjs.map → renderer-rXgqgAjw.mjs.map} +1 -1
  341. package/dist/{renderer-BPsi7Q7Z.mjs → renderer-ut1GqW89.mjs} +3 -3
  342. package/dist/{renderer-BPsi7Q7Z.mjs.map → renderer-ut1GqW89.mjs.map} +1 -1
  343. package/dist/{renderer-DH0wkQkR.mjs → renderer-yyUpCeWb.mjs} +2 -2
  344. package/dist/{renderer-DH0wkQkR.mjs.map → renderer-yyUpCeWb.mjs.map} +1 -1
  345. package/dist/{renderers-CP8CFWDs-DoVn7dbW.mjs → renderers-CP8CFWDs-DzGXDs5p.mjs} +3 -3
  346. package/dist/{renderers-CP8CFWDs-DoVn7dbW.mjs.map → renderers-CP8CFWDs-DzGXDs5p.mjs.map} +1 -1
  347. package/dist/signals/index.d.mts +5 -5
  348. package/dist/signals/index.mjs +6 -6
  349. package/dist/{signals-DGRs6ddH.mjs → signals-C5nOrRmn.mjs} +3 -3
  350. package/dist/{signals-DGRs6ddH.mjs.map → signals-C5nOrRmn.mjs.map} +1 -1
  351. package/package.json +57 -57
  352. package/dist/dist-Cl0mvShy.mjs.map +0 -1
  353. package/dist/dist-DRB6Vg5u.mjs.map +0 -1
  354. package/dist/dist-fjKpBYkc.mjs.map +0 -1
  355. package/dist/index-BHqdtJbN.d.mts.map +0 -1
  356. package/dist/index-BONyHjZX.d.mts.map +0 -1
  357. package/dist/index-DEODKaL6.d.mts.map +0 -1
  358. package/dist/preview-engine/chunk-63SFBHEH.mjs +0 -1
  359. package/dist/preview-engine/chunk-7J2FWGVD.mjs +0 -1
  360. package/dist/preview-engine/chunk-M5HZPZHQ.mjs +0 -1
  361. package/dist/preview-engine/chunk-OG62XGCT.mjs +0 -5
  362. package/dist/preview-engine/renderers-2H7YEUTD.mjs +0 -1
  363. package/dist/preview-engine/renderers-2ILG23ED.mjs +0 -1
  364. package/dist/preview-engine/renderers-3RC5FDWX.mjs +0 -1
  365. package/dist/preview-engine/renderers-6WH7NZCC.mjs +0 -1
  366. package/dist/preview-engine/renderers-7VJN5L3Z.mjs +0 -1
  367. package/dist/preview-engine/renderers-B7DSGUMI.mjs +0 -1
  368. package/dist/preview-engine/renderers-BFNJ7VCI.mjs +0 -1
  369. package/dist/preview-engine/renderers-CGYIDAVV.mjs +0 -1
  370. package/dist/preview-engine/renderers-DXHJAMZR.mjs +0 -1
  371. package/dist/preview-engine/renderers-ECA3P4ON.mjs +0 -1
  372. package/dist/preview-engine/renderers-FWGMNPYB.mjs +0 -1
  373. package/dist/preview-engine/renderers-HUW2ZMS3.mjs +0 -1
  374. package/dist/preview-engine/renderers-HXFRTIJD.mjs +0 -1
  375. package/dist/preview-engine/renderers-JHFT27YU.mjs +0 -1
  376. package/dist/preview-engine/renderers-NQXMYNSY.mjs +0 -1
  377. package/dist/preview-engine/renderers-ORAIXUL3.mjs +0 -1
  378. package/dist/preview-engine/renderers-Q4OFCMXI.mjs +0 -1
  379. package/dist/preview-engine/renderers-QVZVEYP5.mjs +0 -1
  380. package/dist/preview-engine/renderers-RKDPX5JU.mjs +0 -1
  381. package/dist/preview-engine/renderers-SBFF7JP5.mjs +0 -1
  382. package/dist/preview-engine/renderers-TAWT3ZSS.mjs +0 -1
  383. package/dist/preview-engine/renderers-UHTO6BQA.mjs +0 -1
  384. package/dist/preview-engine/renderers-UNK6I4JJ.mjs +0 -1
  385. package/dist/preview-engine/renderers-W773SBPV.mjs +0 -1
  386. package/dist/preview-engine/renderers-XHTMRXC5.mjs +0 -1
  387. package/dist/preview-engine/renderers-YECY2YFT.mjs +0 -1
  388. package/dist/preview-engine/renderers-YMN6QXK7.mjs +0 -1
  389. package/dist/preview-engine/renderers-ZANPE3OK.mjs +0 -1
  390. package/dist/preview-engine/renderers-ZHTX73PR.mjs +0 -1
  391. package/dist/preview-engine/renderers-ZJTRANIX.mjs +0 -1
  392. package/dist/renderer--IHe-yqK.mjs +0 -5
  393. package/dist/renderer-B16iwR0_.mjs +0 -5
  394. package/dist/renderer-B3EEYpx6.mjs +0 -5
  395. package/dist/renderer-B3Si5IB4.mjs +0 -5
  396. package/dist/renderer-BARst3ZD.mjs +0 -3
  397. package/dist/renderer-BH8vZKmX.mjs +0 -5
  398. package/dist/renderer-BHZie6Pa.mjs +0 -5
  399. package/dist/renderer-BHpJ1e15.mjs +0 -5
  400. package/dist/renderer-BPJ79b47.mjs +0 -5
  401. package/dist/renderer-BPbM_6WR.mjs +0 -5
  402. package/dist/renderer-Bn-WnRh9.mjs +0 -5
  403. package/dist/renderer-BqHvDAUe.mjs +0 -5
  404. package/dist/renderer-CAtXDNsh.mjs +0 -5
  405. package/dist/renderer-C_5nfVce.mjs +0 -5
  406. package/dist/renderer-Cie7KKeQ.mjs +0 -5
  407. package/dist/renderer-CuoxvPsX.mjs +0 -5
  408. package/dist/renderer-Cvd3oIJQ.mjs +0 -5
  409. package/dist/renderer-CxAgpBrJ.mjs +0 -5
  410. package/dist/renderer-D-cWBX0r.mjs +0 -5
  411. package/dist/renderer-D0q2VyJR.mjs +0 -5
  412. package/dist/renderer-D6NXn3Ky.mjs +0 -5
  413. package/dist/renderer-D9bp2jor.mjs +0 -5
  414. package/dist/renderer-DEzIOIB7.mjs +0 -5
  415. package/dist/renderer-DSSTVulw.mjs +0 -5
  416. package/dist/renderer-DUmTURPu.mjs +0 -5
  417. package/dist/renderer-DXCAgI9m.mjs +0 -5
  418. package/dist/renderer-DZ9j3fQj.mjs +0 -5
  419. package/dist/renderer-Dd1G_VKM.mjs +0 -5
  420. package/dist/renderer-Dee8079X.mjs +0 -5
  421. package/dist/renderer-DgWh5noB.mjs +0 -5
  422. package/dist/renderer-DuD9QRix.mjs +0 -5
  423. package/dist/renderer-KtG5p44R.mjs +0 -5
  424. package/dist/renderer-TyZu7nQ2.mjs.map +0 -1
  425. package/dist/renderer-fdVdNIhL.mjs +0 -5
  426. package/dist/renderer-gBKWL0_E.mjs +0 -5
  427. package/dist/renderer-hmWhsR6C.mjs +0 -5
  428. package/dist/renderer-jkL9FU2W.mjs +0 -6
  429. package/dist/renderer-yAWv-daq.mjs +0 -5
@@ -1,7 +1,7 @@
1
- import { Ot as getMediaType, in as takeRenderDiagnostics, on as updateClockSignals } from "./dist-fjKpBYkc.mjs";
1
+ import { Ot as getMediaType, an as takeRenderDiagnostics, sn as updateClockSignals } from "./dist-ClyC_d66.mjs";
2
2
  import { i as registerWebGPURenderer, t as audioRegistry } from "./renderer-BSitV56h.mjs";
3
- import { A as ensureDevice, F as getRenderer2D, H as lutStore, I as initHeadlessWebGPU, L as inputStore, W as mediaDecoderCache, et as shaderStore, g as WebGPUAudioProcessor, p as SlugFontCache, rt as textureCache, s as NodeSurfaceProvider, v as clearAllVideoCache, y as clearHeadlessFonts } from "./dist-DRB6Vg5u.mjs";
4
- import { i as mixAudioTracks, m as preloadCompositionFonts, r as drawCompositionTree, t as compositionStateStore } from "./dist-Cl0mvShy.mjs";
3
+ import { A as ensureDevice, F as getRenderer2D, H as lutStore, I as initHeadlessWebGPU, L as inputStore, W as mediaDecoderCache, et as shaderStore, g as WebGPUAudioProcessor, p as SlugFontCache, rt as textureCache, s as NodeSurfaceProvider, v as clearAllVideoCache, y as clearHeadlessFonts } from "./dist-CspOG4V1.mjs";
4
+ import { i as mixAudioTracks, m as preloadCompositionFonts, r as drawCompositionTree, t as compositionStateStore } from "./dist-CxGfrigI.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { AudioSample, AudioSampleSource, FilePathTarget, Mp3OutputFormat, Mp4OutputFormat, Output, QUALITY_HIGH, QUALITY_LOW, QUALITY_VERY_HIGH, QUALITY_VERY_LOW, VideoSample, VideoSampleSource, WebMOutputFormat } from "mediabunny";
7
7
  import fs from "node:fs";
@@ -14,16 +14,51 @@ import pino from "pino";
14
14
  import * as webcodecs from "@napi-rs/webcodecs";
15
15
  import { VideoFrame } from "@napi-rs/webcodecs";
16
16
  import { fileURLToPath, pathToFileURL } from "node:url";
17
- import { registerMediabunnyServer } from "@mediabunny/server";
18
17
  import { exec, spawn } from "node:child_process";
19
18
  import sharp from "sharp";
19
+ import { registerMediabunnyServer } from "@mediabunny/server";
20
20
 
21
- //#region ../renderer/dist/bootstrap-mediabunny-BgWuVtxx.mjs
22
- const rendererLogger = pino({
23
- level: typeof process !== "undefined" && process.env?.LOG_LEVEL || "info",
21
+ //#region ../renderer/dist/headless-webgpu-renderer-BIYZ_h9V.mjs
22
+ const env = typeof process !== "undefined" ? process.env : void 0;
23
+ /**
24
+ * "json" (pino lines, for log collectors) or "text" (one short line each, for
25
+ * people and agents reading a terminal). `FRAMEFIELDS_LOG_FORMAT` picks one;
26
+ * otherwise production is JSON and everything else text.
27
+ */
28
+ function resolveLogFormat(vars = env) {
29
+ const format = vars?.FRAMEFIELDS_LOG_FORMAT?.toLowerCase();
30
+ if (format === "json" || format === "text") return format;
31
+ return vars?.NODE_ENV === "production" ? "json" : "text";
32
+ }
33
+ const LEVEL_TAGS = {
34
+ 40: "warn: ",
35
+ 50: "error: ",
36
+ 60: "fatal: "
37
+ };
38
+ /**
39
+ * Turns pino's JSON lines into `[framefields] Rendered 40% (…)`: the message
40
+ * without its `[Component]` prefix, the level only for warnings and errors,
41
+ * and an error's message (its stack reaches the caller with the throw).
42
+ */
43
+ function textLogStream(write = (line) => process.stderr.write(line)) {
44
+ return { write(json) {
45
+ let entry;
46
+ try {
47
+ entry = JSON.parse(json);
48
+ } catch {
49
+ write(json);
50
+ return;
51
+ }
52
+ const msg = String(entry.msg ?? "").replace(/^\[[^\]]+\]\s*/, "");
53
+ write(`[framefields] ${LEVEL_TAGS[entry.level ?? 0] ?? ""}${msg}${entry.err?.message ? `: ${entry.err.message}` : ""}\n`);
54
+ } };
55
+ }
56
+ const options = {
57
+ level: env?.LOG_LEVEL || "info",
24
58
  timestamp: pino.stdTimeFunctions.isoTime,
25
59
  base: { component: "renderer" }
26
- });
60
+ };
61
+ const rendererLogger = resolveLogFormat() === "text" ? pino(options, textLogStream()) : pino(options);
27
62
  /**
28
63
  * Preloads only the fonts (and emoji) a VirtualMediaData tree's text uses, so
29
64
  * typography renders correctly on Node.js without loading its media. Shared
@@ -53,12 +88,12 @@ var DmaStagingRing = class {
53
88
  device;
54
89
  slots;
55
90
  isDestroyed = false;
56
- constructor(device, options) {
91
+ constructor(device, options$1) {
57
92
  this.device = device;
58
- this.width = options.width;
59
- this.height = options.height;
60
- this.capacity = Math.max(2, options.capacity ?? 2);
61
- this.format = options.format ?? "rgba8unorm";
93
+ this.width = options$1.width;
94
+ this.height = options$1.height;
95
+ this.capacity = Math.max(2, options$1.capacity ?? 2);
96
+ this.format = options$1.format ?? "rgba8unorm";
62
97
  this.unpaddedBytesPerRow = this.width * 4;
63
98
  const rowAlignment = 256;
64
99
  this.bytesPerRow = Math.ceil(this.unpaddedBytesPerRow / rowAlignment) * rowAlignment;
@@ -242,237 +277,237 @@ const BUILTIN_NODE_RENDERERS = [
242
277
  {
243
278
  packageName: "@framefields/node-lut",
244
279
  ops: ["ApplyLUT"],
245
- load: () => import("./renderer-BHpJ1e15.mjs")
280
+ load: () => import("./renderer-Cd87JOjP.mjs")
246
281
  },
247
282
  {
248
283
  packageName: "@framefields/node-ascii",
249
284
  ops: ["Ascii"],
250
- load: () => import("./renderer-CduDa1qf.mjs")
285
+ load: () => import("./renderer-B0gPTXhe.mjs")
251
286
  },
252
287
  {
253
288
  packageName: "@framefields/node-audio-compressor",
254
289
  ops: ["AudioCompressor"],
255
- load: () => import("./renderer-fdVdNIhL.mjs")
290
+ load: () => import("./renderer-D2_0g6Oi.mjs")
256
291
  },
257
292
  {
258
293
  packageName: "@framefields/node-audio-delay",
259
294
  ops: ["AudioDelay"],
260
- load: () => import("./renderer-Bn-WnRh9.mjs")
295
+ load: () => import("./renderer-D62FwolD.mjs")
261
296
  },
262
297
  {
263
298
  packageName: "@framefields/node-audio-fade",
264
299
  ops: ["AudioFade"],
265
- load: () => import("./renderer-D9bp2jor.mjs")
300
+ load: () => import("./renderer-DqcUNP8J.mjs")
266
301
  },
267
302
  {
268
303
  packageName: "@framefields/node-audio-noise-gate",
269
304
  ops: ["AudioNoiseGate"],
270
- load: () => import("./renderer-Dd1G_VKM.mjs")
305
+ load: () => import("./renderer-C_B_4Bl0.mjs")
271
306
  },
272
307
  {
273
308
  packageName: "@framefields/node-audio-parametric-eq",
274
309
  ops: ["AudioParametricEq"],
275
- load: () => import("./renderer-CuoxvPsX.mjs")
310
+ load: () => import("./renderer-DDNY9N7I.mjs")
276
311
  },
277
312
  {
278
313
  packageName: "@framefields/node-audio-reverb",
279
314
  ops: ["AudioReverb"],
280
- load: () => import("./renderer-yAWv-daq.mjs")
315
+ load: () => import("./renderer-C7NkSvUz.mjs")
281
316
  },
282
317
  {
283
318
  packageName: "@framefields/node-audio-signal-extractor",
284
319
  ops: ["AudioSignalExtractor"],
285
- load: () => import("./renderer-jkL9FU2W.mjs")
320
+ load: () => import("./renderer-Cev6orIK.mjs")
286
321
  },
287
322
  {
288
323
  packageName: "@framefields/node-blur",
289
324
  ops: ["Blur"],
290
- load: () => import("./renderer-BHZie6Pa.mjs")
325
+ load: () => import("./renderer-BuY5ypB2.mjs")
291
326
  },
292
327
  {
293
328
  packageName: "@framefields/node-camera-parallax-3d",
294
329
  ops: ["CameraParallax3D"],
295
- load: () => import("./renderer-BZWiY6Jw.mjs")
330
+ load: () => import("./renderer-Dwu_zfdL.mjs")
296
331
  },
297
332
  {
298
333
  packageName: "@framefields/node-canvas-generator",
299
334
  ops: ["CanvasGenerator"],
300
- load: () => import("./renderer-wFyrVuuj.mjs")
335
+ load: () => import("./renderer-CDOobs18.mjs")
301
336
  },
302
337
  {
303
338
  packageName: "@framefields/node-channel-merger",
304
339
  ops: ["ChannelMerger"],
305
- load: () => import("./renderer-BhZutM8K.mjs")
340
+ load: () => import("./renderer-Cv4lchUP.mjs")
306
341
  },
307
342
  {
308
343
  packageName: "@framefields/node-channel-splitter",
309
344
  ops: ["ChannelSplitter"],
310
- load: () => import("./renderer-Cfto0m0-.mjs")
345
+ load: () => import("./renderer-Bkrk0M0r.mjs")
311
346
  },
312
347
  {
313
348
  packageName: "@framefields/node-color-balance",
314
349
  ops: ["ColorBalance"],
315
- load: () => import("./renderer-DY8fPeH3.mjs")
350
+ load: () => import("./renderer-CJ4bxCld.mjs")
316
351
  },
317
352
  {
318
353
  packageName: "@framefields/node-colorkey",
319
354
  ops: ["ColorKey"],
320
- load: () => import("./renderer-B3EEYpx6.mjs")
355
+ load: () => import("./renderer-BHAE_dKq.mjs")
321
356
  },
322
357
  {
323
358
  packageName: "@framefields/node-compositor",
324
359
  ops: ["Compositor"],
325
- load: () => import("./renderer-B8v8iEkB.mjs")
360
+ load: () => import("./renderer-BV48PFjX.mjs")
326
361
  },
327
362
  {
328
363
  packageName: "@framefields/node-contour",
329
364
  ops: ["Contour"],
330
- load: () => import("./renderer-CNS8LA2_.mjs")
365
+ load: () => import("./renderer-gRMkQabv.mjs")
331
366
  },
332
367
  {
333
368
  packageName: "@framefields/node-corner-pin",
334
369
  ops: ["CornerPin"],
335
- load: () => import("./renderer-DUmTURPu.mjs")
370
+ load: () => import("./renderer-BAhZeUUn.mjs")
336
371
  },
337
372
  {
338
373
  packageName: "@framefields/node-crop",
339
374
  ops: ["Crop"],
340
- load: () => import("./renderer--IHe-yqK.mjs")
375
+ load: () => import("./renderer-CrdG7trA.mjs")
341
376
  },
342
377
  {
343
378
  packageName: "@framefields/node-crt",
344
379
  ops: ["CRT"],
345
- load: () => import("./renderer-DkYiOWPJ.mjs")
380
+ load: () => import("./renderer-DyyIXLQK.mjs")
346
381
  },
347
382
  {
348
383
  packageName: "@framefields/node-curves",
349
384
  ops: ["Curves"],
350
- load: () => import("./renderer-DuD9QRix.mjs")
385
+ load: () => import("./renderer-GvSRoQje.mjs")
351
386
  },
352
387
  {
353
388
  packageName: "@framefields/node-datamosh",
354
389
  ops: ["Datamosh"],
355
- load: () => import("./renderer-BtJ6XYN7.mjs")
390
+ load: () => import("./renderer-BPixWnmY.mjs")
356
391
  },
357
392
  {
358
393
  packageName: "@framefields/node-deflicker",
359
394
  ops: ["TemporalDeflicker", "Deflicker"],
360
- load: () => import("./renderer-C_5nfVce.mjs")
395
+ load: () => import("./renderer-BfZquJrW.mjs")
361
396
  },
362
397
  {
363
398
  packageName: "@framefields/node-displacement-map",
364
399
  ops: ["DisplacementMap"],
365
- load: () => import("./renderer-DXCAgI9m.mjs")
400
+ load: () => import("./renderer-CY89dTFR.mjs")
366
401
  },
367
402
  {
368
403
  packageName: "@framefields/node-dither",
369
404
  ops: ["Dither"],
370
- load: () => import("./renderer-DOZJeWM4.mjs")
405
+ load: () => import("./renderer-EZp_IIPK.mjs")
371
406
  },
372
407
  {
373
408
  packageName: "@framefields/node-extract-frame",
374
409
  ops: ["ExtractFrame"],
375
- load: () => import("./renderer-DA1brg35.mjs")
410
+ load: () => import("./renderer-ByCX4JYg.mjs")
376
411
  },
377
412
  {
378
413
  packageName: "@framefields/node-extract-lut",
379
414
  ops: ["ExtractLUT"],
380
- load: () => import("./renderer-CduL1AOK.mjs")
415
+ load: () => import("./renderer-DKfwlE4e.mjs")
381
416
  },
382
417
  {
383
418
  packageName: "@framefields/node-film-grain",
384
419
  ops: ["FilmGrain"],
385
- load: () => import("./renderer-gBKWL0_E.mjs")
420
+ load: () => import("./renderer-CKp97tSQ.mjs")
386
421
  },
387
422
  {
388
423
  packageName: "@framefields/node-flip",
389
424
  ops: ["Flip"],
390
- load: () => import("./renderer-CxAgpBrJ.mjs")
425
+ load: () => import("./renderer-BePHurAU.mjs")
391
426
  },
392
427
  {
393
428
  packageName: "@framefields/node-gooey",
394
429
  ops: ["Gooey"],
395
- load: () => import("./renderer-BzgnTEvf.mjs")
430
+ load: () => import("./renderer-X0eKSD7v.mjs")
396
431
  },
397
432
  {
398
433
  packageName: "@framefields/node-gradient-map",
399
434
  ops: ["GradientMap"],
400
- load: () => import("./renderer-CG4TmDWH.mjs")
435
+ load: () => import("./renderer-CCGzT6bX.mjs")
401
436
  },
402
437
  {
403
438
  packageName: "@framefields/node-halftone-screen",
404
439
  ops: ["HalftoneScreen"],
405
- load: () => import("./renderer-B3Si5IB4.mjs")
440
+ load: () => import("./renderer-Cewf6UPh.mjs")
406
441
  },
407
442
  {
408
443
  packageName: "@framefields/node-high-pass",
409
444
  ops: ["HighPass"],
410
- load: () => import("./renderer-Dee8079X.mjs")
445
+ load: () => import("./renderer-B_xSsTuy.mjs")
411
446
  },
412
447
  {
413
448
  packageName: "@framefields/node-iridescence",
414
449
  ops: ["Iridescence"],
415
- load: () => import("./renderer-DVaVVz-D.mjs")
450
+ load: () => import("./renderer-B3e4LSE6.mjs")
416
451
  },
417
452
  {
418
453
  packageName: "@framefields/node-kaleidoscope",
419
454
  ops: ["Kaleidoscope"],
420
- load: () => import("./renderer-q971j1BW.mjs")
455
+ load: () => import("./renderer-apeDrNXM.mjs")
421
456
  },
422
457
  {
423
458
  packageName: "@framefields/node-kenburns",
424
459
  ops: ["KenBurns"],
425
- load: () => import("./renderer-BqHvDAUe.mjs")
460
+ load: () => import("./renderer-DbzrVHEE.mjs")
426
461
  },
427
462
  {
428
463
  packageName: "@framefields/node-layer-style",
429
464
  ops: ["LayerStyle"],
430
- load: () => import("./renderer-DEzIOIB7.mjs")
465
+ load: () => import("./renderer-DqvFhEQj.mjs")
431
466
  },
432
467
  {
433
468
  packageName: "@framefields/node-levels",
434
469
  ops: ["Levels"],
435
- load: () => import("./renderer-BH8vZKmX.mjs")
470
+ load: () => import("./renderer-DF_ONJ3v.mjs")
436
471
  },
437
472
  {
438
473
  packageName: "@framefields/node-liquify",
439
474
  ops: ["Liquify"],
440
- load: () => import("./renderer-D6NXn3Ky.mjs")
475
+ load: () => import("./renderer-BNYZY3FE.mjs")
441
476
  },
442
477
  {
443
478
  packageName: "@framefields/node-mask-math",
444
479
  ops: ["MaskMath"],
445
- load: () => import("./renderer-DSSTVulw.mjs")
480
+ load: () => import("./renderer-Pc8dyNXt.mjs")
446
481
  },
447
482
  {
448
483
  packageName: "@framefields/node-mesh-warp",
449
484
  ops: ["MeshWarp"],
450
- load: () => import("./renderer-DZ9j3fQj.mjs")
485
+ load: () => import("./renderer-B_M_yhTc.mjs")
451
486
  },
452
487
  {
453
488
  packageName: "@framefields/node-modulate",
454
489
  ops: ["Modulate"],
455
- load: () => import("./renderer-BPbM_6WR.mjs")
490
+ load: () => import("./renderer-CuOjhtoo.mjs")
456
491
  },
457
492
  {
458
493
  packageName: "@framefields/node-noise-generator",
459
494
  ops: ["NoiseGenerator"],
460
- load: () => import("./renderer-B4JmNa_T.mjs")
495
+ load: () => import("./renderer-DwVOxdzC.mjs")
461
496
  },
462
497
  {
463
498
  packageName: "@framefields/node-op-art",
464
499
  ops: ["OpArt"],
465
- load: () => import("./renderer-CoX23zo_.mjs")
500
+ load: () => import("./renderer-DaqWTx7s.mjs")
466
501
  },
467
502
  {
468
503
  packageName: "@framefields/node-paint",
469
504
  ops: ["Paint"],
470
- load: () => import("./renderer-BPJ79b47.mjs")
505
+ load: () => import("./renderer-CIuxV2q1.mjs")
471
506
  },
472
507
  {
473
508
  packageName: "@framefields/node-painterly",
474
509
  ops: ["Painterly"],
475
- load: () => import("./renderer-DqgduGiO.mjs")
510
+ load: () => import("./renderer-BwpgDLYO.mjs")
476
511
  },
477
512
  {
478
513
  packageName: "@framefields/node-particles",
@@ -482,67 +517,67 @@ const BUILTIN_NODE_RENDERERS = [
482
517
  {
483
518
  packageName: "@framefields/node-patch-heal",
484
519
  ops: ["PatchHeal"],
485
- load: () => import("./renderer-gbBgGPNL.mjs")
520
+ load: () => import("./renderer-DjwITRvg.mjs")
486
521
  },
487
522
  {
488
523
  packageName: "@framefields/node-pixelate",
489
524
  ops: ["Pixelate"],
490
- load: () => import("./renderer-Ai5nZsof.mjs")
525
+ load: () => import("./renderer-Za4D9hej.mjs")
491
526
  },
492
527
  {
493
528
  packageName: "@framefields/node-posterize",
494
529
  ops: ["Posterize"],
495
- load: () => import("./renderer-BZvWlGsa.mjs")
530
+ load: () => import("./renderer-DTw-W0Yz.mjs")
496
531
  },
497
532
  {
498
533
  packageName: "@framefields/node-procedural-vfx",
499
534
  ops: ["ProceduralVFX"],
500
- load: () => import("./renderer-D-e3vDnO.mjs")
535
+ load: () => import("./renderer-DzSMeQBC.mjs")
501
536
  },
502
537
  {
503
538
  packageName: "@framefields/node-refine-edge",
504
539
  ops: ["RefineEdge"],
505
- load: () => import("./renderer-B16iwR0_.mjs")
540
+ load: () => import("./renderer-KP7Ita9g.mjs")
506
541
  },
507
542
  {
508
543
  packageName: "@framefields/node-refraction-caustics",
509
544
  ops: ["RefractionCaustics3D"],
510
- load: () => import("./renderer-Edn9xltT.mjs")
545
+ load: () => import("./renderer-BjCHW9Jp.mjs")
511
546
  },
512
547
  {
513
548
  packageName: "@framefields/node-relight-3d",
514
549
  ops: ["Relight3D"],
515
- load: () => import("./renderer-KtG5p44R.mjs")
550
+ load: () => import("./renderer-DlYchp1v.mjs")
516
551
  },
517
552
  {
518
553
  packageName: "@framefields/node-resizer-scaler",
519
554
  ops: ["ResizerScaler"],
520
- load: () => import("./renderer-BZCLdb8F.mjs")
555
+ load: () => import("./renderer-BBAbZfBl.mjs")
521
556
  },
522
557
  {
523
558
  packageName: "@framefields/node-rgb-split",
524
559
  ops: ["RGBSplit"],
525
- load: () => import("./renderer-CjTxu89O.mjs")
560
+ load: () => import("./renderer-B1QREs7J.mjs")
526
561
  },
527
562
  {
528
563
  packageName: "@framefields/node-rotate",
529
564
  ops: ["Rotate"],
530
- load: () => import("./renderer-CAtXDNsh.mjs")
565
+ load: () => import("./renderer-CnHsMLIv.mjs")
531
566
  },
532
567
  {
533
568
  packageName: "@framefields/node-selective-color",
534
569
  ops: ["SelectiveColor"],
535
- load: () => import("./renderer-D-cWBX0r.mjs")
570
+ load: () => import("./renderer-h6ev1ogx.mjs")
536
571
  },
537
572
  {
538
573
  packageName: "@framefields/node-shadows-highlights",
539
574
  ops: ["ShadowsHighlights"],
540
- load: () => import("./renderer-D0q2VyJR.mjs")
575
+ load: () => import("./renderer-DxBav2bE.mjs")
541
576
  },
542
577
  {
543
578
  packageName: "@framefields/node-shape-generator",
544
579
  ops: ["ShapeGenerator"],
545
- load: () => import("./renderer-C2ZIAhdJ.mjs")
580
+ load: () => import("./renderer-BkWd4-YO.mjs")
546
581
  },
547
582
  {
548
583
  packageName: "@framefields/node-signal-gate",
@@ -552,37 +587,37 @@ const BUILTIN_NODE_RENDERERS = [
552
587
  {
553
588
  packageName: "@framefields/node-stereo-panning",
554
589
  ops: ["StereoPanning"],
555
- load: () => import("./renderer-hmWhsR6C.mjs")
590
+ load: () => import("./renderer-Cu5MFgbk.mjs")
556
591
  },
557
592
  {
558
593
  packageName: "@framefields/node-tile-offset",
559
594
  ops: ["TileOffset"],
560
- load: () => import("./renderer-DgWh5noB.mjs")
595
+ load: () => import("./renderer-CoxuAr7b.mjs")
561
596
  },
562
597
  {
563
598
  packageName: "@framefields/node-toon",
564
599
  ops: ["Toon"],
565
- load: () => import("./renderer-Cz9fzS11.mjs")
600
+ load: () => import("./renderer-DaSxr9fM.mjs")
566
601
  },
567
602
  {
568
603
  packageName: "@framefields/node-trails",
569
604
  ops: ["Trails"],
570
- load: () => import("./renderer-CoO2j8AC.mjs")
605
+ load: () => import("./renderer-DILUmb-e.mjs")
571
606
  },
572
607
  {
573
608
  packageName: "@framefields/node-unsharp-mask",
574
609
  ops: ["UnsharpMask"],
575
- load: () => import("./renderer-Cvd3oIJQ.mjs")
610
+ load: () => import("./renderer-BvOQgFHo.mjs")
576
611
  },
577
612
  {
578
613
  packageName: "@framefields/node-vignette",
579
614
  ops: ["Vignette"],
580
- load: () => import("./renderer-Cie7KKeQ.mjs")
615
+ load: () => import("./renderer-BSvubMvI.mjs")
581
616
  },
582
617
  {
583
618
  packageName: "@framefields/node-vision",
584
619
  ops: ["Vision"],
585
- load: () => import("./renderer-BARst3ZD.mjs")
620
+ load: () => import("./renderer-ezRCmU09.mjs")
586
621
  }
587
622
  ];
588
623
  /**
@@ -932,9 +967,217 @@ const bootstrapMediabunny = () => {
932
967
  registerMediabunnyServer(videoCodecServerOptions(isAMD()));
933
968
  for (const key of Object.keys(webcodecs)) if (typeof globalThis[key] === "undefined") globalThis[key] = webcodecs[key];
934
969
  };
935
-
936
- //#endregion
937
- //#region ../renderer/dist/headless-webgpu-renderer-1QAxgoPn.mjs
970
+ const LOG_PREFIX = "[HeadlessWebGPURenderer]";
971
+ /** A milestone reached sooner than this after the last line is not logged. */
972
+ const MIN_LOG_GAP_MS = 1e3;
973
+ /**
974
+ * Quiet time before the first "still …" line of a phase. Each one doubles it
975
+ * up to the cap, so a long phase adds a few lines rather than one a minute.
976
+ */
977
+ const HEARTBEAT_FIRST_MS = 1e4;
978
+ const HEARTBEAT_MAX_MS = 5 * 6e4;
979
+ const ACTIVITY = {
980
+ prepare: "preparing",
981
+ render: "rendering",
982
+ audio: "mixing audio",
983
+ "audio-encode": "encoding audio",
984
+ mux: "muxing",
985
+ convert: "converting to GIF",
986
+ done: "finishing"
987
+ };
988
+ /**
989
+ * Reports a render's progress to the log and to `onProgress`.
990
+ *
991
+ * The log stays short whatever the length of the film, so it fits an agent's
992
+ * context: one line per phase, frame lines only at percent milestones, and a
993
+ * "still …" line when a phase goes quiet, backing off from 10 s to 5 min.
994
+ * `onProgress` gets every update; the "still …" lines are log-only, so a stall
995
+ * detector fed by `onProgress` still sees a hang.
996
+ */
997
+ var RenderReporter = class {
998
+ renderId;
999
+ totalFrames;
1000
+ onProgress;
1001
+ milestonePercent;
1002
+ log;
1003
+ now;
1004
+ startedAt;
1005
+ phaseMs = /* @__PURE__ */ new Map();
1006
+ phase = "prepare";
1007
+ phaseStartedAt;
1008
+ frame = 0;
1009
+ phaseProgress;
1010
+ detail;
1011
+ lastMilestone = 0;
1012
+ /** Last phase or milestone line; "still …" lines don't count. */
1013
+ lastLogAt;
1014
+ heartbeatMs = HEARTBEAT_FIRST_MS;
1015
+ heartbeat;
1016
+ constructor(options$1) {
1017
+ this.renderId = options$1.renderId;
1018
+ this.totalFrames = options$1.totalFrames;
1019
+ this.onProgress = options$1.onProgress;
1020
+ this.milestonePercent = options$1.milestonePercent ?? 10;
1021
+ this.log = options$1.log ?? rendererLogger;
1022
+ this.now = options$1.now ?? (() => performance.now());
1023
+ this.startedAt = this.now();
1024
+ this.phaseStartedAt = this.startedAt;
1025
+ this.lastLogAt = this.startedAt;
1026
+ }
1027
+ /** Starts a phase: logs `message` and emits a progress event. */
1028
+ stage(phase, message, fields = {}) {
1029
+ this.closePhase();
1030
+ this.phase = phase;
1031
+ this.phaseProgress = void 0;
1032
+ this.detail = void 0;
1033
+ this.heartbeatMs = HEARTBEAT_FIRST_MS;
1034
+ if (phase !== "render" && phase !== "prepare") this.frame = this.totalFrames;
1035
+ this.info(message, fields);
1036
+ this.emit();
1037
+ }
1038
+ /** Records a finished frame; logs at each milestone. */
1039
+ frameDone(frame) {
1040
+ this.frame = frame;
1041
+ const percent = frame / this.totalFrames * 100;
1042
+ const milestone = frame >= this.totalFrames ? 100 : Math.floor(percent / this.milestonePercent) * this.milestonePercent;
1043
+ const { fps, etaSec } = this.rate();
1044
+ if (milestone > this.lastMilestone) {
1045
+ this.lastMilestone = milestone;
1046
+ if (milestone === 100 || this.now() - this.lastLogAt >= MIN_LOG_GAP_MS) {
1047
+ const tail = milestone === 100 ? `in ${formatDuration(this.now() - this.phaseStartedAt)}` : `eta ${formatDuration(etaSec * 1e3)}`;
1048
+ this.info(`Rendered ${milestone}% (${frame}/${this.totalFrames} frames) · ${fps.toFixed(1)} fps · ${tail}`, {
1049
+ fps: round1(fps),
1050
+ etaSec
1051
+ });
1052
+ }
1053
+ }
1054
+ this.emit({
1055
+ fps: round1(fps),
1056
+ etaSec
1057
+ });
1058
+ }
1059
+ /** Updates what the current phase is doing; shown in "still …" lines. */
1060
+ update(detail, phaseProgress) {
1061
+ this.detail = detail;
1062
+ this.phaseProgress = phaseProgress;
1063
+ this.emit();
1064
+ }
1065
+ /** Logs the summary and emits the "done" event. */
1066
+ finish(fields = {}) {
1067
+ this.closePhase();
1068
+ this.phase = "done";
1069
+ this.frame = this.totalFrames;
1070
+ this.stopHeartbeat();
1071
+ const total = this.now() - this.startedAt;
1072
+ const parts = [...this.phaseMs].map(([phase, ms]) => `${phase} ${formatDuration(ms)}`);
1073
+ const size = fields.bytes !== void 0 ? ` (${formatBytes(fields.bytes)})` : "";
1074
+ this.log.info({
1075
+ renderId: this.renderId,
1076
+ phase: "done",
1077
+ elapsedMs: Math.round(total),
1078
+ phaseMs: Object.fromEntries([...this.phaseMs].map(([phase, ms]) => [phase, Math.round(ms)])),
1079
+ ...fields
1080
+ }, `${LOG_PREFIX} Done in ${formatDuration(total)}${size}: ${parts.join(" · ")}`);
1081
+ this.emit();
1082
+ }
1083
+ /** Logs which phase the render stopped in. */
1084
+ fail(error, aborted) {
1085
+ this.stopHeartbeat();
1086
+ const elapsed = formatDuration(this.now() - this.startedAt);
1087
+ const fields = {
1088
+ renderId: this.renderId,
1089
+ phase: this.phase,
1090
+ frame: this.frame,
1091
+ totalFrames: this.totalFrames,
1092
+ elapsedMs: Math.round(this.now() - this.startedAt)
1093
+ };
1094
+ if (aborted) this.log.warn(fields, `${LOG_PREFIX} Aborted while ${ACTIVITY[this.phase]} after ${elapsed}`);
1095
+ else this.log.error({
1096
+ ...fields,
1097
+ err: error
1098
+ }, `${LOG_PREFIX} Failed while ${ACTIVITY[this.phase]} after ${elapsed}`);
1099
+ }
1100
+ /** Stops the "still …" timer. Safe to call more than once. */
1101
+ dispose() {
1102
+ this.stopHeartbeat();
1103
+ }
1104
+ closePhase() {
1105
+ const now = this.now();
1106
+ this.phaseMs.set(this.phase, (this.phaseMs.get(this.phase) ?? 0) + (now - this.phaseStartedAt));
1107
+ this.phaseStartedAt = now;
1108
+ }
1109
+ rate() {
1110
+ const seconds = Math.max(.001, (this.now() - this.phaseStartedAt) / 1e3);
1111
+ const fps = this.frame / seconds;
1112
+ return {
1113
+ fps,
1114
+ etaSec: Math.round((this.totalFrames - this.frame) / Math.max(fps, .001))
1115
+ };
1116
+ }
1117
+ info(message, fields = {}) {
1118
+ this.log.info({
1119
+ renderId: this.renderId,
1120
+ phase: this.phase,
1121
+ frame: this.frame,
1122
+ totalFrames: this.totalFrames,
1123
+ ...fields
1124
+ }, `${LOG_PREFIX} ${message}`);
1125
+ this.lastLogAt = this.now();
1126
+ this.armHeartbeat();
1127
+ }
1128
+ emit(extra = {}) {
1129
+ this.onProgress?.({
1130
+ phase: this.phase,
1131
+ frame: this.frame,
1132
+ totalFrames: this.totalFrames,
1133
+ elapsedMs: Math.round(this.now() - this.startedAt),
1134
+ ...this.phaseProgress !== void 0 && { phaseProgress: this.phaseProgress },
1135
+ ...this.detail !== void 0 && { detail: this.detail },
1136
+ ...extra
1137
+ });
1138
+ }
1139
+ armHeartbeat() {
1140
+ this.stopHeartbeat();
1141
+ this.heartbeat = setTimeout(() => this.beat(), this.heartbeatMs);
1142
+ this.heartbeat.unref?.();
1143
+ }
1144
+ beat() {
1145
+ const inPhase = formatDuration(this.now() - this.phaseStartedAt);
1146
+ let what = "";
1147
+ if (this.phase === "render") what = ` (frame ${this.frame}/${this.totalFrames})`;
1148
+ else if (this.detail || this.phaseProgress !== void 0) what = ` (${[this.phaseProgress !== void 0 ? `${Math.floor(this.phaseProgress * 100)}%` : "", this.detail].filter(Boolean).join(", ")})`;
1149
+ this.log.info({
1150
+ renderId: this.renderId,
1151
+ phase: this.phase,
1152
+ frame: this.frame,
1153
+ totalFrames: this.totalFrames
1154
+ }, `${LOG_PREFIX} Still ${ACTIVITY[this.phase]}${what}, ${inPhase} in this phase`);
1155
+ this.heartbeatMs = Math.min(this.heartbeatMs * 2, HEARTBEAT_MAX_MS);
1156
+ this.armHeartbeat();
1157
+ }
1158
+ stopHeartbeat() {
1159
+ if (this.heartbeat) clearTimeout(this.heartbeat);
1160
+ this.heartbeat = void 0;
1161
+ }
1162
+ };
1163
+ /** "4.2s", "2m 05s", "1h 02m". */
1164
+ function formatDuration(ms) {
1165
+ const s = Math.max(0, ms) / 1e3;
1166
+ if (s < 60) return `${s.toFixed(1)}s`;
1167
+ const total = Math.round(s);
1168
+ const h = Math.floor(total / 3600);
1169
+ const m = Math.floor(total % 3600 / 60);
1170
+ const sec = total % 60;
1171
+ if (h > 0) return `${h}h ${String(m).padStart(2, "0")}m`;
1172
+ return `${m}m ${String(sec).padStart(2, "0")}s`;
1173
+ }
1174
+ function formatBytes(bytes) {
1175
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1176
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
1177
+ }
1178
+ function round1(n) {
1179
+ return Math.round(n * 10) / 10;
1180
+ }
938
1181
  const DEFAULTS = {
939
1182
  blackPixelThreshold: .1,
940
1183
  blackFrameRatio: .98,
@@ -954,9 +1197,9 @@ var FrameInspector = class {
954
1197
  sameAsPrevious = [];
955
1198
  lumaSum = 0;
956
1199
  previous = null;
957
- constructor(options = {}) {
958
- this.blackLuma = (options.blackPixelThreshold ?? DEFAULTS.blackPixelThreshold) * 255;
959
- this.blackRatio = options.blackFrameRatio ?? DEFAULTS.blackFrameRatio;
1200
+ constructor(options$1 = {}) {
1201
+ this.blackLuma = (options$1.blackPixelThreshold ?? DEFAULTS.blackPixelThreshold) * 255;
1202
+ this.blackRatio = options$1.blackFrameRatio ?? DEFAULTS.blackFrameRatio;
960
1203
  }
961
1204
  get frameCount() {
962
1205
  return this.black.length;
@@ -989,9 +1232,9 @@ var FrameInspector = class {
989
1232
  this.sameAsPrevious.push(same);
990
1233
  this.previous = luma;
991
1234
  }
992
- stats(expectedFrames, encodedFrames, fps, width, height, options = {}) {
993
- const minBlack = Math.max(1, Math.round((options.minBlackSec ?? DEFAULTS.minBlackSec) * fps));
994
- const minFrozen = Math.max(2, Math.round((options.minFrozenSec ?? DEFAULTS.minFrozenSec) * fps));
1235
+ stats(expectedFrames, encodedFrames, fps, width, height, options$1 = {}) {
1236
+ const minBlack = Math.max(1, Math.round((options$1.minBlackSec ?? DEFAULTS.minBlackSec) * fps));
1237
+ const minFrozen = Math.max(2, Math.round((options$1.minFrozenSec ?? DEFAULTS.minFrozenSec) * fps));
995
1238
  const blackSegments = runs(this.black, minBlack).map(([a, b]) => ({
996
1239
  startSec: a / fps,
997
1240
  endSec: b / fps
@@ -1026,7 +1269,7 @@ function runs(flags, minLength) {
1026
1269
  }
1027
1270
  const toDb = (power) => power > 0 ? 10 * Math.log10(power) : -Infinity;
1028
1271
  /** Measures a mixed audio track (one Float32Array per channel). */
1029
- function analyzeAudio(channels, sampleRate, options = {}) {
1272
+ function analyzeAudio(channels, sampleRate, options$1 = {}) {
1030
1273
  const length = channels[0]?.length ?? 0;
1031
1274
  let peak = 0;
1032
1275
  let sumSquares = 0;
@@ -1038,7 +1281,7 @@ function analyzeAudio(channels, sampleRate, options = {}) {
1038
1281
  sumSquares += v * v;
1039
1282
  }
1040
1283
  const total = length * Math.max(1, channels.length);
1041
- const silenceDbfs = options.silenceDbfs ?? DEFAULTS.silenceDbfs;
1284
+ const silenceDbfs = options$1.silenceDbfs ?? DEFAULTS.silenceDbfs;
1042
1285
  const window = Math.max(1, Math.round(sampleRate * .1));
1043
1286
  const silent = [];
1044
1287
  for (let start = 0; start < length; start += window) {
@@ -1047,7 +1290,7 @@ function analyzeAudio(channels, sampleRate, options = {}) {
1047
1290
  for (const ch of channels) for (let i = start; i < end; i++) s += ch[i] * ch[i];
1048
1291
  silent.push(toDb(s / ((end - start) * channels.length)) < silenceDbfs);
1049
1292
  }
1050
- const silentSegments = runs(silent, Math.max(1, Math.round((options.minSilenceSec ?? DEFAULTS.minSilenceSec) / .1))).map(([a, b]) => ({
1293
+ const silentSegments = runs(silent, Math.max(1, Math.round((options$1.minSilenceSec ?? DEFAULTS.minSilenceSec) / .1))).map(([a, b]) => ({
1051
1294
  startSec: a * window / sampleRate,
1052
1295
  endSec: Math.min(length, b * window) / sampleRate
1053
1296
  }));
@@ -1143,7 +1386,7 @@ function integratedLoudness(channels, sampleRate) {
1143
1386
  }
1144
1387
  /** Turn measurements and document diagnostics into a report with issues. */
1145
1388
  function buildQaReport(parts) {
1146
- const { video, audio, options = {} } = parts;
1389
+ const { video, audio, options: options$1 = {} } = parts;
1147
1390
  const issues = [];
1148
1391
  const at = (s) => `${s.startSec.toFixed(2)}–${s.endSec.toFixed(2)} s`;
1149
1392
  if (video) {
@@ -1182,13 +1425,13 @@ function buildQaReport(parts) {
1182
1425
  message: `Silence at ${at(s)}`,
1183
1426
  ...s
1184
1427
  });
1185
- if (options.targetLufs !== void 0) {
1186
- const off = audio.integratedLufs - options.targetLufs;
1187
- const tolerance = options.lufsTolerance ?? DEFAULTS.lufsTolerance;
1428
+ if (options$1.targetLufs !== void 0) {
1429
+ const off = audio.integratedLufs - options$1.targetLufs;
1430
+ const tolerance = options$1.lufsTolerance ?? DEFAULTS.lufsTolerance;
1188
1431
  if (Math.abs(off) > tolerance) issues.push({
1189
1432
  severity: "warning",
1190
1433
  code: "loudness_off_target",
1191
- message: `Integrated loudness ${audio.integratedLufs.toFixed(1)} LUFS is ${Math.abs(off).toFixed(1)} LU ${off > 0 ? "above" : "below"} the ${options.targetLufs} LUFS target`
1434
+ message: `Integrated loudness ${audio.integratedLufs.toFixed(1)} LUFS is ${Math.abs(off).toFixed(1)} LU ${off > 0 ? "above" : "below"} the ${options$1.targetLufs} LUFS target`
1192
1435
  });
1193
1436
  }
1194
1437
  }
@@ -1247,16 +1490,16 @@ var ZeroCopyWebCodecsPipeline = class {
1247
1490
  maxCycleTimeMs = 0;
1248
1491
  minCycleTimeMs = Number.POSITIVE_INFINITY;
1249
1492
  pipelineStartTime = 0;
1250
- constructor(device, options) {
1493
+ constructor(device, options$1) {
1251
1494
  this.device = device;
1252
- this.width = options.width;
1253
- this.height = options.height;
1254
- this.fps = options.fps;
1255
- this.videoSource = options.videoSource;
1256
- this.ringCapacity = Math.max(2, options.ringCapacity ?? 2);
1257
- this.colorSpace = options.colorSpace;
1258
- this.directCanvasSource = options.directCanvasSource;
1259
- this.onFrame = options.onFrame;
1495
+ this.width = options$1.width;
1496
+ this.height = options$1.height;
1497
+ this.fps = options$1.fps;
1498
+ this.videoSource = options$1.videoSource;
1499
+ this.ringCapacity = Math.max(2, options$1.ringCapacity ?? 2);
1500
+ this.colorSpace = options$1.colorSpace;
1501
+ this.directCanvasSource = options$1.directCanvasSource;
1502
+ this.onFrame = options$1.onFrame;
1260
1503
  this.stagingRing = new DmaStagingRing(device, {
1261
1504
  width: this.width,
1262
1505
  height: this.height,
@@ -1573,6 +1816,13 @@ const takeStillId = () => idleStillIds.pop() ?? `img-${randomUUID()}`;
1573
1816
  const returnStillId = (id) => {
1574
1817
  idleStillIds.push(id);
1575
1818
  };
1819
+ async function fileSize(file) {
1820
+ try {
1821
+ return (await fs$1.stat(file)).size;
1822
+ } catch {
1823
+ return;
1824
+ }
1825
+ }
1576
1826
  function toEvenDimension(n) {
1577
1827
  const v = Math.round(n);
1578
1828
  return v % 2 === 0 ? v : v + 1;
@@ -1697,13 +1947,13 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
1697
1947
  })();
1698
1948
  return HeadlessWebGPURenderer$1.initPromise;
1699
1949
  }
1700
- async renderImage(virtualMedia, frame = 0, fps = 24, options = {}) {
1950
+ async renderImage(virtualMedia, frame = 0, fps = 24, options$1 = {}) {
1701
1951
  await HeadlessWebGPURenderer$1.initialize();
1702
1952
  const width = toEvenDimension(virtualMedia.metadata.width ?? 0);
1703
1953
  const height = toEvenDimension(virtualMedia.metadata.height ?? 0);
1704
1954
  if (!width || !height) throw new Error(`Invalid dimensions: ${width}x${height}`);
1705
- const pooledId = options.renderId ? void 0 : takeStillId();
1706
- const renderId = options.renderId ?? pooledId;
1955
+ const pooledId = options$1.renderId ? void 0 : takeStillId();
1956
+ const renderId = options$1.renderId ?? pooledId;
1707
1957
  rendererLogger.debug({
1708
1958
  renderId,
1709
1959
  frame,
@@ -1771,7 +2021,7 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
1771
2021
  device.queue.submit([encoder.finish()]);
1772
2022
  const pixels = await surface.readPixels();
1773
2023
  const pixelsArr = new Uint8Array(pixels.buffer, pixels.byteOffset, pixels.byteLength);
1774
- if (options.format === "rgba") return Buffer.from(pixelsArr);
2024
+ if (options$1.format === "rgba") return Buffer.from(pixelsArr);
1775
2025
  return await sharp(Buffer.from(pixelsArr), { raw: {
1776
2026
  width,
1777
2027
  height,
@@ -1802,26 +2052,26 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
1802
2052
  /**
1803
2053
  * Renders a single frame to a PNG buffer at a specified timestamp in milliseconds or frame index.
1804
2054
  */
1805
- async renderFrame(source, options = {}) {
2055
+ async renderFrame(source, options$1 = {}) {
1806
2056
  const vm = typeof source === "object" && source !== null && "toVirtualMedia" in source ? source.toVirtualMedia() : source;
1807
- const fps = options.fps ?? (vm.metadata?.fps || 30);
1808
- const frame = options.atMs !== void 0 ? Math.round(options.atMs / 1e3 * fps) : options.frame ?? 0;
2057
+ const fps = options$1.fps ?? (vm.metadata?.fps || 30);
2058
+ const frame = options$1.atMs !== void 0 ? Math.round(options$1.atMs / 1e3 * fps) : options$1.frame ?? 0;
1809
2059
  return this.renderImage(vm, frame, fps, {
1810
- renderId: options.renderId,
1811
- format: options.format
2060
+ renderId: options$1.renderId,
2061
+ format: options$1.format
1812
2062
  });
1813
2063
  }
1814
2064
  /**
1815
2065
  * Mixes the composition's full audio timeline (clips, effects, synthesized
1816
2066
  * tracks) to stereo PCM, exactly as `renderVideo` muxes it.
1817
2067
  */
1818
- async renderAudio(virtualMedia, options = {}) {
2068
+ async renderAudio(virtualMedia, options$1 = {}) {
1819
2069
  await HeadlessWebGPURenderer$1.initialize();
1820
- const fps = options.fps ?? (virtualMedia.metadata?.fps || 30);
2070
+ const fps = options$1.fps ?? (virtualMedia.metadata?.fps || 30);
1821
2071
  await renderSemaphore.acquire();
1822
2072
  try {
1823
2073
  const device = await ensureDevice();
1824
- return await mixAudioTracks(virtualMedia, fps, options.sampleRate ?? 48e3, device, `aud-${randomUUID()}`);
2074
+ return await mixAudioTracks(virtualMedia, fps, options$1.sampleRate ?? 48e3, device, `aud-${randomUUID()}`);
1825
2075
  } finally {
1826
2076
  renderSemaphore.release();
1827
2077
  }
@@ -1961,9 +2211,9 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
1961
2211
  } catch (_) {}
1962
2212
  return maxDurationMs > 0 ? maxDurationMs : 1e3;
1963
2213
  }
1964
- async renderVideo(virtualMedia, options) {
2214
+ async renderVideo(virtualMedia, options$1) {
1965
2215
  await HeadlessWebGPURenderer$1.initialize();
1966
- const codecOption = options?.codec ?? "h264";
2216
+ const codecOption = options$1?.codec ?? "h264";
1967
2217
  const isMp3 = codecOption === "mp3";
1968
2218
  const isWebM = codecOption === "vp8" || codecOption === "vp9" || codecOption === "opus";
1969
2219
  const mediaType = getMediaType(virtualMedia);
@@ -1985,13 +2235,13 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
1985
2235
  }
1986
2236
  const totalFrames = Math.max(1, Math.round(durationMs / 1e3 * fps));
1987
2237
  const renderId = `vid-${randomUUID()}`;
1988
- const qaOptions = options?.qa === true ? {} : options?.qa ? options.qa : void 0;
2238
+ const qaOptions = options$1?.qa === true ? {} : options$1?.qa ? options$1.qa : void 0;
1989
2239
  const inspector = qaOptions ? new FrameInspector(qaOptions) : void 0;
1990
2240
  let videoQa;
1991
2241
  let audioQa;
1992
2242
  const videoCodec = codecOption === "vp9" ? "vp9" : codecOption === "vp8" ? "vp8" : "avc";
1993
- const audioCodec = options?.audioCodec ?? (isMp3 ? "mp3" : isWebM ? "opus" : "aac");
1994
- const quality = resolveQuality(options?.quality);
2243
+ const audioCodec = options$1?.audioCodec ?? (isMp3 ? "mp3" : isWebM ? "opus" : "aac");
2244
+ const quality = resolveQuality(options$1?.quality);
1995
2245
  rendererLogger.debug({
1996
2246
  renderId,
1997
2247
  totalFrames,
@@ -2001,7 +2251,24 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2001
2251
  codec: codecOption,
2002
2252
  ...renderSemaphore.stats
2003
2253
  }, "[HeadlessWebGPURenderer] Acquiring slot for video render (inline)");
2254
+ if (renderSemaphore.stats.active >= renderSemaphore.stats.max) rendererLogger.info({
2255
+ renderId,
2256
+ ...renderSemaphore.stats
2257
+ }, `[HeadlessWebGPURenderer] Waiting for a render slot (${renderSemaphore.stats.active} running, ${renderSemaphore.stats.queued} queued)`);
2004
2258
  await renderSemaphore.acquire();
2259
+ const reporter = new RenderReporter({
2260
+ renderId,
2261
+ totalFrames,
2262
+ onProgress: options$1?.onProgress
2263
+ });
2264
+ const seconds = `${(durationMs / 1e3).toFixed(1)}s`;
2265
+ reporter.stage("prepare", isAudioOnly ? `Preparing ${seconds} of audio (${audioCodec})` : `Preparing ${totalFrames} frames (${seconds}) at ${width}x${height}, ${fps} fps, ${codecOption}`, {
2266
+ width,
2267
+ height,
2268
+ fps,
2269
+ durationMs,
2270
+ codec: codecOption
2271
+ });
2005
2272
  let lastCpuUsage = process.cpuUsage();
2006
2273
  let lastCpuTime = process.hrtime.bigint();
2007
2274
  const getCpuUsage = () => {
@@ -2062,11 +2329,11 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2062
2329
  output.addAudioTrack(audioSource);
2063
2330
  let outputStarted = false;
2064
2331
  let outputFinalized = false;
2065
- const device = await ensureDevice();
2066
2332
  let surface;
2067
2333
  let renderer;
2068
2334
  let pipeline;
2069
2335
  try {
2336
+ const device = await ensureDevice();
2070
2337
  await output.start();
2071
2338
  outputStarted = true;
2072
2339
  await preloadFonts(virtualMedia, device);
@@ -2078,7 +2345,7 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2078
2345
  height,
2079
2346
  fps,
2080
2347
  videoSource,
2081
- ringCapacity: resolveRingCapacity(options?.ringCapacity),
2348
+ ringCapacity: resolveRingCapacity(options$1?.ringCapacity),
2082
2349
  onFrame: inspector ? (rgba) => inspector.inspect(rgba, width, height) : void 0
2083
2350
  });
2084
2351
  const ctx = surface && renderer ? {
@@ -2112,13 +2379,9 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2112
2379
  await lutStore.awaitAllPending(device);
2113
2380
  };
2114
2381
  await prePass(0);
2382
+ reporter.stage("render", `Rendering ${totalFrames} frames`);
2115
2383
  for (let i = 0; i < totalFrames; i++) {
2116
- options?.signal?.throwIfAborted();
2117
- if (i % 10 === 0) rendererLogger.info({
2118
- renderId,
2119
- frame: i,
2120
- totalFrames
2121
- }, `[HeadlessWebGPURenderer] Rendering frame ${i}/${totalFrames}`);
2384
+ options$1?.signal?.throwIfAborted();
2122
2385
  if (ctx && surface && renderer && pipeline) {
2123
2386
  if (i > 0 && (lutStore.hasPending(device) || SlugFontCache.hasPending())) {
2124
2387
  updateClockSignals(i, fps, durationMs);
@@ -2148,15 +2411,12 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2148
2411
  isVideoMode: virtualMedia.operation?.dataType === "Video"
2149
2412
  });
2150
2413
  await pipeline.enqueueFrame(i, targetTexture, encoder);
2151
- options?.onProgress?.({
2152
- phase: "render",
2153
- frame: i + 1,
2154
- totalFrames
2155
- });
2414
+ if (i + 1 < totalFrames) reporter.frameDone(i + 1);
2156
2415
  } else throw new Error("Invalid render context state");
2157
2416
  }
2158
2417
  if (pipeline) {
2159
2418
  await pipeline.drain();
2419
+ reporter.frameDone(totalFrames);
2160
2420
  const pipelineStats = pipeline.getStats();
2161
2421
  if (inspector && qaOptions) videoQa = inspector.stats(totalFrames, pipelineStats.totalFramesEncoded, fps, width, height, qaOptions);
2162
2422
  rendererLogger.debug({
@@ -2166,18 +2426,15 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2166
2426
  }, `[HeadlessWebGPURenderer] All frames rendered and encoded (avg cycle: ${pipelineStats.averageCycleTimeMs.toFixed(2)}ms, throughput: ${pipelineStats.throughputFps.toFixed(1)} fps)`);
2167
2427
  }
2168
2428
  }
2169
- options?.signal?.throwIfAborted();
2170
- options?.onProgress?.({
2171
- phase: "audio",
2172
- frame: totalFrames,
2173
- totalFrames
2174
- });
2175
- const { channels, sampleRate } = await mixAudioTracks(virtualMedia, fps, 48e3, device, renderId);
2429
+ options$1?.signal?.throwIfAborted();
2430
+ reporter.stage("audio", "Mixing audio");
2431
+ const { channels, sampleRate } = await mixAudioTracks(virtualMedia, fps, 48e3, device, renderId, { onProgress: ({ done, total, source }) => reporter.update(total > 0 ? `${done}/${total} clips${source ? `: ${source}` : ""}` : "no audio clips", total > 0 ? done / total : void 0) });
2176
2432
  const numChannels = channels.length;
2177
2433
  if (numChannels === 0) throw new Error("mixAudioTracks returned no channels");
2178
2434
  if (qaOptions) audioQa = analyzeAudio(channels, sampleRate, qaOptions);
2179
2435
  const totalSamples = channels[0].length;
2180
2436
  const chunkSize = Math.round(.1 * sampleRate);
2437
+ reporter.stage("audio-encode", `Encoding ${(totalSamples / sampleRate).toFixed(1)}s of audio (${audioCodec})`);
2181
2438
  for (let offset = 0; offset < totalSamples; offset += chunkSize) {
2182
2439
  const currentChunk = Math.min(chunkSize, totalSamples - offset);
2183
2440
  const interleaved = new Float32Array(currentChunk * numChannels);
@@ -2194,8 +2451,11 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2194
2451
  } finally {
2195
2452
  sample.close();
2196
2453
  }
2454
+ const written = offset + currentChunk;
2455
+ reporter.update(`${(written / sampleRate).toFixed(1)}s/${(totalSamples / sampleRate).toFixed(1)}s`, written / totalSamples);
2197
2456
  }
2198
- options?.signal?.throwIfAborted();
2457
+ options$1?.signal?.throwIfAborted();
2458
+ reporter.stage("mux", `Muxing ${extension}`);
2199
2459
  await output.finalize();
2200
2460
  outputFinalized = true;
2201
2461
  const qa = qaOptions ? buildQaReport({
@@ -2211,20 +2471,23 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2211
2471
  } catch {}
2212
2472
  };
2213
2473
  if (codecOption === "gif") {
2214
- rendererLogger.debug("[HeadlessWebGPURenderer] Converting rendered MP4 to high-quality GIF...");
2474
+ reporter.stage("convert", "Converting to GIF (ffmpeg)");
2215
2475
  await convertMp4ToGif(tempFilePath, tempGifPath);
2476
+ reporter.finish({ bytes: await fileSize(tempGifPath) });
2216
2477
  return {
2217
2478
  filePath: tempGifPath,
2218
2479
  cleanup,
2219
2480
  ...qa && { qa }
2220
2481
  };
2221
2482
  }
2483
+ reporter.finish({ bytes: await fileSize(tempFilePath) });
2222
2484
  return {
2223
2485
  filePath: tempFilePath,
2224
2486
  cleanup,
2225
2487
  ...qa && { qa }
2226
2488
  };
2227
2489
  } catch (error) {
2490
+ reporter.fail(error, options$1?.signal?.aborted === true);
2228
2491
  if (outputStarted && !outputFinalized) try {
2229
2492
  await output.finalize();
2230
2493
  } catch {}
@@ -2234,6 +2497,7 @@ var HeadlessWebGPURenderer = class HeadlessWebGPURenderer$1 {
2234
2497
  } catch {}
2235
2498
  throw error;
2236
2499
  } finally {
2500
+ reporter.dispose();
2237
2501
  if (statsInterval) clearInterval(statsInterval);
2238
2502
  try {
2239
2503
  renderer?.destroy();
@@ -2293,28 +2557,28 @@ function resetRenderCaches() {
2293
2557
  /**
2294
2558
  * Resolves and validates the list of sample points from the provided options.
2295
2559
  */
2296
- function resolveSamplePoints(options, defaultFps = 24, durationMs) {
2297
- const fps = options.fps ?? defaultFps;
2560
+ function resolveSamplePoints(options$1, defaultFps = 24, durationMs) {
2561
+ const fps = options$1.fps ?? defaultFps;
2298
2562
  if (fps <= 0) throw new Error(`[FrameGrid] Invalid fps: ${fps}. Must be > 0.`);
2299
2563
  const samples = [];
2300
- if (Array.isArray(options.frames) && options.frames.length > 0) for (const f of options.frames) {
2564
+ if (Array.isArray(options$1.frames) && options$1.frames.length > 0) for (const f of options$1.frames) {
2301
2565
  if (typeof f !== "number" || f < 0 || !Number.isFinite(f)) throw new Error(`[FrameGrid] Invalid frame index in frames list: ${f}`);
2302
2566
  samples.push({
2303
2567
  frame: Math.round(f),
2304
2568
  timeMs: Math.round(f / fps * 1e3)
2305
2569
  });
2306
2570
  }
2307
- else if (Array.isArray(options.timesMs) && options.timesMs.length > 0) for (const ms of options.timesMs) {
2571
+ else if (Array.isArray(options$1.timesMs) && options$1.timesMs.length > 0) for (const ms of options$1.timesMs) {
2308
2572
  if (typeof ms !== "number" || ms < 0 || !Number.isFinite(ms)) throw new Error(`[FrameGrid] Invalid timestamp in timesMs list: ${ms}`);
2309
2573
  samples.push({
2310
2574
  frame: Math.round(ms / 1e3 * fps),
2311
2575
  timeMs: Math.round(ms)
2312
2576
  });
2313
2577
  }
2314
- else if (options.startMs !== void 0 || options.endMs !== void 0 || options.stepMs !== void 0) {
2315
- const startMs = options.startMs ?? 0;
2316
- const endMs = options.endMs ?? durationMs ?? startMs + 1e3;
2317
- const stepMs = options.stepMs ?? Math.round(5 / fps * 1e3);
2578
+ else if (options$1.startMs !== void 0 || options$1.endMs !== void 0 || options$1.stepMs !== void 0) {
2579
+ const startMs = options$1.startMs ?? 0;
2580
+ const endMs = options$1.endMs ?? durationMs ?? startMs + 1e3;
2581
+ const stepMs = options$1.stepMs ?? Math.round(5 / fps * 1e3);
2318
2582
  if (startMs < 0 || endMs < startMs) throw new Error(`[FrameGrid] Invalid millisecond range: startMs=${startMs}, endMs=${endMs}. startMs must be <= endMs.`);
2319
2583
  if (stepMs <= 0) throw new Error(`[FrameGrid] Invalid stepMs: ${stepMs}. Must be > 0.`);
2320
2584
  for (let ms = startMs; ms <= endMs; ms += stepMs) samples.push({
@@ -2322,9 +2586,9 @@ function resolveSamplePoints(options, defaultFps = 24, durationMs) {
2322
2586
  timeMs: Math.round(ms)
2323
2587
  });
2324
2588
  } else {
2325
- const startFrame = options.startFrame ?? 0;
2326
- const endFrame = options.endFrame ?? (durationMs ? Math.min(startFrame + 30, Math.floor(durationMs / 1e3 * fps)) : startFrame + 30);
2327
- const stepFrames = options.stepFrames ?? 5;
2589
+ const startFrame = options$1.startFrame ?? 0;
2590
+ const endFrame = options$1.endFrame ?? (durationMs ? Math.min(startFrame + 30, Math.floor(durationMs / 1e3 * fps)) : startFrame + 30);
2591
+ const stepFrames = options$1.stepFrames ?? 5;
2328
2592
  if (startFrame < 0 || endFrame < startFrame) throw new Error(`[FrameGrid] Invalid frame range: startFrame=${startFrame}, endFrame=${endFrame}. startFrame must be <= endFrame.`);
2329
2593
  if (stepFrames <= 0) throw new Error(`[FrameGrid] Invalid stepFrames: ${stepFrames}. Must be > 0.`);
2330
2594
  for (let f = startFrame; f <= endFrame; f += stepFrames) samples.push({
@@ -2332,7 +2596,7 @@ function resolveSamplePoints(options, defaultFps = 24, durationMs) {
2332
2596
  timeMs: Math.round(f / fps * 1e3)
2333
2597
  });
2334
2598
  }
2335
- const maxFramesLimit = Math.min(options.maxFrames ?? 64, 120);
2599
+ const maxFramesLimit = Math.min(options$1.maxFrames ?? 64, 120);
2336
2600
  if (samples.length > maxFramesLimit) throw new Error(`[FrameGrid] Requested ${samples.length} frames exceeds the safety threshold of ${maxFramesLimit}. Increase stepFrames/stepMs or narrow the start/end range to prevent oversized images.`);
2337
2601
  if (samples.length === 0) throw new Error("[FrameGrid] Zero frames were resolved for sampling.");
2338
2602
  return {
@@ -2343,13 +2607,13 @@ function resolveSamplePoints(options, defaultFps = 24, durationMs) {
2343
2607
  /**
2344
2608
  * Computes grid layout dimensions, ensuring resulting canvas does not exceed size limits.
2345
2609
  */
2346
- function computeGridLayout(numSamples, aspectRatio, options) {
2347
- const gap = options.gap ?? 12;
2348
- const padding = options.padding ?? 16;
2349
- const headerHeight = options.showHeader ?? true ? 54 : 0;
2350
- const maxGridWidth = options.maxGridWidth ?? 4096;
2351
- const maxGridHeight = options.maxGridHeight ?? 4096;
2352
- let columns = options.columns;
2610
+ function computeGridLayout(numSamples, aspectRatio, options$1) {
2611
+ const gap = options$1.gap ?? 12;
2612
+ const padding = options$1.padding ?? 16;
2613
+ const headerHeight = options$1.showHeader ?? true ? 54 : 0;
2614
+ const maxGridWidth = options$1.maxGridWidth ?? 4096;
2615
+ const maxGridHeight = options$1.maxGridHeight ?? 4096;
2616
+ let columns = options$1.columns;
2353
2617
  if (!columns || columns <= 0) if (numSamples <= 4) columns = numSamples;
2354
2618
  else if (numSamples <= 9) columns = 3;
2355
2619
  else if (numSamples <= 16) columns = 4;
@@ -2357,8 +2621,8 @@ function computeGridLayout(numSamples, aspectRatio, options) {
2357
2621
  else columns = 6;
2358
2622
  columns = Math.min(columns, numSamples);
2359
2623
  const rows = Math.ceil(numSamples / columns);
2360
- let cellWidth = Math.max(120, Math.min(options.cellWidth ?? 320, 960));
2361
- let cellHeight = options.cellHeight ?? Math.round(cellWidth / (aspectRatio > 0 ? aspectRatio : 16 / 9));
2624
+ let cellWidth = Math.max(120, Math.min(options$1.cellWidth ?? 320, 960));
2625
+ let cellHeight = options$1.cellHeight ?? Math.round(cellWidth / (aspectRatio > 0 ? aspectRatio : 16 / 9));
2362
2626
  let totalWidth = columns * cellWidth + (columns - 1) * gap + padding * 2;
2363
2627
  let totalHeight = rows * cellHeight + (rows - 1) * gap + padding * 2 + headerHeight;
2364
2628
  if (totalWidth > maxGridWidth || totalHeight > maxGridHeight) {
@@ -2385,15 +2649,15 @@ function computeGridLayout(numSamples, aspectRatio, options) {
2385
2649
  * Renders a sequence of frames from a Composition or Media pipeline into a unified image grid (contact sheet).
2386
2650
  * Ideal for visual inspection of kinetic motion, transitions, easing, and layout stability.
2387
2651
  */
2388
- async function renderFrameGrid(target, options = {}) {
2652
+ async function renderFrameGrid(target, options$1 = {}) {
2389
2653
  const defaultFps = target.fps ?? 24;
2390
2654
  const durationMs = target.durationMs;
2391
- const { samples, fps } = resolveSamplePoints(options, defaultFps, durationMs);
2655
+ const { samples, fps } = resolveSamplePoints(options$1, defaultFps, durationMs);
2392
2656
  const compWidth = target.width ?? 1920;
2393
2657
  const compHeight = target.height ?? 1080;
2394
2658
  const aspectRatio = compWidth > 0 && compHeight > 0 ? compWidth / compHeight : 16 / 9;
2395
- const layout = computeGridLayout(samples.length, aspectRatio, options);
2396
- const renderer = options.renderer ?? new HeadlessMediaRenderer();
2659
+ const layout = computeGridLayout(samples.length, aspectRatio, options$1);
2660
+ const renderer = options$1.renderer ?? new HeadlessMediaRenderer();
2397
2661
  const frameBuffers = [];
2398
2662
  for (const sample of samples) {
2399
2663
  const buf = await target.renderFrame({
@@ -2406,11 +2670,11 @@ async function renderFrameGrid(target, options = {}) {
2406
2670
  }
2407
2671
  const canvas = new Canvas(layout.totalWidth, layout.totalHeight);
2408
2672
  const ctx = canvas.getContext("2d");
2409
- ctx.fillStyle = options.backgroundColor ?? "#090a0f";
2673
+ ctx.fillStyle = options$1.backgroundColor ?? "#090a0f";
2410
2674
  ctx.fillRect(0, 0, layout.totalWidth, layout.totalHeight);
2411
- if (options.showHeader !== false && layout.headerHeight > 0) {
2412
- const title = options.headerText ?? `FrameGrid Conformance Review | Frames ${samples[0].frame}–${samples[samples.length - 1].frame} (Count: ${samples.length})`;
2413
- const subtitle = `${compWidth}×${compHeight} @ ${fps} FPS | Cell: ${layout.cellWidth}×${layout.cellHeight}px | Step: ${options.stepFrames ? `${options.stepFrames}f` : options.stepMs ? `${options.stepMs}ms` : "Custom"}`;
2675
+ if (options$1.showHeader !== false && layout.headerHeight > 0) {
2676
+ const title = options$1.headerText ?? `FrameGrid Conformance Review | Frames ${samples[0].frame}–${samples[samples.length - 1].frame} (Count: ${samples.length})`;
2677
+ const subtitle = `${compWidth}×${compHeight} @ ${fps} FPS | Cell: ${layout.cellWidth}×${layout.cellHeight}px | Step: ${options$1.stepFrames ? `${options$1.stepFrames}f` : options$1.stepMs ? `${options$1.stepMs}ms` : "Custom"}`;
2414
2678
  ctx.fillStyle = "#f8fafc";
2415
2679
  ctx.font = "bold 15px sans-serif";
2416
2680
  ctx.fillText(title, layout.padding, layout.padding + 18);
@@ -2424,7 +2688,7 @@ async function renderFrameGrid(target, options = {}) {
2424
2688
  ctx.lineTo(layout.totalWidth - layout.padding, layout.padding + 46);
2425
2689
  ctx.stroke();
2426
2690
  }
2427
- const showLabels = options.showLabels ?? true;
2691
+ const showLabels = options$1.showLabels ?? true;
2428
2692
  for (let i = 0; i < samples.length; i++) {
2429
2693
  const sample = samples[i];
2430
2694
  const col = i % layout.columns;
@@ -2455,10 +2719,10 @@ async function renderFrameGrid(target, options = {}) {
2455
2719
  }
2456
2720
  }
2457
2721
  const gridBuffer = await canvas.toBuffer("png");
2458
- if (options.outputPath) await fs$1.writeFile(options.outputPath, gridBuffer);
2722
+ if (options$1.outputPath) await fs$1.writeFile(options$1.outputPath, gridBuffer);
2459
2723
  return gridBuffer;
2460
2724
  }
2461
2725
 
2462
2726
  //#endregion
2463
2727
  export { HeadlessMediaRenderer as a, renderSemaphore as c, resetRenderCaches as i, renderFrameGrid as n, HeadlessWebGPURenderer as o, resolveSamplePoints as r, formatQaReport as s, computeGridLayout as t };
2464
- //# sourceMappingURL=renderer-TyZu7nQ2.mjs.map
2728
+ //# sourceMappingURL=renderer-CoWfz-9p.mjs.map