@omnimedia/omnitool 1.1.0-8 → 1.1.0-80

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 (436) hide show
  1. package/README.md +293 -76
  2. package/package.json +19 -17
  3. package/s/context.ts +0 -7
  4. package/s/demo/demo.bundle.ts +104 -43
  5. package/s/demo/demo.css +244 -14
  6. package/s/demo/routines/export-test.ts +16 -0
  7. package/s/demo/routines/filmstrip-test.ts +22 -18
  8. package/s/demo/routines/load-video.ts +2 -3
  9. package/s/demo/routines/playback-test.ts +61 -0
  10. package/s/demo/routines/timeline-setup.ts +50 -0
  11. package/s/demo/routines/transcode-test.ts +19 -5
  12. package/s/demo/routines/transitions-test.ts +2 -2
  13. package/s/demo/routines/waveform-test.ts +35 -8
  14. package/s/driver/driver-worker.ts +9 -0
  15. package/s/driver/driver.test.ts +1 -1
  16. package/s/driver/driver.ts +43 -42
  17. package/s/driver/fns/schematic.ts +26 -6
  18. package/s/driver/fns/work.ts +65 -189
  19. package/s/driver/parts/compositor.ts +316 -0
  20. package/s/driver/parts/machina.ts +19 -20
  21. package/s/driver/utils/find-pixi-filter.ts +24 -0
  22. package/s/index.html.ts +103 -25
  23. package/s/index.ts +1 -0
  24. package/s/tests.bundle.ts +11 -0
  25. package/s/tests.html.ts +28 -0
  26. package/s/timeline/index.ts +8 -2
  27. package/s/timeline/parts/animations.ts +56 -0
  28. package/s/timeline/parts/filmstrip.ts +43 -16
  29. package/s/timeline/parts/filters.ts +453 -0
  30. package/s/timeline/parts/item.ts +70 -7
  31. package/s/timeline/parts/media.ts +12 -2
  32. package/s/timeline/parts/resource-pool.ts +8 -5
  33. package/s/timeline/parts/resource.ts +3 -0
  34. package/s/timeline/parts/waveform/parts/collect.ts +72 -0
  35. package/s/timeline/parts/waveform/parts/render.ts +45 -0
  36. package/s/timeline/parts/waveform/parts/types.ts +24 -0
  37. package/s/timeline/parts/waveform/waveform.ts +161 -0
  38. package/s/timeline/renderers/export/parts/audio-gain.ts +17 -0
  39. package/s/timeline/renderers/export/parts/audio-mix.ts +133 -0
  40. package/s/timeline/renderers/export/parts/cursor.ts +129 -0
  41. package/s/timeline/renderers/export/parts/produce-audio.ts +64 -0
  42. package/s/timeline/renderers/export/parts/produce-video.ts +49 -0
  43. package/s/timeline/renderers/export/parts/resamplers.ts +48 -0
  44. package/s/timeline/renderers/export/produce.ts +28 -0
  45. package/s/timeline/renderers/parts/handy.ts +377 -0
  46. package/s/timeline/renderers/parts/samplers/audio/parts/find.ts +19 -0
  47. package/s/timeline/renderers/parts/samplers/audio/parts/init.ts +60 -0
  48. package/s/timeline/renderers/parts/samplers/audio/parts/sink.ts +38 -0
  49. package/s/timeline/renderers/parts/samplers/audio/parts/types.ts +16 -0
  50. package/s/timeline/renderers/parts/samplers/audio/sampler.ts +35 -0
  51. package/s/timeline/renderers/parts/samplers/visual/parts/defaults.ts +16 -0
  52. package/s/timeline/renderers/parts/samplers/visual/parts/sample.ts +69 -0
  53. package/s/timeline/renderers/parts/samplers/visual/parts/sequence.ts +111 -0
  54. package/s/timeline/renderers/parts/samplers/visual/parts/sink.ts +38 -0
  55. package/s/timeline/renderers/parts/samplers/visual/parts/transition.ts +28 -0
  56. package/s/timeline/renderers/parts/samplers/visual/parts/types.ts +10 -0
  57. package/s/timeline/renderers/parts/samplers/visual/sampler.ts +28 -0
  58. package/s/timeline/renderers/parts/schedulers.ts +96 -0
  59. package/s/timeline/renderers/player/parts/playback.ts +159 -0
  60. package/s/timeline/renderers/player/player.ts +77 -0
  61. package/s/timeline/renderers/renderers.test.ts +385 -0
  62. package/s/timeline/sugar/helpers.ts +190 -0
  63. package/s/timeline/sugar/o.ts +271 -59
  64. package/s/timeline/sugar/omni.test.ts +210 -0
  65. package/s/timeline/sugar/omni.ts +35 -12
  66. package/s/timeline/types.ts +28 -3
  67. package/s/timeline/utils/anim.ts +71 -0
  68. package/s/timeline/utils/checksum.ts +3 -1
  69. package/s/timeline/utils/datafile.ts +15 -4
  70. package/s/timeline/utils/dummy-data.ts +3 -3
  71. package/s/timeline/utils/matrix.ts +21 -0
  72. package/s/timeline/utils/terps.ts +81 -0
  73. package/s/units/fps.ts +8 -0
  74. package/s/units/ms.ts +8 -0
  75. package/s/units/seconds.ts +8 -0
  76. package/x/WebGLRenderer-4CHIZDHY.js +2 -0
  77. package/x/WebGLRenderer-4CHIZDHY.js.map +7 -0
  78. package/x/WebGPURenderer-O6WXU2QR.js +2 -0
  79. package/x/WebGPURenderer-O6WXU2QR.js.map +7 -0
  80. package/x/browserAll-WNIOTNNP.js +2 -0
  81. package/x/browserAll-WNIOTNNP.js.map +7 -0
  82. package/x/chunk-23FOBGX6.js +2 -0
  83. package/x/chunk-23FOBGX6.js.map +7 -0
  84. package/x/chunk-73XOWA4F.js +393 -0
  85. package/x/chunk-73XOWA4F.js.map +7 -0
  86. package/x/chunk-IAWJKNX5.js +42 -0
  87. package/x/chunk-IAWJKNX5.js.map +7 -0
  88. package/x/chunk-KCMVLWBS.js +157 -0
  89. package/x/chunk-KCMVLWBS.js.map +7 -0
  90. package/x/chunk-MR32SQ27.js +2 -0
  91. package/x/chunk-MR32SQ27.js.map +7 -0
  92. package/x/chunk-VCUJJYRJ.js +327 -0
  93. package/x/chunk-VCUJJYRJ.js.map +7 -0
  94. package/x/chunk-XNIZ4L5W.js +269 -0
  95. package/x/chunk-XNIZ4L5W.js.map +7 -0
  96. package/x/chunk-ZLGNQFUI.js +15 -0
  97. package/x/chunk-ZLGNQFUI.js.map +7 -0
  98. package/x/context.d.ts +1 -4
  99. package/x/context.js +1 -5
  100. package/x/context.js.map +1 -1
  101. package/x/demo/WebGLRenderer-RSJAHIG2.js +2 -0
  102. package/x/demo/WebGLRenderer-RSJAHIG2.js.map +7 -0
  103. package/x/demo/WebGPURenderer-MGFAJCYY.js +2 -0
  104. package/x/demo/WebGPURenderer-MGFAJCYY.js.map +7 -0
  105. package/x/demo/browserAll-PTRBXBRP.js +2 -0
  106. package/x/demo/browserAll-PTRBXBRP.js.map +7 -0
  107. package/x/demo/chunk-CUYOGHWU.js +42 -0
  108. package/x/demo/chunk-CUYOGHWU.js.map +7 -0
  109. package/x/demo/chunk-DGTDNJ7W.js +2 -0
  110. package/x/demo/chunk-DGTDNJ7W.js.map +7 -0
  111. package/x/demo/chunk-FZ5BYF63.js +15 -0
  112. package/x/demo/chunk-FZ5BYF63.js.map +7 -0
  113. package/x/demo/chunk-KWN4NNES.js +269 -0
  114. package/x/demo/chunk-KWN4NNES.js.map +7 -0
  115. package/x/demo/chunk-OJ3FPXW7.js +157 -0
  116. package/x/demo/chunk-OJ3FPXW7.js.map +7 -0
  117. package/x/demo/chunk-PSLUOGTZ.js +393 -0
  118. package/x/demo/chunk-PSLUOGTZ.js.map +7 -0
  119. package/x/demo/chunk-VLCVEIFU.js +327 -0
  120. package/x/demo/chunk-VLCVEIFU.js.map +7 -0
  121. package/x/demo/chunk-ZWCPT5FR.js +2 -0
  122. package/x/demo/chunk-ZWCPT5FR.js.map +7 -0
  123. package/x/demo/demo.bundle.js +94 -40
  124. package/x/demo/demo.bundle.js.map +1 -1
  125. package/x/demo/demo.bundle.min.js +7340 -90
  126. package/x/demo/demo.bundle.min.js.map +4 -4
  127. package/x/demo/demo.css +244 -14
  128. package/x/demo/routines/export-test.d.ts +2 -0
  129. package/x/demo/routines/export-test.js +10 -0
  130. package/x/demo/routines/export-test.js.map +1 -0
  131. package/x/demo/routines/filmstrip-test.d.ts +1 -1
  132. package/x/demo/routines/filmstrip-test.js +20 -17
  133. package/x/demo/routines/filmstrip-test.js.map +1 -1
  134. package/x/demo/routines/load-video.d.ts +1 -1
  135. package/x/demo/routines/load-video.js +1 -2
  136. package/x/demo/routines/load-video.js.map +1 -1
  137. package/x/demo/routines/playback-test.d.ts +2 -0
  138. package/x/demo/routines/playback-test.js +51 -0
  139. package/x/demo/routines/playback-test.js.map +1 -0
  140. package/x/demo/routines/timeline-setup.d.ts +6 -0
  141. package/x/demo/routines/timeline-setup.js +32 -0
  142. package/x/demo/routines/timeline-setup.js.map +1 -0
  143. package/x/demo/routines/transcode-test.js +15 -5
  144. package/x/demo/routines/transcode-test.js.map +1 -1
  145. package/x/demo/routines/transitions-test.js +2 -2
  146. package/x/demo/routines/transitions-test.js.map +1 -1
  147. package/x/demo/routines/waveform-test.d.ts +2 -1
  148. package/x/demo/routines/waveform-test.js +29 -8
  149. package/x/demo/routines/waveform-test.js.map +1 -1
  150. package/x/demo/webworkerAll-JENRT6BT.js +2 -0
  151. package/x/demo/webworkerAll-JENRT6BT.js.map +7 -0
  152. package/x/driver/driver-worker.d.ts +1 -0
  153. package/x/driver/driver-worker.js +6 -0
  154. package/x/driver/driver-worker.js.map +1 -0
  155. package/x/driver/driver.d.ts +25 -8
  156. package/x/driver/driver.js +43 -39
  157. package/x/driver/driver.js.map +1 -1
  158. package/x/driver/driver.test.js +1 -1
  159. package/x/driver/driver.test.js.map +1 -1
  160. package/x/driver/driver.worker.bundle.min.js +117 -3506
  161. package/x/driver/driver.worker.bundle.min.js.map +4 -4
  162. package/x/driver/fns/host.d.ts +3 -2
  163. package/x/driver/fns/schematic.d.ts +25 -4
  164. package/x/driver/fns/work.d.ts +4 -4
  165. package/x/driver/fns/work.js +55 -155
  166. package/x/driver/fns/work.js.map +1 -1
  167. package/x/driver/parts/compositor.d.ts +39 -0
  168. package/x/driver/parts/compositor.js +261 -0
  169. package/x/driver/parts/compositor.js.map +1 -0
  170. package/x/driver/parts/machina.d.ts +0 -20
  171. package/x/driver/parts/machina.js +6 -10
  172. package/x/driver/parts/machina.js.map +1 -1
  173. package/x/driver/utils/find-pixi-filter.d.ts +5 -0
  174. package/x/driver/utils/find-pixi-filter.js +13 -0
  175. package/x/driver/utils/find-pixi-filter.js.map +1 -0
  176. package/x/features/speech/transcribe/parts/prep-audio.d.ts +1 -1
  177. package/x/features/speech/transcribe/worker.bundle.min.js +899 -899
  178. package/x/features/speech/transcribe/worker.bundle.min.js.map +4 -4
  179. package/x/index.d.ts +1 -0
  180. package/x/index.html +347 -38
  181. package/x/index.html.js +103 -24
  182. package/x/index.html.js.map +1 -1
  183. package/x/index.js +1 -0
  184. package/x/index.js.map +1 -1
  185. package/x/tests.bundle.js +8 -0
  186. package/x/tests.bundle.js.map +1 -0
  187. package/x/tests.bundle.min.js +7374 -0
  188. package/x/tests.bundle.min.js.map +7 -0
  189. package/x/tests.html +316 -0
  190. package/x/tests.html.d.ts +2 -0
  191. package/x/tests.html.js +22 -0
  192. package/x/tests.html.js.map +1 -0
  193. package/x/timeline/index.d.ts +7 -1
  194. package/x/timeline/index.js +7 -1
  195. package/x/timeline/index.js.map +1 -1
  196. package/x/timeline/parts/animations.d.ts +105 -0
  197. package/x/timeline/parts/animations.js +28 -0
  198. package/x/timeline/parts/animations.js.map +1 -0
  199. package/x/timeline/parts/filmstrip.d.ts +4 -3
  200. package/x/timeline/parts/filmstrip.js +29 -10
  201. package/x/timeline/parts/filmstrip.js.map +1 -1
  202. package/x/timeline/parts/filters.d.ts +108 -0
  203. package/x/timeline/parts/filters.js +340 -0
  204. package/x/timeline/parts/filters.js.map +1 -0
  205. package/x/timeline/parts/item.d.ts +56 -4
  206. package/x/timeline/parts/item.js +5 -1
  207. package/x/timeline/parts/item.js.map +1 -1
  208. package/x/timeline/parts/media.d.ts +2 -0
  209. package/x/timeline/parts/media.js +11 -2
  210. package/x/timeline/parts/media.js.map +1 -1
  211. package/x/timeline/parts/resource-pool.d.ts +3 -0
  212. package/x/timeline/parts/resource-pool.js +7 -4
  213. package/x/timeline/parts/resource-pool.js.map +1 -1
  214. package/x/timeline/parts/resource.d.ts +3 -0
  215. package/x/timeline/parts/waveform/parts/collect.d.ts +11 -0
  216. package/x/timeline/parts/waveform/parts/collect.js +56 -0
  217. package/x/timeline/parts/waveform/parts/collect.js.map +1 -0
  218. package/x/timeline/parts/waveform/parts/render.d.ts +5 -0
  219. package/x/timeline/parts/waveform/parts/render.js +29 -0
  220. package/x/timeline/parts/waveform/parts/render.js.map +1 -0
  221. package/x/timeline/parts/waveform/parts/types.d.ts +21 -0
  222. package/x/timeline/parts/waveform/parts/types.js.map +1 -0
  223. package/x/timeline/parts/waveform/waveform.d.ts +19 -0
  224. package/x/timeline/parts/waveform/waveform.js +133 -0
  225. package/x/timeline/parts/waveform/waveform.js.map +1 -0
  226. package/x/timeline/renderers/export/parts/audio-gain.d.ts +1 -0
  227. package/x/timeline/renderers/export/parts/audio-gain.js +13 -0
  228. package/x/timeline/renderers/export/parts/audio-gain.js.map +1 -0
  229. package/x/timeline/renderers/export/parts/audio-mix.d.ts +21 -0
  230. package/x/timeline/renderers/export/parts/audio-mix.js +89 -0
  231. package/x/timeline/renderers/export/parts/audio-mix.js.map +1 -0
  232. package/x/timeline/renderers/export/parts/cursor.d.ts +18 -0
  233. package/x/timeline/renderers/export/parts/cursor.js +99 -0
  234. package/x/timeline/renderers/export/parts/cursor.js.map +1 -0
  235. package/x/timeline/renderers/export/parts/produce-audio.d.ts +6 -0
  236. package/x/timeline/renderers/export/parts/produce-audio.js +41 -0
  237. package/x/timeline/renderers/export/parts/produce-audio.js.map +1 -0
  238. package/x/timeline/renderers/export/parts/produce-video.d.ts +10 -0
  239. package/x/timeline/renderers/export/parts/produce-video.js +26 -0
  240. package/x/timeline/renderers/export/parts/produce-video.js.map +1 -0
  241. package/x/timeline/renderers/export/parts/resamplers.d.ts +12 -0
  242. package/x/timeline/renderers/export/parts/resamplers.js +29 -0
  243. package/x/timeline/renderers/export/parts/resamplers.js.map +1 -0
  244. package/x/timeline/renderers/export/produce.d.ts +13 -0
  245. package/x/timeline/renderers/export/produce.js +15 -0
  246. package/x/timeline/renderers/export/produce.js.map +1 -0
  247. package/x/timeline/renderers/parts/handy.d.ts +36 -0
  248. package/x/timeline/renderers/parts/handy.js +221 -0
  249. package/x/timeline/renderers/parts/handy.js.map +1 -0
  250. package/x/timeline/renderers/parts/samplers/audio/parts/find.d.ts +6 -0
  251. package/x/timeline/renderers/parts/samplers/audio/parts/find.js +15 -0
  252. package/x/timeline/renderers/parts/samplers/audio/parts/find.js.map +1 -0
  253. package/x/timeline/renderers/parts/samplers/audio/parts/init.d.ts +5 -0
  254. package/x/timeline/renderers/parts/samplers/audio/parts/init.js +40 -0
  255. package/x/timeline/renderers/parts/samplers/audio/parts/init.js.map +1 -0
  256. package/x/timeline/renderers/parts/samplers/audio/parts/sink.d.ts +8 -0
  257. package/x/timeline/renderers/parts/samplers/audio/parts/sink.js +24 -0
  258. package/x/timeline/renderers/parts/samplers/audio/parts/sink.js.map +1 -0
  259. package/x/timeline/renderers/parts/samplers/audio/parts/types.d.ts +14 -0
  260. package/x/timeline/renderers/parts/samplers/audio/parts/types.js +2 -0
  261. package/x/timeline/renderers/parts/samplers/audio/parts/types.js.map +1 -0
  262. package/x/timeline/renderers/parts/samplers/audio/sampler.d.ts +11 -0
  263. package/x/timeline/renderers/parts/samplers/audio/sampler.js +22 -0
  264. package/x/timeline/renderers/parts/samplers/audio/sampler.js.map +1 -0
  265. package/x/timeline/renderers/parts/samplers/visual/parts/defaults.d.ts +5 -0
  266. package/x/timeline/renderers/parts/samplers/visual/parts/defaults.js +10 -0
  267. package/x/timeline/renderers/parts/samplers/visual/parts/defaults.js.map +1 -0
  268. package/x/timeline/renderers/parts/samplers/visual/parts/sample.d.ts +6 -0
  269. package/x/timeline/renderers/parts/samplers/visual/parts/sample.js +48 -0
  270. package/x/timeline/renderers/parts/samplers/visual/parts/sample.js.map +1 -0
  271. package/x/timeline/renderers/parts/samplers/visual/parts/sequence.d.ts +6 -0
  272. package/x/timeline/renderers/parts/samplers/visual/parts/sequence.js +75 -0
  273. package/x/timeline/renderers/parts/samplers/visual/parts/sequence.js.map +1 -0
  274. package/x/timeline/renderers/parts/samplers/visual/parts/sink.d.ts +8 -0
  275. package/x/timeline/renderers/parts/samplers/visual/parts/sink.js +24 -0
  276. package/x/timeline/renderers/parts/samplers/visual/parts/sink.js.map +1 -0
  277. package/x/timeline/renderers/parts/samplers/visual/parts/transition.d.ts +3 -0
  278. package/x/timeline/renderers/parts/samplers/visual/parts/transition.js +18 -0
  279. package/x/timeline/renderers/parts/samplers/visual/parts/transition.js.map +1 -0
  280. package/x/timeline/renderers/parts/samplers/visual/parts/types.d.ts +8 -0
  281. package/x/timeline/renderers/parts/samplers/visual/parts/types.js +2 -0
  282. package/x/timeline/renderers/parts/samplers/visual/parts/types.js.map +1 -0
  283. package/x/timeline/renderers/parts/samplers/visual/sampler.d.ts +7 -0
  284. package/x/timeline/renderers/parts/samplers/visual/sampler.js +17 -0
  285. package/x/timeline/renderers/parts/samplers/visual/sampler.js.map +1 -0
  286. package/x/timeline/renderers/parts/schedulers.d.ts +17 -0
  287. package/x/timeline/renderers/parts/schedulers.js +64 -0
  288. package/x/timeline/renderers/parts/schedulers.js.map +1 -0
  289. package/x/timeline/renderers/player/parts/playback.d.ts +36 -0
  290. package/x/timeline/renderers/player/parts/playback.js +113 -0
  291. package/x/timeline/renderers/player/parts/playback.js.map +1 -0
  292. package/x/timeline/renderers/player/player.d.ts +25 -0
  293. package/x/timeline/renderers/player/player.js +56 -0
  294. package/x/timeline/renderers/player/player.js.map +1 -0
  295. package/x/timeline/renderers/renderers.test.d.ts +32 -0
  296. package/x/timeline/renderers/renderers.test.js +305 -0
  297. package/x/timeline/renderers/renderers.test.js.map +1 -0
  298. package/x/timeline/sugar/helpers.d.ts +56 -0
  299. package/x/timeline/sugar/helpers.js +104 -0
  300. package/x/timeline/sugar/helpers.js.map +1 -0
  301. package/x/timeline/sugar/o.d.ts +48 -14
  302. package/x/timeline/sugar/o.js +213 -54
  303. package/x/timeline/sugar/o.js.map +1 -1
  304. package/x/timeline/sugar/omni.d.ts +11 -6
  305. package/x/timeline/sugar/omni.js +28 -8
  306. package/x/timeline/sugar/omni.js.map +1 -1
  307. package/x/timeline/sugar/omni.test.d.ts +27 -0
  308. package/x/timeline/sugar/omni.test.js +128 -0
  309. package/x/timeline/sugar/omni.test.js.map +1 -0
  310. package/x/timeline/types.d.ts +12 -2
  311. package/x/timeline/utils/anim.d.ts +5 -0
  312. package/x/timeline/utils/anim.js +44 -0
  313. package/x/timeline/utils/anim.js.map +1 -0
  314. package/x/timeline/utils/checksum.d.ts +3 -2
  315. package/x/timeline/utils/checksum.js.map +1 -1
  316. package/x/timeline/utils/datafile.d.ts +5 -3
  317. package/x/timeline/utils/datafile.js +18 -5
  318. package/x/timeline/utils/datafile.js.map +1 -1
  319. package/x/timeline/utils/dummy-data.d.ts +1 -2
  320. package/x/timeline/utils/dummy-data.js +4 -2
  321. package/x/timeline/utils/dummy-data.js.map +1 -1
  322. package/x/timeline/utils/matrix.d.ts +9 -0
  323. package/x/timeline/utils/matrix.js +10 -0
  324. package/x/timeline/utils/matrix.js.map +1 -1
  325. package/x/timeline/utils/terps.d.ts +11 -0
  326. package/x/timeline/utils/terps.js +57 -0
  327. package/x/timeline/utils/terps.js.map +1 -0
  328. package/x/units/fps.d.ts +6 -0
  329. package/x/units/fps.js +2 -0
  330. package/x/units/fps.js.map +1 -0
  331. package/x/units/ms.d.ts +6 -0
  332. package/x/units/ms.js +2 -0
  333. package/x/units/ms.js.map +1 -0
  334. package/x/units/seconds.d.ts +6 -0
  335. package/x/units/seconds.js +2 -0
  336. package/x/units/seconds.js.map +1 -0
  337. package/x/webworkerAll-RLCTMSDD.js +2 -0
  338. package/x/webworkerAll-RLCTMSDD.js.map +7 -0
  339. package/s/tests.test.ts +0 -8
  340. package/s/timeline/parts/compositor/export.ts +0 -77
  341. package/s/timeline/parts/compositor/parts/html-tree.ts +0 -37
  342. package/s/timeline/parts/compositor/parts/schedulers.ts +0 -85
  343. package/s/timeline/parts/compositor/parts/tree-builder.ts +0 -184
  344. package/s/timeline/parts/compositor/parts/webcodecs-tree.ts +0 -30
  345. package/s/timeline/parts/compositor/playback.ts +0 -81
  346. package/s/timeline/parts/compositor/samplers/html.ts +0 -115
  347. package/s/timeline/parts/compositor/samplers/webcodecs.ts +0 -60
  348. package/s/timeline/parts/waveform.ts +0 -62
  349. package/s/timeline/sugar/builders.ts +0 -102
  350. package/s/timeline/sugar/omni-test.ts +0 -38
  351. package/s/timeline/timeline.ts +0 -22
  352. package/s/timeline/utils/audio-stream.ts +0 -15
  353. package/s/timeline/utils/video-cursor.ts +0 -40
  354. package/s/tools/common/loader.ts +0 -26
  355. package/s/tools/common/transformer-pipeline.ts +0 -26
  356. package/s/tools/speech-recognition/common/model.ts +0 -26
  357. package/s/tools/speech-recognition/whisper/fns/host.ts +0 -25
  358. package/s/tools/speech-recognition/whisper/fns/schematic.ts +0 -23
  359. package/s/tools/speech-recognition/whisper/fns/work.ts +0 -91
  360. package/s/tools/speech-recognition/whisper/parts/types.ts +0 -38
  361. package/s/tools/speech-recognition/whisper/parts/worker.bundle.ts +0 -7
  362. package/s/tools/speech-recognition/whisper/tool.ts +0 -70
  363. package/x/tests.test.js +0 -6
  364. package/x/tests.test.js.map +0 -1
  365. package/x/timeline/parts/compositor/export.d.ts +0 -9
  366. package/x/timeline/parts/compositor/export.js +0 -64
  367. package/x/timeline/parts/compositor/export.js.map +0 -1
  368. package/x/timeline/parts/compositor/parts/html-tree.d.ts +0 -3
  369. package/x/timeline/parts/compositor/parts/html-tree.js +0 -40
  370. package/x/timeline/parts/compositor/parts/html-tree.js.map +0 -1
  371. package/x/timeline/parts/compositor/parts/schedulers.d.ts +0 -15
  372. package/x/timeline/parts/compositor/parts/schedulers.js +0 -64
  373. package/x/timeline/parts/compositor/parts/schedulers.js.map +0 -1
  374. package/x/timeline/parts/compositor/parts/tree-builder.d.ts +0 -37
  375. package/x/timeline/parts/compositor/parts/tree-builder.js +0 -147
  376. package/x/timeline/parts/compositor/parts/tree-builder.js.map +0 -1
  377. package/x/timeline/parts/compositor/parts/webcodecs-tree.d.ts +0 -3
  378. package/x/timeline/parts/compositor/parts/webcodecs-tree.js +0 -28
  379. package/x/timeline/parts/compositor/parts/webcodecs-tree.js.map +0 -1
  380. package/x/timeline/parts/compositor/playback.d.ts +0 -19
  381. package/x/timeline/parts/compositor/playback.js +0 -71
  382. package/x/timeline/parts/compositor/playback.js.map +0 -1
  383. package/x/timeline/parts/compositor/samplers/html.d.ts +0 -3
  384. package/x/timeline/parts/compositor/samplers/html.js +0 -106
  385. package/x/timeline/parts/compositor/samplers/html.js.map +0 -1
  386. package/x/timeline/parts/compositor/samplers/webcodecs.d.ts +0 -2
  387. package/x/timeline/parts/compositor/samplers/webcodecs.js +0 -55
  388. package/x/timeline/parts/compositor/samplers/webcodecs.js.map +0 -1
  389. package/x/timeline/parts/waveform.d.ts +0 -8
  390. package/x/timeline/parts/waveform.js +0 -51
  391. package/x/timeline/parts/waveform.js.map +0 -1
  392. package/x/timeline/sugar/builders.d.ts +0 -96
  393. package/x/timeline/sugar/builders.js +0 -108
  394. package/x/timeline/sugar/builders.js.map +0 -1
  395. package/x/timeline/sugar/omni-test.d.ts +0 -1
  396. package/x/timeline/sugar/omni-test.js +0 -22
  397. package/x/timeline/sugar/omni-test.js.map +0 -1
  398. package/x/timeline/timeline.d.ts +0 -9
  399. package/x/timeline/timeline.js +0 -22
  400. package/x/timeline/timeline.js.map +0 -1
  401. package/x/timeline/utils/audio-stream.d.ts +0 -6
  402. package/x/timeline/utils/audio-stream.js +0 -17
  403. package/x/timeline/utils/audio-stream.js.map +0 -1
  404. package/x/timeline/utils/video-cursor.d.ts +0 -10
  405. package/x/timeline/utils/video-cursor.js +0 -36
  406. package/x/timeline/utils/video-cursor.js.map +0 -1
  407. package/x/tools/common/loader.d.ts +0 -19
  408. package/x/tools/common/loader.js +0 -18
  409. package/x/tools/common/loader.js.map +0 -1
  410. package/x/tools/common/transformer-pipeline.d.ts +0 -8
  411. package/x/tools/common/transformer-pipeline.js +0 -24
  412. package/x/tools/common/transformer-pipeline.js.map +0 -1
  413. package/x/tools/speech-recognition/common/model.d.ts +0 -14
  414. package/x/tools/speech-recognition/common/model.js +0 -16
  415. package/x/tools/speech-recognition/common/model.js.map +0 -1
  416. package/x/tools/speech-recognition/whisper/fns/host.d.ts +0 -13
  417. package/x/tools/speech-recognition/whisper/fns/host.js +0 -19
  418. package/x/tools/speech-recognition/whisper/fns/host.js.map +0 -1
  419. package/x/tools/speech-recognition/whisper/fns/schematic.d.ts +0 -19
  420. package/x/tools/speech-recognition/whisper/fns/schematic.js +0 -2
  421. package/x/tools/speech-recognition/whisper/fns/schematic.js.map +0 -1
  422. package/x/tools/speech-recognition/whisper/fns/work.d.ts +0 -12
  423. package/x/tools/speech-recognition/whisper/fns/work.js +0 -74
  424. package/x/tools/speech-recognition/whisper/fns/work.js.map +0 -1
  425. package/x/tools/speech-recognition/whisper/parts/types.d.ts +0 -31
  426. package/x/tools/speech-recognition/whisper/parts/types.js.map +0 -1
  427. package/x/tools/speech-recognition/whisper/parts/worker.bundle.d.ts +0 -1
  428. package/x/tools/speech-recognition/whisper/parts/worker.bundle.js +0 -4
  429. package/x/tools/speech-recognition/whisper/parts/worker.bundle.js.map +0 -1
  430. package/x/tools/speech-recognition/whisper/parts/worker.bundle.min.js +0 -8
  431. package/x/tools/speech-recognition/whisper/parts/worker.bundle.min.js.map +0 -7
  432. package/x/tools/speech-recognition/whisper/tool.d.ts +0 -12
  433. package/x/tools/speech-recognition/whisper/tool.js +0 -63
  434. package/x/tools/speech-recognition/whisper/tool.js.map +0 -1
  435. /package/x/{tests.test.d.ts → tests.bundle.d.ts} +0 -0
  436. /package/x/{tools/speech-recognition/whisper → timeline/parts/waveform}/parts/types.js +0 -0
@@ -14,13 +14,23 @@ export class Media {
14
14
 
15
15
  static async analyze(datafile: Datafile) {
16
16
  const media = new this(datafile)
17
- media.duration = 10
18
- const {video, audio} = await this.#has("/assets/temp/gl.mp4")
17
+ const duration = (await this.duration(datafile.url)) * 1000
18
+ media.duration = duration
19
+ const {video, audio} = await this.#has(datafile.url)
19
20
  media.hasAudio = audio
20
21
  media.hasVideo = video
21
22
  return media
22
23
  }
23
24
 
25
+ static async duration(source: DecoderSource) {
26
+ const input = new Input({
27
+ formats: ALL_FORMATS,
28
+ source: await loadDecoderSource(source)
29
+ })
30
+ const duration = await input.computeDuration()
31
+ return Number(duration.toFixed(5)) // fix weird floating points
32
+ }
33
+
24
34
  static async #has(source: DecoderSource) {
25
35
  const input = new Input({
26
36
  formats: ALL_FORMATS,
@@ -1,27 +1,30 @@
1
1
 
2
- import {MapG} from "@e280/stz"
2
+ import {GMap} from "@e280/stz"
3
3
  import {Hash} from "./basics.js"
4
4
  import {Media} from "./media.js"
5
5
  import {Resource} from "./resource.js"
6
6
  import {Datafile} from "../utils/datafile.js"
7
7
 
8
8
  export class ResourcePool {
9
- #map = new MapG<Hash, Resource.Any>
9
+ #map = new GMap<Hash, Resource.Any>
10
10
 
11
11
  /** store a media file (avoids duplicates via hash) */
12
12
  async store(datafile: Datafile) {
13
13
  const media = await Media.analyze(datafile)
14
14
  const {hash} = media.datafile.checksum
15
- const {filename, bytes} = media.datafile
15
+ const {filename, bytes, url, blob} = media.datafile
16
16
 
17
17
  if (this.#map.has(hash)) {
18
18
  const alreadyExists = this.#map.require(hash)
19
19
  alreadyExists.filename = filename
20
20
  }
21
21
  else
22
- this.#map.set(hash, {kind: "media", filename, bytes})
22
+ this.#map.set(hash, {kind: "media", filename, bytes, url, blob, duration: media.duration})
23
23
 
24
24
  return media
25
25
  }
26
- }
27
26
 
27
+ require(hash: Hash) {
28
+ return this.#map.require(hash)
29
+ }
30
+ }
@@ -4,6 +4,9 @@ export namespace Resource {
4
4
  kind: "media"
5
5
  filename: string
6
6
  bytes: Uint8Array
7
+ blob: Blob
8
+ url: string
9
+ duration: number
7
10
  }
8
11
 
9
12
  export type Any = Media
@@ -0,0 +1,72 @@
1
+
2
+ import {Driver} from "../../../../driver/driver.js"
3
+ import {DecoderSource} from "../../../../driver/fns/schematic.js"
4
+
5
+ export const PEAK_LEVELS = [2048, 1024, 512, 256, 128, 64, 32] as const
6
+
7
+ export async function collectPeakLevels(driver: Driver, source: DecoderSource) {
8
+ const duration = (await driver.getAudioDuration(source)) ?? 0
9
+ const readable = driver.decodeAudio({source}).readable
10
+ const finestSamplesPerPeak = PEAK_LEVELS[PEAK_LEVELS.length - 1]
11
+ const finestPeaks: number[] = []
12
+
13
+ let currentMax = 0
14
+ let sampleCount = 0
15
+ let sampleRate = 0
16
+
17
+ for await (const audioData of readable) {
18
+ sampleRate ||= audioData.sampleRate
19
+
20
+ const frames = audioData.numberOfFrames
21
+ const plane = new Float32Array(frames)
22
+ audioData.copyTo(plane, {planeIndex: 0})
23
+
24
+ for (let i = 0; i < plane.length; i++) {
25
+ const amplitude = Math.abs(plane[i]!)
26
+ if (amplitude > currentMax) currentMax = amplitude
27
+
28
+ sampleCount++
29
+ if (sampleCount >= finestSamplesPerPeak) {
30
+ finestPeaks.push(currentMax)
31
+ currentMax = 0
32
+ sampleCount = 0
33
+ }
34
+ }
35
+
36
+ audioData.close()
37
+ }
38
+
39
+ if (sampleCount > 0) finestPeaks.push(currentMax)
40
+
41
+ const base = new Float32Array(finestPeaks)
42
+ const levels = PEAK_LEVELS.map(samplesPerPeak => {
43
+ const factor = Math.max(1, Math.round(samplesPerPeak / finestSamplesPerPeak))
44
+ const peaks = factor === 1 ? base : downsampleMax(base, factor)
45
+ return {
46
+ samplesPerPeak,
47
+ peaks,
48
+ peaksPerSecond: sampleRate > 0 ? sampleRate / samplesPerPeak : 0,
49
+ }
50
+ })
51
+
52
+ return {duration, levels}
53
+ }
54
+
55
+ function downsampleMax(peaks: Float32Array, factor: number) {
56
+ const downsampled = new Float32Array(Math.ceil(peaks.length / factor))
57
+
58
+ for (let i = 0; i < downsampled.length; i++) {
59
+ let maxPeak = 0
60
+ const start = i * factor
61
+ const end = Math.min(start + factor, peaks.length)
62
+
63
+ for (let j = start; j < end; j++) {
64
+ if (peaks[j]! > maxPeak) maxPeak = peaks[j]!
65
+ }
66
+
67
+ downsampled[i] = maxPeak
68
+ }
69
+
70
+ return downsampled
71
+ }
72
+
@@ -0,0 +1,45 @@
1
+
2
+ export function renderTile(
3
+ peaks: Float32Array,
4
+ opts: {
5
+ width: number
6
+ height: number
7
+ color: string
8
+ }
9
+ ) {
10
+ const dpr = typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1
11
+ const canvas = document.createElement("canvas")
12
+ canvas.width = opts.width * dpr
13
+ canvas.height = opts.height * dpr
14
+ canvas.style.width = `${opts.width}px`
15
+ canvas.style.height = `${opts.height}px`
16
+
17
+ const ctx = canvas.getContext("2d")
18
+ if (!ctx) return canvas
19
+
20
+ ctx.scale(dpr, dpr)
21
+ ctx.fillStyle = opts.color
22
+
23
+ const centerY = opts.height / 2
24
+ const columns = Math.max(1, opts.width)
25
+ const peaksPerPixel = peaks.length / columns
26
+
27
+ for (let px = 0; px < columns; px++) {
28
+ const startIndex = Math.floor(px * peaksPerPixel)
29
+ const endIndex = Math.max(
30
+ startIndex + 1,
31
+ Math.floor((px + 1) * peaksPerPixel)
32
+ )
33
+
34
+ let maxPeak = 0
35
+ for (let i = startIndex; i < endIndex && i < peaks.length; i++) {
36
+ if (peaks[i]! > maxPeak) maxPeak = peaks[i]!
37
+ }
38
+
39
+ const barHeight = maxPeak * opts.height
40
+ ctx.fillRect(px, centerY - barHeight / 2, 1, barHeight)
41
+ }
42
+
43
+ return canvas
44
+ }
45
+
@@ -0,0 +1,24 @@
1
+ export interface WaveformTileData {
2
+ startTime: number
3
+ endTime: number
4
+ peaks: Float32Array
5
+ canvas: HTMLCanvasElement
6
+ }
7
+
8
+ export interface WaveformOptions {
9
+ tileSize?: number
10
+ zoom?: number
11
+ tileWidth?: number
12
+ tileHeight?: number
13
+ preloadMargin?: number
14
+ color?: string
15
+ onChange?: (tiles: WaveformTileData[]) => void
16
+ }
17
+
18
+ export type WaveformTimeRange = [start: number, end: number]
19
+
20
+ export type WaveformPeakLevel = {
21
+ samplesPerPeak: number
22
+ peaks: Float32Array
23
+ peaksPerSecond: number
24
+ }
@@ -0,0 +1,161 @@
1
+
2
+ import {renderTile} from "./parts/render.js"
3
+ import {Driver} from "../../../driver/driver.js"
4
+ import {collectPeakLevels} from "./parts/collect.js"
5
+ import {DecoderSource} from "../../../driver/fns/schematic.js"
6
+ import {WaveformOptions, WaveformPeakLevel, WaveformTileData, WaveformTimeRange} from "./parts/types.js"
7
+
8
+ const MAX_TILE_WIDTH = 4096
9
+
10
+ export class Waveform {
11
+ #tiles = new Map<number, WaveformTileData>()
12
+ #activeRange: WaveformTimeRange = [0, 0]
13
+ #visibleRange: WaveformTimeRange = [0, 0]
14
+
15
+ #zoom
16
+ #levels
17
+ #onChange
18
+ #updateQueued = false
19
+
20
+ readonly color
21
+ readonly duration
22
+ readonly tileSize
23
+ readonly tileHeight
24
+ readonly preloadMargin
25
+
26
+ private constructor(levels: WaveformPeakLevel[], duration: number, options: WaveformOptions) {
27
+ this.#levels = levels
28
+ this.duration = duration
29
+ this.tileSize = options.tileSize ?? 1
30
+ this.#zoom = options.zoom ?? ((options.tileWidth ?? 256) / this.tileSize)
31
+ this.tileHeight = options.tileHeight ?? 96
32
+ this.preloadMargin = options.preloadMargin ?? 2
33
+ this.color = options.color ?? "rgb(3, 148, 129)"
34
+ this.#onChange = options.onChange
35
+ }
36
+
37
+ static async init(driver: Driver, source: DecoderSource, options: WaveformOptions = {}) {
38
+ const {duration, levels} = await collectPeakLevels(driver, source)
39
+ return new Waveform(levels, duration, options)
40
+ }
41
+
42
+ /** Waveform render density in pixels per second. */
43
+ set zoom(pixelsPerSecond: number) {
44
+ const next = Math.max(1, pixelsPerSecond)
45
+ if (next === this.#zoom)
46
+ return
47
+
48
+ this.#zoom = next
49
+ this.#tiles.clear()
50
+ this.#queueUpdate()
51
+ }
52
+
53
+ get zoom() {
54
+ return this.#zoom
55
+ }
56
+
57
+ get range() {
58
+ return this.#visibleRange
59
+ }
60
+
61
+ #computeActiveRange([start, end]: WaveformTimeRange, margin = 1): WaveformTimeRange {
62
+ const visibleSize = end - start
63
+ return [
64
+ Math.max(0, start - visibleSize * margin),
65
+ Math.min(this.duration, end + visibleSize * margin),
66
+ ]
67
+ }
68
+
69
+ set range(visibleRange: WaveformTimeRange) {
70
+ this.#visibleRange = visibleRange
71
+
72
+ const [visibleStart, visibleEnd] = visibleRange
73
+ const visibleSize = visibleEnd - visibleStart
74
+ const [activeStart, activeEnd] = this.#activeRange
75
+
76
+ const leftBuffered = activeStart > 0
77
+ const rightBuffered = activeEnd < this.duration
78
+ const leftSettled = !leftBuffered || visibleStart >= activeStart + visibleSize
79
+ const rightSettled = !rightBuffered || visibleEnd <= activeEnd - visibleSize
80
+
81
+ if (leftSettled && rightSettled) return
82
+
83
+ this.#activeRange = this.#computeActiveRange(visibleRange, this.preloadMargin)
84
+ this.#queueUpdate()
85
+ }
86
+
87
+ #queueUpdate() {
88
+ if (this.#updateQueued) return
89
+ this.#updateQueued = true
90
+
91
+ queueMicrotask(() => {
92
+ this.#updateQueued = false
93
+ this.#generateTiles()
94
+ })
95
+ }
96
+
97
+ #generateTiles() {
98
+ const [rangeStart, rangeEnd] = this.#activeRange
99
+ const neededStarts = new Set<number>()
100
+ const level = this.#levelForZoom()
101
+
102
+ const firstStart = Math.max(0, Math.floor(rangeStart / this.tileSize) * this.tileSize)
103
+ const lastStart = Math.min(this.duration, rangeEnd)
104
+
105
+ for (let startTime = firstStart; startTime <= lastStart; startTime += this.tileSize) {
106
+ neededStarts.add(startTime)
107
+ }
108
+
109
+ for (const startTime of neededStarts) {
110
+ if (!this.#tiles.has(startTime)) {
111
+ const endTime = Math.min(startTime + this.tileSize, this.duration)
112
+ this.#tiles.set(startTime, this.#buildTileData(startTime, endTime, level))
113
+ }
114
+ }
115
+
116
+ for (const startTime of this.#tiles.keys()) {
117
+ if (!neededStarts.has(startTime)) this.#tiles.delete(startTime)
118
+ }
119
+
120
+ this.#emit()
121
+ }
122
+
123
+ #buildTileData(startTime: number, endTime: number, level: WaveformPeakLevel): WaveformTileData {
124
+ const peaks = this.#slicePeaks(level, startTime, endTime)
125
+ return {
126
+ startTime,
127
+ endTime,
128
+ peaks,
129
+ canvas: renderTile(peaks, {
130
+ width: this.#tilePixelWidth(startTime, endTime),
131
+ height: this.tileHeight,
132
+ color: this.color,
133
+ }),
134
+ }
135
+ }
136
+
137
+ #levelForZoom() {
138
+ return this.#levels.find(level => level.peaksPerSecond >= this.#zoom)
139
+ ?? this.#levels[this.#levels.length - 1]!
140
+ }
141
+
142
+ #slicePeaks(level: WaveformPeakLevel, startTime: number, endTime: number) {
143
+ if (!level.peaksPerSecond) return new Float32Array()
144
+ const from = Math.max(0, Math.floor(startTime * level.peaksPerSecond))
145
+ const to = Math.max(from + 1, Math.min(level.peaks.length, Math.ceil(endTime * level.peaksPerSecond)))
146
+ return level.peaks.slice(from, to)
147
+ }
148
+
149
+ #tilePixelWidth(startTime: number, endTime: number) {
150
+ return Math.min(MAX_TILE_WIDTH, Math.max(1, Math.ceil((endTime - startTime) * this.#zoom)))
151
+ }
152
+
153
+ #emit() {
154
+ if (!this.#onChange) return
155
+ this.#onChange([...this.#tiles.values()].sort((a, b) => a.startTime - b.startTime))
156
+ }
157
+
158
+ getTiles() {
159
+ return this.#tiles
160
+ }
161
+ }
@@ -0,0 +1,17 @@
1
+ // this is mutating fn
2
+ export const applyGainToPlanar = (
3
+ planes: Float32Array[],
4
+ gain: number
5
+ ) => {
6
+ if (gain === 1)
7
+ return
8
+ // planes
9
+
10
+ for (const plane of planes) {
11
+ for (let i = 0; i < plane.length; i++) {
12
+ plane[i] *= gain
13
+ }
14
+ }
15
+
16
+ // return planes
17
+ }
@@ -0,0 +1,133 @@
1
+
2
+ export type AudioPlanesInput = {
3
+ planes: Float32Array[]
4
+ sampleRate: number
5
+ timestamp: number
6
+ }
7
+
8
+ export type MixedChunk = {
9
+ planar: Float32Array
10
+ sampleRate: number
11
+ channels: number
12
+ frames: number
13
+ startFrame: number
14
+ }
15
+
16
+ type ActiveSample = {
17
+ startFrame: number
18
+ endFrame: number
19
+ data: Float32Array[]
20
+ }
21
+
22
+ export type AudioMixOptions = {
23
+ chunkFrames?: number
24
+ clamp?: boolean
25
+ }
26
+
27
+ export class AudioMix {
28
+ readonly #chunkFrames: number
29
+ readonly #clamp: boolean
30
+
31
+ constructor(options: AudioMixOptions = {}) {
32
+ this.#chunkFrames = options.chunkFrames ?? 1024
33
+ this.#clamp = options.clamp ?? true
34
+ }
35
+
36
+ async *mix(samples: AsyncIterable<AudioPlanesInput>): AsyncGenerator<MixedChunk> {
37
+ const chunkFrames = this.#chunkFrames
38
+ let sampleRate: number | null = null
39
+ let channels: number | null = null
40
+ const active: ActiveSample[] = []
41
+ let nextFrame = 0
42
+ let maxEnd = 0
43
+
44
+ for await (const input of samples) {
45
+ if (channels === null) {
46
+ channels = input.planes.length
47
+ sampleRate = input.sampleRate
48
+ } else {
49
+ if (input.planes.length !== channels) throw new Error(`Channel count changed`)
50
+ if (input.sampleRate !== sampleRate) throw new Error(`Sample rate changed`)
51
+ }
52
+
53
+ const inputStart = Math.round(input.timestamp * sampleRate)
54
+ const frames = input.planes[0]?.length ?? 0
55
+
56
+ while (nextFrame + chunkFrames <= inputStart) {
57
+ yield this.#processChunk(active, nextFrame, channels, sampleRate)
58
+ nextFrame += chunkFrames
59
+ }
60
+
61
+ active.push({
62
+ startFrame: inputStart,
63
+ endFrame: inputStart + frames,
64
+ data: input.planes
65
+ })
66
+
67
+ maxEnd = Math.max(maxEnd, inputStart + frames)
68
+ }
69
+
70
+ if (channels !== null && sampleRate !== null) {
71
+ while (nextFrame < maxEnd) {
72
+ yield this.#processChunk(active, nextFrame, channels, sampleRate)
73
+ nextFrame += chunkFrames
74
+ }
75
+ }
76
+ }
77
+
78
+ #processChunk(
79
+ active: ActiveSample[],
80
+ currentStartFrame: number,
81
+ channels: number,
82
+ sampleRate: number
83
+ ): MixedChunk {
84
+ const chunkFrames = this.#chunkFrames
85
+ const outputBuffer = new Float32Array(channels * chunkFrames)
86
+ const chunkEnd = currentStartFrame + chunkFrames
87
+
88
+ for (let ch = 0; ch < channels; ch++) {
89
+ const channelOffset = ch * chunkFrames
90
+ const outChannelView = outputBuffer.subarray(channelOffset, channelOffset + chunkFrames)
91
+
92
+ for (const sample of active) {
93
+ const data = sample.data[ch]
94
+ if (!data) continue
95
+
96
+ const start = Math.max(currentStartFrame, sample.startFrame)
97
+ const end = Math.min(chunkEnd, sample.endFrame)
98
+
99
+ if (start >= end) continue
100
+
101
+ const dstIdx = start - currentStartFrame
102
+ const srcIdx = start - sample.startFrame
103
+ const len = end - start
104
+
105
+ for (let i = 0; i < len; i++) {
106
+ outChannelView[dstIdx + i] += data[srcIdx + i]
107
+ }
108
+ }
109
+
110
+ if (this.#clamp) {
111
+ for (let i = 0; i < chunkFrames; i++) {
112
+ const v = outChannelView[i]
113
+ outChannelView[i] = v < -1.0 ? -1.0 : (v > 1.0 ? 1.0 : v)
114
+ }
115
+ }
116
+ }
117
+
118
+ for (let i = active.length - 1; i >= 0; i--) {
119
+ if (active[i].endFrame <= chunkEnd) {
120
+ active.splice(i, 1)
121
+ }
122
+ }
123
+
124
+ return {
125
+ planar: outputBuffer,
126
+ sampleRate,
127
+ channels,
128
+ frames: chunkFrames,
129
+ startFrame: currentStartFrame
130
+ }
131
+ }
132
+ }
133
+
@@ -0,0 +1,129 @@
1
+
2
+ import {ms, Ms} from "../../../../units/ms.js"
3
+ import {Driver} from "../../../../driver/driver.js"
4
+ import {TimelineFile} from "../../../parts/basics.js"
5
+ import {DecoderSource} from "../../../../driver/fns/schematic.js"
6
+ import {createVisualSampler} from "../../parts/samplers/visual/sampler.js"
7
+
8
+ /**
9
+ * forward-only frame cursor optimized for export purposes.
10
+ * it uses mediabunny internally so the support for non-clients
11
+ * should be done from mediabunny custom decoder/encoder
12
+ */
13
+
14
+ export class CursorVisualSampler {
15
+ #lastTimecode = -Infinity
16
+ #videoCursors = new Map<number, VideoFrameCursor>()
17
+ #sampler
18
+
19
+ constructor(
20
+ private driver: Driver,
21
+ private resolveMedia: (hash: string) => DecoderSource,
22
+ private timeline: TimelineFile
23
+ ) {
24
+ this.#sampler = createVisualSampler(this.resolveMedia, (item, time) => {
25
+ const targetUs = toUs(time)
26
+ let cursor = this.#videoCursors.get(item.id)
27
+
28
+ if (!cursor) {
29
+ const source = this.resolveMedia(item.mediaHash)
30
+ const endUs = toUs(ms(item.start + item.duration))
31
+ cursor = this.#createVideoCursor(source, targetUs, endUs)
32
+ this.#videoCursors.set(item.id, cursor)
33
+ }
34
+
35
+ return cursor.next(targetUs)
36
+ })
37
+ }
38
+
39
+ next(timecode: Ms) {
40
+ if (timecode < this.#lastTimecode)
41
+ throw new Error(`Forward-only cursor regression: ${timecode}ms < ${this.#lastTimecode}ms`)
42
+
43
+ this.#lastTimecode = timecode
44
+ return this.#sampler.sample(this.timeline, timecode)
45
+ }
46
+
47
+ async cancel() {
48
+ await Promise.all([...this.#videoCursors.values()].map(c => c.cancel()))
49
+ this.#videoCursors.clear()
50
+ }
51
+
52
+ #createVideoCursor(source: DecoderSource, startUs: number, endUs: number): VideoFrameCursor {
53
+ const video = this.driver.decodeVideo({source, start: startUs / 1_000_000, end: endUs / 1_000_000})
54
+ const reader = video.readable.getReader()
55
+
56
+ let current: VideoFrame | null = null
57
+ let nextPromise: Promise<VideoFrame | null> | null = null
58
+ let ended = false
59
+
60
+ const readNext = async () => {
61
+ if (ended) return null
62
+ const {done, value} = await reader.read()
63
+ if (done) return (ended = true, null)
64
+
65
+ const frame = new VideoFrame(value)
66
+ value.close()
67
+ return frame
68
+ }
69
+
70
+ return {
71
+ async next(targetUs: number): Promise<VideoFrame | undefined> {
72
+ current ??= await readNext()
73
+ if (!current) return undefined
74
+
75
+ while (true) {
76
+ nextPromise ??= readNext()
77
+ const nextFrame = await nextPromise
78
+
79
+ if (!nextFrame) return new VideoFrame(current)
80
+
81
+ const currentUs = current.timestamp ?? -Infinity
82
+ const nextUs = nextFrame.timestamp ?? currentUs
83
+
84
+ if (nextUs < targetUs) {
85
+ current.close()
86
+ current = nextFrame
87
+ nextPromise = null
88
+ continue
89
+ }
90
+
91
+ const useNext = Math.abs(nextUs - targetUs) < Math.abs(currentUs - targetUs)
92
+
93
+ if (useNext) {
94
+ current.close()
95
+ current = nextFrame
96
+ nextPromise = null
97
+ continue
98
+ }
99
+
100
+ return new VideoFrame(current)
101
+ }
102
+ },
103
+
104
+ async cancel() {
105
+ const pending = nextPromise
106
+ nextPromise = null
107
+ ended = true
108
+
109
+ const buffered = await pending?.catch(() => null)
110
+ buffered?.close()
111
+
112
+ current?.close()
113
+ current = null
114
+
115
+ video.cancel()
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ const toUs = (ms: Ms) => Math.round(ms * 1_000)
122
+
123
+ type StreamCursor<T> = {
124
+ next(target: number): Promise<T | undefined>
125
+ cancel(): Promise<void>
126
+ }
127
+
128
+ type VideoFrameCursor = StreamCursor<VideoFrame>
129
+