@tscaps/engine 0.3.0 → 0.4.0

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 (251) hide show
  1. package/README.md +35 -8
  2. package/dist/modules/document/CssVariable.d.ts +6 -0
  3. package/dist/modules/document/CssVariable.d.ts.map +1 -1
  4. package/dist/modules/document/CssVariable.js +6 -0
  5. package/dist/modules/document/CssVariable.js.map +1 -1
  6. package/dist/modules/document/Document.d.ts +3 -0
  7. package/dist/modules/document/Document.d.ts.map +1 -1
  8. package/dist/modules/document/Document.js +12 -1
  9. package/dist/modules/document/Document.js.map +1 -1
  10. package/dist/modules/document/DocumentEditor.d.ts +16 -4
  11. package/dist/modules/document/DocumentEditor.d.ts.map +1 -1
  12. package/dist/modules/document/DocumentEditor.js +14 -10
  13. package/dist/modules/document/DocumentEditor.js.map +1 -1
  14. package/dist/modules/document/Line.d.ts +6 -0
  15. package/dist/modules/document/Line.d.ts.map +1 -1
  16. package/dist/modules/document/Line.js +10 -0
  17. package/dist/modules/document/Line.js.map +1 -1
  18. package/dist/modules/document/Word.d.ts +8 -0
  19. package/dist/modules/document/Word.d.ts.map +1 -1
  20. package/dist/modules/document/Word.js +11 -1
  21. package/dist/modules/document/Word.js.map +1 -1
  22. package/dist/modules/pipeline/RenderPipelineBuilder.d.ts +1 -1
  23. package/dist/modules/pipeline/RenderPipelineBuilder.d.ts.map +1 -1
  24. package/dist/modules/pipeline/RenderPipelineBuilder.js +15 -5
  25. package/dist/modules/pipeline/RenderPipelineBuilder.js.map +1 -1
  26. package/dist/modules/rendering/BrowserSubtitleFrameRenderer.d.ts +18 -8
  27. package/dist/modules/rendering/BrowserSubtitleFrameRenderer.d.ts.map +1 -1
  28. package/dist/modules/rendering/BrowserSubtitleFrameRenderer.js +27 -21
  29. package/dist/modules/rendering/BrowserSubtitleFrameRenderer.js.map +1 -1
  30. package/dist/modules/rendering/SubtitleFrameRenderer.d.ts +41 -33
  31. package/dist/modules/rendering/SubtitleFrameRenderer.d.ts.map +1 -1
  32. package/dist/modules/rendering/index.d.ts +4 -0
  33. package/dist/modules/rendering/index.d.ts.map +1 -1
  34. package/dist/modules/rendering/index.js +2 -0
  35. package/dist/modules/rendering/index.js.map +1 -1
  36. package/dist/modules/rendering/subtitle/ActiveRenderSession.d.ts +13 -6
  37. package/dist/modules/rendering/subtitle/ActiveRenderSession.d.ts.map +1 -1
  38. package/dist/modules/rendering/subtitle/ActiveRenderSession.js +16 -9
  39. package/dist/modules/rendering/subtitle/ActiveRenderSession.js.map +1 -1
  40. package/dist/modules/rendering/subtitle/ActiveRenderSessionFactory.d.ts +5 -2
  41. package/dist/modules/rendering/subtitle/ActiveRenderSessionFactory.d.ts.map +1 -1
  42. package/dist/modules/rendering/subtitle/ActiveRenderSessionFactory.js +26 -8
  43. package/dist/modules/rendering/subtitle/ActiveRenderSessionFactory.js.map +1 -1
  44. package/dist/modules/rendering/subtitle/AnimationStateFingerprint.d.ts +20 -0
  45. package/dist/modules/rendering/subtitle/AnimationStateFingerprint.d.ts.map +1 -0
  46. package/dist/modules/rendering/subtitle/AnimationStateFingerprint.js +2 -0
  47. package/dist/modules/rendering/subtitle/AnimationStateFingerprint.js.map +1 -0
  48. package/dist/modules/rendering/subtitle/AssetGroupBuilder.d.ts +4 -0
  49. package/dist/modules/rendering/subtitle/AssetGroupBuilder.d.ts.map +1 -1
  50. package/dist/modules/rendering/subtitle/AssetGroupBuilder.js +8 -0
  51. package/dist/modules/rendering/subtitle/AssetGroupBuilder.js.map +1 -1
  52. package/dist/modules/rendering/subtitle/BatchPlanner.d.ts +50 -5
  53. package/dist/modules/rendering/subtitle/BatchPlanner.d.ts.map +1 -1
  54. package/dist/modules/rendering/subtitle/BatchPlanner.js +97 -15
  55. package/dist/modules/rendering/subtitle/BatchPlanner.js.map +1 -1
  56. package/dist/modules/rendering/subtitle/ElementWidthMeasurer.d.ts +56 -0
  57. package/dist/modules/rendering/subtitle/ElementWidthMeasurer.d.ts.map +1 -0
  58. package/dist/modules/rendering/subtitle/ElementWidthMeasurer.js +119 -0
  59. package/dist/modules/rendering/subtitle/ElementWidthMeasurer.js.map +1 -0
  60. package/dist/modules/rendering/subtitle/ElementWidths.d.ts +23 -0
  61. package/dist/modules/rendering/subtitle/ElementWidths.d.ts.map +1 -0
  62. package/dist/modules/rendering/subtitle/ElementWidths.js +29 -0
  63. package/dist/modules/rendering/subtitle/ElementWidths.js.map +1 -0
  64. package/dist/modules/rendering/subtitle/ImageDecodeSpriteSheetRasterProbe.d.ts +18 -0
  65. package/dist/modules/rendering/subtitle/ImageDecodeSpriteSheetRasterProbe.d.ts.map +1 -0
  66. package/dist/modules/rendering/subtitle/ImageDecodeSpriteSheetRasterProbe.js +42 -0
  67. package/dist/modules/rendering/subtitle/ImageDecodeSpriteSheetRasterProbe.js.map +1 -0
  68. package/dist/modules/rendering/subtitle/KeyframeScanAnimationStateFingerprint.d.ts +35 -0
  69. package/dist/modules/rendering/subtitle/KeyframeScanAnimationStateFingerprint.d.ts.map +1 -0
  70. package/dist/modules/rendering/subtitle/KeyframeScanAnimationStateFingerprint.js +64 -0
  71. package/dist/modules/rendering/subtitle/KeyframeScanAnimationStateFingerprint.js.map +1 -0
  72. package/dist/modules/rendering/subtitle/PreparedStyle.d.ts +2 -0
  73. package/dist/modules/rendering/subtitle/PreparedStyle.d.ts.map +1 -1
  74. package/dist/modules/rendering/subtitle/PreparedStyleFactory.d.ts.map +1 -1
  75. package/dist/modules/rendering/subtitle/PreparedStyleFactory.js +12 -1
  76. package/dist/modules/rendering/subtitle/PreparedStyleFactory.js.map +1 -1
  77. package/dist/modules/rendering/subtitle/SegmentAnchorVarsBuilder.d.ts +28 -0
  78. package/dist/modules/rendering/subtitle/SegmentAnchorVarsBuilder.d.ts.map +1 -0
  79. package/dist/modules/rendering/subtitle/SegmentAnchorVarsBuilder.js +23 -0
  80. package/dist/modules/rendering/subtitle/SegmentAnchorVarsBuilder.js.map +1 -0
  81. package/dist/modules/rendering/subtitle/SegmentSubtreeHtmlBuilder.d.ts +3 -0
  82. package/dist/modules/rendering/subtitle/SegmentSubtreeHtmlBuilder.d.ts.map +1 -1
  83. package/dist/modules/rendering/subtitle/SegmentSubtreeHtmlBuilder.js +12 -3
  84. package/dist/modules/rendering/subtitle/SegmentSubtreeHtmlBuilder.js.map +1 -1
  85. package/dist/modules/rendering/subtitle/SegmentWrapperRenderer.d.ts +7 -1
  86. package/dist/modules/rendering/subtitle/SegmentWrapperRenderer.d.ts.map +1 -1
  87. package/dist/modules/rendering/subtitle/SegmentWrapperRenderer.js +23 -5
  88. package/dist/modules/rendering/subtitle/SegmentWrapperRenderer.js.map +1 -1
  89. package/dist/modules/rendering/subtitle/SpriteSheetProbeObserver.d.ts +29 -0
  90. package/dist/modules/rendering/subtitle/SpriteSheetProbeObserver.d.ts.map +1 -0
  91. package/dist/modules/rendering/subtitle/SpriteSheetProbeObserver.js +2 -0
  92. package/dist/modules/rendering/subtitle/SpriteSheetProbeObserver.js.map +1 -0
  93. package/dist/modules/rendering/subtitle/SpriteSheetRasterProbe.d.ts +19 -0
  94. package/dist/modules/rendering/subtitle/SpriteSheetRasterProbe.d.ts.map +1 -0
  95. package/dist/modules/rendering/subtitle/SpriteSheetRasterProbe.js +2 -0
  96. package/dist/modules/rendering/subtitle/SpriteSheetRasterProbe.js.map +1 -0
  97. package/dist/modules/rendering/subtitle/SpriteSheetSizeProbe.d.ts +31 -0
  98. package/dist/modules/rendering/subtitle/SpriteSheetSizeProbe.d.ts.map +1 -0
  99. package/dist/modules/rendering/subtitle/SpriteSheetSizeProbe.js +89 -0
  100. package/dist/modules/rendering/subtitle/SpriteSheetSizeProbe.js.map +1 -0
  101. package/dist/modules/rendering/subtitle/SubtreeAnimationReading.d.ts +49 -0
  102. package/dist/modules/rendering/subtitle/SubtreeAnimationReading.d.ts.map +1 -0
  103. package/dist/modules/rendering/subtitle/SubtreeAnimationReading.js +87 -0
  104. package/dist/modules/rendering/subtitle/SubtreeAnimationReading.js.map +1 -0
  105. package/dist/modules/rendering/subtitle/SubtreeAnimationSupport.d.ts +17 -0
  106. package/dist/modules/rendering/subtitle/SubtreeAnimationSupport.d.ts.map +1 -0
  107. package/dist/modules/rendering/subtitle/SubtreeAnimationSupport.js +53 -0
  108. package/dist/modules/rendering/subtitle/SubtreeAnimationSupport.js.map +1 -0
  109. package/dist/modules/rendering/subtitle/SubtreeMountAnimationStateFingerprint.d.ts +62 -0
  110. package/dist/modules/rendering/subtitle/SubtreeMountAnimationStateFingerprint.d.ts.map +1 -0
  111. package/dist/modules/rendering/subtitle/SubtreeMountAnimationStateFingerprint.js +153 -0
  112. package/dist/modules/rendering/subtitle/SubtreeMountAnimationStateFingerprint.js.map +1 -0
  113. package/dist/modules/rendering/subtitle/SvgFilterStateFingerprint.d.ts +47 -0
  114. package/dist/modules/rendering/subtitle/SvgFilterStateFingerprint.d.ts.map +1 -0
  115. package/dist/modules/rendering/subtitle/SvgFilterStateFingerprint.js +69 -0
  116. package/dist/modules/rendering/subtitle/SvgFilterStateFingerprint.js.map +1 -0
  117. package/dist/modules/rendering/subtitle/UnknownAnimationStateFingerprint.d.ts +9 -0
  118. package/dist/modules/rendering/subtitle/UnknownAnimationStateFingerprint.d.ts.map +1 -0
  119. package/dist/modules/rendering/subtitle/UnknownAnimationStateFingerprint.js +10 -0
  120. package/dist/modules/rendering/subtitle/UnknownAnimationStateFingerprint.js.map +1 -0
  121. package/dist/modules/rendering/subtitle/VideoFrameVarsBuilder.d.ts.map +1 -1
  122. package/dist/modules/rendering/subtitle/VideoFrameVarsBuilder.js +2 -0
  123. package/dist/modules/rendering/subtitle/VideoFrameVarsBuilder.js.map +1 -1
  124. package/dist/modules/rendering/types/ElementRenderOverrides.d.ts +2 -0
  125. package/dist/modules/rendering/types/ElementRenderOverrides.d.ts.map +1 -1
  126. package/dist/modules/rendering/types/ElementRenderOverrides.js +4 -0
  127. package/dist/modules/rendering/types/ElementRenderOverrides.js.map +1 -1
  128. package/dist/modules/splitting/BalancedLineSplitter.d.ts +9 -0
  129. package/dist/modules/splitting/BalancedLineSplitter.d.ts.map +1 -1
  130. package/dist/modules/splitting/BalancedLineSplitter.js +15 -3
  131. package/dist/modules/splitting/BalancedLineSplitter.js.map +1 -1
  132. package/dist/modules/splitting/BalancedPixelWidthLineSplitter.d.ts +1 -4
  133. package/dist/modules/splitting/BalancedPixelWidthLineSplitter.d.ts.map +1 -1
  134. package/dist/modules/splitting/BalancedPixelWidthLineSplitter.js +5 -7
  135. package/dist/modules/splitting/BalancedPixelWidthLineSplitter.js.map +1 -1
  136. package/dist/modules/splitting/DomProbeCanvasTextMeasurer.d.ts +16 -7
  137. package/dist/modules/splitting/DomProbeCanvasTextMeasurer.d.ts.map +1 -1
  138. package/dist/modules/splitting/DomProbeCanvasTextMeasurer.js +44 -33
  139. package/dist/modules/splitting/DomProbeCanvasTextMeasurer.js.map +1 -1
  140. package/dist/modules/splitting/TextMeasurer.d.ts +9 -4
  141. package/dist/modules/splitting/TextMeasurer.d.ts.map +1 -1
  142. package/dist/modules/svg-filter/SvgFilter.d.ts +9 -0
  143. package/dist/modules/svg-filter/SvgFilter.d.ts.map +1 -1
  144. package/dist/modules/svg-filter/SvgFilter.js +17 -0
  145. package/dist/modules/svg-filter/SvgFilter.js.map +1 -1
  146. package/dist/modules/svg-filter/SvgFilterDefinitions.d.ts +7 -0
  147. package/dist/modules/svg-filter/SvgFilterDefinitions.d.ts.map +1 -1
  148. package/dist/modules/svg-filter/SvgFilterDefinitions.js +17 -0
  149. package/dist/modules/svg-filter/SvgFilterDefinitions.js.map +1 -1
  150. package/dist/modules/tagging/RegexTagger.js +1 -2
  151. package/dist/modules/tagging/RegexTagger.js.map +1 -1
  152. package/dist/modules/tagging/SpanTagger.js +1 -2
  153. package/dist/modules/tagging/SpanTagger.js.map +1 -1
  154. package/dist/modules/tagging/StructureTagger.js +1 -2
  155. package/dist/modules/tagging/StructureTagger.js.map +1 -1
  156. package/dist/modules/tagging/WordlistTagger.js +1 -2
  157. package/dist/modules/tagging/WordlistTagger.js.map +1 -1
  158. package/dist/modules/transcription/AudioSegmentLayout.d.ts +23 -0
  159. package/dist/modules/transcription/AudioSegmentLayout.d.ts.map +1 -0
  160. package/dist/modules/transcription/AudioSegmentLayout.js +40 -0
  161. package/dist/modules/transcription/AudioSegmentLayout.js.map +1 -0
  162. package/dist/modules/transcription/FallbackAudioDecoder.d.ts +25 -0
  163. package/dist/modules/transcription/FallbackAudioDecoder.d.ts.map +1 -0
  164. package/dist/modules/transcription/FallbackAudioDecoder.js +46 -0
  165. package/dist/modules/transcription/FallbackAudioDecoder.js.map +1 -0
  166. package/dist/modules/transcription/MediaBunnyAudioOnlyRemuxer.d.ts +71 -0
  167. package/dist/modules/transcription/MediaBunnyAudioOnlyRemuxer.d.ts.map +1 -0
  168. package/dist/modules/transcription/MediaBunnyAudioOnlyRemuxer.js +145 -0
  169. package/dist/modules/transcription/MediaBunnyAudioOnlyRemuxer.js.map +1 -0
  170. package/dist/modules/transcription/WebAudioAudioDecoder.d.ts +46 -0
  171. package/dist/modules/transcription/WebAudioAudioDecoder.d.ts.map +1 -0
  172. package/dist/modules/transcription/WebAudioAudioDecoder.js +123 -0
  173. package/dist/modules/transcription/WebAudioAudioDecoder.js.map +1 -0
  174. package/dist/modules/transcription/index.d.ts +4 -0
  175. package/dist/modules/transcription/index.d.ts.map +1 -1
  176. package/dist/modules/transcription/index.js +3 -0
  177. package/dist/modules/transcription/index.js.map +1 -1
  178. package/dist/modules/video/RenderJob.d.ts +23 -0
  179. package/dist/modules/video/RenderJob.d.ts.map +1 -1
  180. package/dist/modules/video/index.d.ts +5 -3
  181. package/dist/modules/video/index.d.ts.map +1 -1
  182. package/dist/modules/video/index.js +2 -0
  183. package/dist/modules/video/index.js.map +1 -1
  184. package/dist/modules/video/mediabunny/MediaBunnyTranscodeCoordinator.d.ts +33 -1
  185. package/dist/modules/video/mediabunny/MediaBunnyTranscodeCoordinator.d.ts.map +1 -1
  186. package/dist/modules/video/mediabunny/MediaBunnyTranscodeCoordinator.js +97 -20
  187. package/dist/modules/video/mediabunny/MediaBunnyTranscodeCoordinator.js.map +1 -1
  188. package/dist/modules/video/mediabunny/MediaBunnyVideoRenderer.d.ts.map +1 -1
  189. package/dist/modules/video/mediabunny/MediaBunnyVideoRenderer.js +1 -0
  190. package/dist/modules/video/mediabunny/MediaBunnyVideoRenderer.js.map +1 -1
  191. package/dist/modules/video/mediabunny/caption/BatchedSubtitleLayerSource.d.ts +20 -9
  192. package/dist/modules/video/mediabunny/caption/BatchedSubtitleLayerSource.d.ts.map +1 -1
  193. package/dist/modules/video/mediabunny/caption/BatchedSubtitleLayerSource.js +56 -14
  194. package/dist/modules/video/mediabunny/caption/BatchedSubtitleLayerSource.js.map +1 -1
  195. package/dist/modules/video/mediabunny/caption/ComposedSubtitleLayerSource.d.ts +29 -10
  196. package/dist/modules/video/mediabunny/caption/ComposedSubtitleLayerSource.d.ts.map +1 -1
  197. package/dist/modules/video/mediabunny/caption/ComposedSubtitleLayerSource.js +48 -17
  198. package/dist/modules/video/mediabunny/caption/ComposedSubtitleLayerSource.js.map +1 -1
  199. package/dist/modules/video/mediabunny/caption/SubtitleLayerSource.d.ts +28 -11
  200. package/dist/modules/video/mediabunny/caption/SubtitleLayerSource.d.ts.map +1 -1
  201. package/dist/modules/video/mediabunny/caption/VideoBoundSubtitleLayerSource.d.ts +33 -12
  202. package/dist/modules/video/mediabunny/caption/VideoBoundSubtitleLayerSource.d.ts.map +1 -1
  203. package/dist/modules/video/mediabunny/caption/VideoBoundSubtitleLayerSource.js +53 -18
  204. package/dist/modules/video/mediabunny/caption/VideoBoundSubtitleLayerSource.js.map +1 -1
  205. package/dist/modules/video/mediabunny/encoder/MediaBunnyCanvasVideoTrackEncoder.d.ts.map +1 -1
  206. package/dist/modules/video/mediabunny/encoder/MediaBunnyCanvasVideoTrackEncoder.js +7 -3
  207. package/dist/modules/video/mediabunny/encoder/MediaBunnyCanvasVideoTrackEncoder.js.map +1 -1
  208. package/dist/modules/video/mediabunny/frame/BufferedVideoFrameSource.d.ts +45 -0
  209. package/dist/modules/video/mediabunny/frame/BufferedVideoFrameSource.d.ts.map +1 -0
  210. package/dist/modules/video/mediabunny/frame/BufferedVideoFrameSource.js +93 -0
  211. package/dist/modules/video/mediabunny/frame/BufferedVideoFrameSource.js.map +1 -0
  212. package/dist/modules/video/mediabunny/frame/DefaultVideoFrameDecoderFactory.d.ts.map +1 -1
  213. package/dist/modules/video/mediabunny/frame/DefaultVideoFrameDecoderFactory.js +3 -1
  214. package/dist/modules/video/mediabunny/frame/DefaultVideoFrameDecoderFactory.js.map +1 -1
  215. package/dist/modules/video/mediabunny/frame/RetainedVideoFrame.d.ts +26 -0
  216. package/dist/modules/video/mediabunny/frame/RetainedVideoFrame.d.ts.map +1 -0
  217. package/dist/modules/video/mediabunny/frame/RetainedVideoFrame.js +55 -0
  218. package/dist/modules/video/mediabunny/frame/RetainedVideoFrame.js.map +1 -0
  219. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderFactory.d.ts +6 -1
  220. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderFactory.d.ts.map +1 -1
  221. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.d.ts +14 -0
  222. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.d.ts.map +1 -0
  223. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.js +14 -0
  224. package/dist/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.js.map +1 -0
  225. package/dist/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.d.ts +16 -0
  226. package/dist/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.d.ts.map +1 -0
  227. package/dist/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.js +23 -0
  228. package/dist/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.js.map +1 -0
  229. package/dist/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.d.ts +9 -3
  230. package/dist/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.d.ts.map +1 -1
  231. package/dist/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.js +24 -7
  232. package/dist/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.js.map +1 -1
  233. package/dist/modules/video/mediabunny/painter/FramePainter.d.ts +35 -14
  234. package/dist/modules/video/mediabunny/painter/FramePainter.d.ts.map +1 -1
  235. package/package.json +4 -1
  236. package/dist/modules/rendering/subtitle/AbstractAnim.d.ts +0 -13
  237. package/dist/modules/rendering/subtitle/AbstractAnim.d.ts.map +0 -1
  238. package/dist/modules/rendering/subtitle/AbstractAnim.js +0 -2
  239. package/dist/modules/rendering/subtitle/AbstractAnim.js.map +0 -1
  240. package/dist/modules/rendering/subtitle/AnimationProbe.d.ts +0 -39
  241. package/dist/modules/rendering/subtitle/AnimationProbe.d.ts.map +0 -1
  242. package/dist/modules/rendering/subtitle/AnimationProbe.js +0 -203
  243. package/dist/modules/rendering/subtitle/AnimationProbe.js.map +0 -1
  244. package/dist/modules/rendering/subtitle/SpriteSheetSizeProber.d.ts +0 -17
  245. package/dist/modules/rendering/subtitle/SpriteSheetSizeProber.d.ts.map +0 -1
  246. package/dist/modules/rendering/subtitle/SpriteSheetSizeProber.js +0 -58
  247. package/dist/modules/rendering/subtitle/SpriteSheetSizeProber.js.map +0 -1
  248. package/dist/modules/video/mediabunny/frame/CurrentFrameVideoSource.d.ts +0 -27
  249. package/dist/modules/video/mediabunny/frame/CurrentFrameVideoSource.d.ts.map +0 -1
  250. package/dist/modules/video/mediabunny/frame/CurrentFrameVideoSource.js +0 -84
  251. package/dist/modules/video/mediabunny/frame/CurrentFrameVideoSource.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ import { profiler } from '../../../profiling/Profiler';
2
+ /**
3
+ * A decoded frame's pixels copied onto a canvas of the caller's own, so
4
+ * they outlive the decoder's frame.
5
+ *
6
+ * A decoder hands out frames it expects back promptly: holding several
7
+ * at once back-pressures the frame pool into a stall. Copying breaks
8
+ * that tie — the decoder's frame closes immediately and what stays
9
+ * alive is an ordinary canvas, at the cost of one full-frame draw and
10
+ * `width × height × 4` bytes per frame held.
11
+ */
12
+ export class RetainedVideoFrame {
13
+ timestamp;
14
+ duration;
15
+ /**
16
+ * Copies `frame` at the given dimensions. Does not close `frame`;
17
+ * the caller keeps that responsibility and may do so as soon as this
18
+ * returns.
19
+ */
20
+ static copyOf(frame, width, height) {
21
+ const canvas = new OffscreenCanvas(width, height);
22
+ const context = canvas.getContext('2d', { alpha: false });
23
+ if (!context) {
24
+ throw new Error('Unable to acquire a 2D context to retain a video frame.');
25
+ }
26
+ // Smoothing left at the context default, which matters whenever the
27
+ // export was asked for dimensions the source does not have: this is
28
+ // the only resample those pixels get before they reach the encoder.
29
+ profiler.time('RetainedVideoFrame.copy', () => frame.draw(context, 0, 0, width, height));
30
+ return new RetainedVideoFrame(canvas, frame.timestamp, frame.duration);
31
+ }
32
+ canvas;
33
+ constructor(canvas, timestamp, duration) {
34
+ this.timestamp = timestamp;
35
+ this.duration = duration;
36
+ this.canvas = canvas;
37
+ }
38
+ draw(context, dx, dy, dWidth, dHeight) {
39
+ if (!this.canvas) {
40
+ throw new Error('RetainedVideoFrame.draw called after close.');
41
+ }
42
+ context.drawImage(this.canvas, dx, dy, dWidth, dHeight);
43
+ }
44
+ close() {
45
+ // Dropping the reference is what frees the pixels; an OffscreenCanvas
46
+ // has no explicit release. Sizing it to nothing first hands the
47
+ // buffer back without waiting for a collection.
48
+ if (this.canvas) {
49
+ this.canvas.width = 0;
50
+ this.canvas.height = 0;
51
+ }
52
+ this.canvas = null;
53
+ }
54
+ }
55
+ //# sourceMappingURL=RetainedVideoFrame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetainedVideoFrame.js","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/RetainedVideoFrame.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD;;;;;;;;;GASG;AACH,MAAM,OAAO,kBAAkB;IAwBlB;IACA;IAvBX;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,KAAwB,EAAE,KAAa,EAAE,MAAc;QACnE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QACD,oEAAoE;QACpE,oEAAoE;QACpE,oEAAoE;QACpE,QAAQ,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QACzF,OAAO,IAAI,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzE,CAAC;IAEO,MAAM,CAAyB;IAEvC,YACE,MAAuB,EACd,SAAiB,EACjB,QAAgB;QADhB,cAAS,GAAT,SAAS,CAAQ;QACjB,aAAQ,GAAR,QAAQ,CAAQ;QAEzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,IAAI,CACF,OAAqE,EACrE,EAAU,EACV,EAAU,EACV,MAAc,EACd,OAAe;QAEf,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK;QACH,sEAAsE;QACtE,gEAAgE;QAChE,gDAAgD;QAChD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;CACF"}
@@ -1,6 +1,6 @@
1
1
  import type { InputVideoTrack } from 'mediabunny';
2
2
  import type { VideoFrameDecoder } from '../../../video/mediabunny/frame/VideoFrameDecoder';
3
- import type { FallbackDecoderInfo } from '../../../video/RenderJob';
3
+ import type { FallbackDecoderInfo, VideoFrameDecoderSelection } from '../../../video/RenderJob';
4
4
  export interface VideoFrameDecoderRequest {
5
5
  /** The primary video track from the input file. */
6
6
  track: InputVideoTrack;
@@ -12,6 +12,11 @@ export interface VideoFrameDecoderRequest {
12
12
  * the factory uses the fallback without asking.
13
13
  */
14
14
  confirmFallback?: (info: FallbackDecoderInfo) => Promise<boolean>;
15
+ /**
16
+ * Called with the decoder the factory settled on, before it is
17
+ * returned. Not invoked when the factory aborts instead.
18
+ */
19
+ onDecoderSelected?: (selection: VideoFrameDecoderSelection) => void;
15
20
  }
16
21
  /**
17
22
  * Picks an appropriate {@link VideoFrameDecoder} for the given input track.
@@ -1 +1 @@
1
- {"version":3,"file":"VideoFrameDecoderFactory.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/VideoFrameDecoderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,MAAM,WAAW,wBAAwB;IACvC,mDAAmD;IACnD,KAAK,EAAE,eAAe,CAAC;IACvB,0EAA0E;IAC1E,MAAM,EAAE,IAAI,CAAC;IACb;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvE"}
1
+ {"version":3,"file":"VideoFrameDecoderFactory.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/VideoFrameDecoderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEhG,MAAM,WAAW,wBAAwB;IACvC,mDAAmD;IACnD,KAAK,EAAE,eAAe,CAAC;IACvB,0EAA0E;IAC1E,MAAM,EAAE,IAAI,CAAC;IACb;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,0BAA0B,KAAK,IAAI,CAAC;CACrE;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvE"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Raised when no decoder the factory is allowed to use can handle the
3
+ * input's video track. Fired before any frame is decoded.
4
+ *
5
+ * The `.name` string is set explicitly, and exposed as `ERROR_NAME` on
6
+ * the class, so consumers can recognise the failure across a boundary
7
+ * that preserves string fields but not class identity — a Worker, or a
8
+ * browser driven from outside the page.
9
+ */
10
+ export declare class VideoFrameDecoderSelectionFailedError extends Error {
11
+ static readonly ERROR_NAME = "VideoFrameDecoderSelectionFailedError";
12
+ readonly name = "VideoFrameDecoderSelectionFailedError";
13
+ }
14
+ //# sourceMappingURL=VideoFrameDecoderSelectionFailedError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoFrameDecoderSelectionFailedError.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,qCAAsC,SAAQ,KAAK;IAC9D,MAAM,CAAC,QAAQ,CAAC,UAAU,2CAA2C;IACrE,QAAQ,CAAC,IAAI,2CAAoD;CAClE"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Raised when no decoder the factory is allowed to use can handle the
3
+ * input's video track. Fired before any frame is decoded.
4
+ *
5
+ * The `.name` string is set explicitly, and exposed as `ERROR_NAME` on
6
+ * the class, so consumers can recognise the failure across a boundary
7
+ * that preserves string fields but not class identity — a Worker, or a
8
+ * browser driven from outside the page.
9
+ */
10
+ export class VideoFrameDecoderSelectionFailedError extends Error {
11
+ static ERROR_NAME = 'VideoFrameDecoderSelectionFailedError';
12
+ name = VideoFrameDecoderSelectionFailedError.ERROR_NAME;
13
+ }
14
+ //# sourceMappingURL=VideoFrameDecoderSelectionFailedError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VideoFrameDecoderSelectionFailedError.js","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/VideoFrameDecoderSelectionFailedError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,OAAO,qCAAsC,SAAQ,KAAK;IAC9D,MAAM,CAAU,UAAU,GAAG,uCAAuC,CAAC;IAC5D,IAAI,GAAG,qCAAqC,CAAC,UAAU,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { VideoFrameDecoder } from '../../../video/mediabunny/frame/VideoFrameDecoder';
2
+ import type { VideoFrameDecoderFactory, VideoFrameDecoderRequest } from '../../../video/mediabunny/frame/VideoFrameDecoderFactory';
3
+ /**
4
+ * Returns the WebCodecs decoder or nothing at all.
5
+ *
6
+ * The `<video>` element fallback the default factory reaches for is
7
+ * bounded by playback speed, so a host that decodes a source only that
8
+ * way is better served by rewriting the source than by driving it. This
9
+ * factory makes that refusal explicit instead of quietly taking the
10
+ * slow path: it raises {@link VideoFrameDecoderSelectionFailedError},
11
+ * and whoever asked decides what to rewrite.
12
+ */
13
+ export declare class WebCodecsOnlyVideoFrameDecoderFactory implements VideoFrameDecoderFactory {
14
+ create(request: VideoFrameDecoderRequest): Promise<VideoFrameDecoder>;
15
+ }
16
+ //# sourceMappingURL=WebCodecsOnlyVideoFrameDecoderFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebCodecsOnlyVideoFrameDecoderFactory.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,0DAA0D,CAAC;AAIlE;;;;;;;;;GASG;AACH,qBAAa,qCAAsC,YAAW,wBAAwB;IAE9E,MAAM,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAU5E"}
@@ -0,0 +1,23 @@
1
+ import { VideoFrameDecoderSelectionFailedError } from '../../../video/mediabunny/frame/VideoFrameDecoderSelectionFailedError';
2
+ import { WebCodecsVideoFrameDecoder } from '../../../video/mediabunny/frame/WebCodecsVideoFrameDecoder';
3
+ /**
4
+ * Returns the WebCodecs decoder or nothing at all.
5
+ *
6
+ * The `<video>` element fallback the default factory reaches for is
7
+ * bounded by playback speed, so a host that decodes a source only that
8
+ * way is better served by rewriting the source than by driving it. This
9
+ * factory makes that refusal explicit instead of quietly taking the
10
+ * slow path: it raises {@link VideoFrameDecoderSelectionFailedError},
11
+ * and whoever asked decides what to rewrite.
12
+ */
13
+ export class WebCodecsOnlyVideoFrameDecoderFactory {
14
+ async create(request) {
15
+ const inputCodec = (await request.track.getCodec()) ?? 'unknown';
16
+ if (!(await request.track.canDecode())) {
17
+ throw new VideoFrameDecoderSelectionFailedError(`WebCodecs cannot decode the input video codec (${inputCodec}).`);
18
+ }
19
+ request.onDecoderSelected?.({ kind: 'web-codecs', inputCodec });
20
+ return new WebCodecsVideoFrameDecoder(request.track);
21
+ }
22
+ }
23
+ //# sourceMappingURL=WebCodecsOnlyVideoFrameDecoderFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebCodecsOnlyVideoFrameDecoderFactory.js","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/frame/WebCodecsOnlyVideoFrameDecoderFactory.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qCAAqC,EAAE,MAAM,uEAAuE,CAAC;AAC9H,OAAO,EAAE,0BAA0B,EAAE,MAAM,4DAA4D,CAAC;AAExG;;;;;;;;;GASG;AACH,MAAM,OAAO,qCAAqC;IAEhD,KAAK,CAAC,MAAM,CAAC,OAAiC;QAC5C,MAAM,UAAU,GAAG,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,SAAS,CAAC;QACjE,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,qCAAqC,CAC7C,kDAAkD,UAAU,IAAI,CACjE,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,iBAAiB,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,0BAA0B,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -1,12 +1,11 @@
1
1
  import type { Document } from '../../../document/Document';
2
2
  import type { OverlayFrameRenderer } from '../../../rendering/OverlayFrameRenderer';
3
3
  import type { SubtitleStyle } from '../../../rendering/SubtitleFrameRenderer';
4
- import type { DecodedVideoFrame } from '../../../video/mediabunny/frame/VideoFrameDecoder';
5
4
  import type { FrameCompositor } from '../../../video/mediabunny/frame/FrameCompositor';
6
5
  import type { SubtitleLayerSource } from '../../../video/mediabunny/caption/SubtitleLayerSource';
7
6
  import type { TopLayerSource } from '../../../video/mediabunny/painter/TopLayerSource';
8
7
  import type { PaintFrame } from '../../../video/mediabunny/encoder/VideoTrackEncoder';
9
- import type { FramePainter } from '../../../video/mediabunny/painter/FramePainter';
8
+ import type { FramePainter, FramePaintRequest } from '../../../video/mediabunny/painter/FramePainter';
10
9
  /**
11
10
  * Paints each output frame as the source frame composited with a
12
11
  * per-timestamp caption raster and a frame-invariant overlay. The
@@ -29,7 +28,14 @@ export declare class CaptionsOverlayFramePainter implements FramePainter {
29
28
  private overlay;
30
29
  constructor(subtitleLayer: SubtitleLayerSource, overlayRenderer: OverlayFrameRenderer, frameCompositor: FrameCompositor, document: Document, styles: Readonly<Record<string, SubtitleStyle>>, overlayHtml: string | undefined, topLayer: TopLayerSource | null);
31
30
  begin(width: number, height: number, fps: number): Promise<void>;
32
- paint(frame: DecodedVideoFrame, _outputTimestamp: number): Promise<PaintFrame>;
31
+ lookAhead(): number;
32
+ paint(requests: ReadonlyArray<FramePaintRequest>): Promise<PaintFrame[]>;
33
+ /**
34
+ * One per request, or all null when no top layer is configured. Kept
35
+ * frame by frame because the top layer reads the frame it occludes
36
+ * and has no batch of its own to amortize.
37
+ */
38
+ private paintTopLayers;
33
39
  end(): void;
34
40
  }
35
41
  //# sourceMappingURL=CaptionsOverlayFramePainter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CaptionsOverlayFramePainter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAgB,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uDAAuD,CAAC;AACjG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gDAAgD,CAAC;AAUnF;;;;;;;;GAQG;AACH,qBAAa,2BAA4B,YAAW,YAAY;IAO5D,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAA6B;gBAGzB,aAAa,EAAE,mBAAmB,EAClC,eAAe,EAAE,oBAAoB,EACrC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,EAC/C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,cAAc,GAAG,IAAI;IAG5C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAahE,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAepF,GAAG,IAAI,IAAI;CAKZ"}
1
+ {"version":3,"file":"CaptionsOverlayFramePainter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAgB,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AACvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uDAAuD,CAAC;AACjG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAUtG;;;;;;;;GAQG;AACH,qBAAa,2BAA4B,YAAW,YAAY;IAO5D,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAA6B;gBAGzB,aAAa,EAAE,mBAAmB,EAClC,eAAe,EAAE,oBAAoB,EACrC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,EAC/C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,cAAc,GAAG,IAAI;IAG5C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatE,SAAS,IAAI,MAAM;IAIb,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAiB9E;;;;OAIG;YACW,cAAc;IAW5B,GAAG,IAAI,IAAI;CAKZ"}
@@ -46,19 +46,36 @@ export class CaptionsOverlayFramePainter {
46
46
  await this.topLayer.open(width, height);
47
47
  }
48
48
  }
49
- async paint(frame, _outputTimestamp) {
50
- const captions = await this.subtitleLayer.frameAt(frame.timestamp, frame);
51
- const topLayer = this.topLayer === null ? null : await this.topLayer.frameAt(frame.timestamp, frame);
52
- return (ctx) => {
49
+ lookAhead() {
50
+ return this.subtitleLayer.lookAhead();
51
+ }
52
+ async paint(requests) {
53
+ const captions = await this.subtitleLayer.framesFor(requests.map(({ frame }) => ({ time: frame.timestamp, videoFrame: frame })));
54
+ const topLayers = await this.paintTopLayers(requests);
55
+ return requests.map(({ frame }, i) => (ctx) => {
53
56
  this.frameCompositor.compose(ctx, {
54
57
  frame,
55
- captions,
58
+ captions: captions[i] ?? null,
56
59
  overlay: this.overlay,
57
- topLayer,
60
+ topLayer: topLayers[i] ?? null,
58
61
  width: this.width,
59
62
  height: this.height,
60
63
  });
61
- };
64
+ });
65
+ }
66
+ /**
67
+ * One per request, or all null when no top layer is configured. Kept
68
+ * frame by frame because the top layer reads the frame it occludes
69
+ * and has no batch of its own to amortize.
70
+ */
71
+ async paintTopLayers(requests) {
72
+ if (this.topLayer === null)
73
+ return requests.map(() => null);
74
+ const layers = [];
75
+ for (const { frame } of requests) {
76
+ layers.push(await this.topLayer.frameAt(frame.timestamp, frame));
77
+ }
78
+ return layers;
62
79
  }
63
80
  end() {
64
81
  this.subtitleLayer.close();
@@ -1 +1 @@
1
- {"version":3,"file":"CaptionsOverlayFramePainter.js","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;;;;;;GAQG;AACH,MAAM,OAAO,2BAA2B;IAOnB;IACA;IACA;IACA;IACA;IACA;IACA;IAXX,KAAK,GAAG,CAAC,CAAC;IACV,MAAM,GAAG,CAAC,CAAC;IACX,OAAO,GAAwB,IAAI,CAAC;IAE5C,YACmB,aAAkC,EAClC,eAAqC,EACrC,eAAgC,EAChC,QAAkB,EAClB,MAA+C,EAC/C,WAA+B,EAC/B,QAA+B;QAN/B,kBAAa,GAAb,aAAa,CAAqB;QAClC,oBAAe,GAAf,eAAe,CAAsB;QACrC,oBAAe,GAAf,eAAe,CAAiB;QAChC,aAAQ,GAAR,QAAQ,CAAU;QAClB,WAAM,GAAN,MAAM,CAAyC;QAC/C,gBAAW,GAAX,WAAW,CAAoB;QAC/B,aAAQ,GAAR,QAAQ,CAAuB;IAC/C,CAAC;IAEJ,KAAK,CAAC,KAAK,CAAC,KAAa,EAAE,MAAc,EAAE,GAAW;QACpD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;QAC1F,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAwB,EAAE,gBAAwB;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrG,OAAO,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE;gBAChC,KAAK;gBACL,QAAQ;gBACR,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,QAAQ;gBACR,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC,CAAC;IACJ,CAAC;IAED,GAAG;QACD,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;CACF"}
1
+ {"version":3,"file":"CaptionsOverlayFramePainter.js","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/CaptionsOverlayFramePainter.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  import type { DecodedVideoFrame } from '../../../video/mediabunny/frame/VideoFrameDecoder';
2
2
  import type { PaintFrame } from '../../../video/mediabunny/encoder/VideoTrackEncoder';
3
+ /** One output frame to paint: the decoded source frame and where it lands on the output timeline. */
4
+ export interface FramePaintRequest {
5
+ readonly frame: DecodedVideoFrame;
6
+ readonly outputTimestamp: number;
7
+ }
3
8
  /**
4
9
  * Owns the pixel work for a single transcode run: what to draw into
5
10
  * every output frame's canvas. The transcode coordinator owns the
@@ -8,16 +13,16 @@ import type { PaintFrame } from '../../../video/mediabunny/encoder/VideoTrackEnc
8
13
  *
9
14
  * Lifecycle is per-run: {@link begin} once at the start with the
10
15
  * resolved output dimensions and source frame rate, {@link paint} for
11
- * each decoded frame in monotonically advancing source-time order, and
12
- * {@link end} once at the end (called on both success and failure).
13
- * Instances are single-use unless the concrete class documents
14
- * otherwise.
16
+ * each run of decoded frames in monotonically advancing source-time
17
+ * order, and {@link end} once at the end (called on both success and
18
+ * failure). Instances are single-use unless the concrete class
19
+ * documents otherwise.
15
20
  *
16
21
  * The two-step {@link paint} contract exists because
17
22
  * {@link VideoTrackEncoder.encode} takes a synchronous paint callback:
18
- * any per-frame work that has to be awaited (e.g. rasterizing a
19
- * caption layer) happens inside {@link paint}, and the returned
20
- * closure runs synchronously against the encoder's canvas.
23
+ * any work that has to be awaited (e.g. rasterizing a caption layer)
24
+ * happens inside {@link paint}, and the returned closures run
25
+ * synchronously against the encoder's canvas.
21
26
  */
22
27
  export interface FramePainter {
23
28
  /**
@@ -28,14 +33,30 @@ export interface FramePainter {
28
33
  */
29
34
  begin(width: number, height: number, fps: number): Promise<void>;
30
35
  /**
31
- * Resolves any per-frame state asynchronously and returns the
32
- * synchronous paint step the encoder will run. `outputTimestamp` is
33
- * the frame's presentation time on the output timeline (already
34
- * mapped through any skip ranges by the caller); `frame.timestamp`
35
- * carries the source-timeline time and stays authoritative for any
36
- * lookup against source-aligned data (captions, per-source overlays).
36
+ * How many consecutive frames the painter wants handed to one
37
+ * {@link paint} call to work at its best. `1` means it is happy frame
38
+ * by frame; a larger number means it amortizes work across the run,
39
+ * and the caller should gather that many before painting — which
40
+ * costs it holding them all until the run is painted and encoded.
41
+ *
42
+ * A preference, not a requirement: {@link paint} accepts any length,
43
+ * and the last run of a render is short by nature. Meaningful only
44
+ * after {@link begin}.
45
+ */
46
+ lookAhead(): number;
47
+ /**
48
+ * Resolves any state the run needs asynchronously and returns one
49
+ * synchronous paint step per request, in the order given.
50
+ *
51
+ * Each request's `outputTimestamp` is that frame's presentation time
52
+ * on the output timeline (already mapped through any skip ranges by
53
+ * the caller); its `frame.timestamp` carries the source-timeline time
54
+ * and stays authoritative for any lookup against source-aligned data
55
+ * (captions, per-source overlays).
56
+ *
57
+ * The frames must stay open until every returned step has run.
37
58
  */
38
- paint(frame: DecodedVideoFrame, outputTimestamp: number): Promise<PaintFrame>;
59
+ paint(requests: ReadonlyArray<FramePaintRequest>): Promise<PaintFrame[]>;
39
60
  /**
40
61
  * Releases the per-run resources opened by {@link begin}. Called on
41
62
  * both success and failure paths of the enclosing run. Idempotent:
@@ -1 +1 @@
1
- {"version":3,"file":"FramePainter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/FramePainter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qDAAqD,CAAC;AAEtF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE9E;;;;OAIG;IACH,GAAG,IAAI,IAAI,CAAC;CACb"}
1
+ {"version":3,"file":"FramePainter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/video/mediabunny/painter/FramePainter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qDAAqD,CAAC;AAEtF,qGAAqG;AACrG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;;;;;;;;OAUG;IACH,SAAS,IAAI,MAAM,CAAC;IAEpB;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEzE;;;;OAIG;IACH,GAAG,IAAI,IAAI,CAAC;CACb"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscaps/engine",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Burn subtitles into video in the browser. CSS-styled captions, frame-accurate export, no server.",
5
5
  "keywords": [
6
6
  "subtitles",
@@ -56,6 +56,9 @@
56
56
  "bidi-js": "^1.0.3",
57
57
  "mediabunny": "^1.51.0"
58
58
  },
59
+ "peerDependencies": {
60
+ "onnxruntime-web": "^1.27.0"
61
+ },
59
62
  "devDependencies": {
60
63
  "@eslint/js": "10.0.1",
61
64
  "@playwright/test": "^1.49.0",
@@ -1,13 +0,0 @@
1
- import type { CssVariable } from '../../document/CssVariable';
2
- /**
3
- * One animation timing extracted from a probed element's computed
4
- * style: the CSS variable whose start moment anchors the active
5
- * window, and the duration the rule runs for once that moment passes.
6
- * `durationS` is `Infinity` for an `animation-iteration-count:
7
- * infinite` rule.
8
- */
9
- export interface AbstractAnim {
10
- cssVar: CssVariable;
11
- durationS: number;
12
- }
13
- //# sourceMappingURL=AbstractAnim.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AbstractAnim.d.ts","sourceRoot":"","sources":["../../../../src/modules/rendering/subtitle/AbstractAnim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=AbstractAnim.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AbstractAnim.js","sourceRoot":"","sources":["../../../../src/modules/rendering/subtitle/AbstractAnim.ts"],"names":[],"mappings":""}
@@ -1,39 +0,0 @@
1
- import type { Segment } from '../../document/Segment';
2
- import type { PreparedStyle } from '../../rendering/subtitle/PreparedStyle';
3
- /**
4
- * Decides whether a render item should redraw every frame: builds
5
- * throw-away DOM chains matching what the renderer emits, reads back
6
- * resolved `animation-duration` / `animation-delay` from
7
- * `getComputedStyle`, and decodes each timing back to the CSS
8
- * variable that anchored its window. Caches per chain so the same one
9
- * is probed at most once. `clear` empties the cache.
10
- *
11
- * A chain carries the element ids the renderer stamps as well as the
12
- * classes, because a stylesheet can address one element rather than a
13
- * class of them. Built from classes alone, the chain resolves a
14
- * different animation than the node it stands for — none at all where
15
- * only the element carries one, and the wrong window where the
16
- * element's beats the template's. Either way the tile is reused across
17
- * a frame that moved, and the animation exports as a still image.
18
- *
19
- * Only ids the stylesheet actually addresses go on, so a caption
20
- * nobody has styled probes one chain per class combination as before.
21
- */
22
- export declare class AnimationProbe {
23
- private readonly timingByKey;
24
- isItemAnimating(style: PreparedStyle, seg: Segment, t: number): boolean;
25
- clear(): void;
26
- /** The element as the probe will build it, addressed only where the stylesheet says so. */
27
- private probed;
28
- private animates;
29
- private timingOf;
30
- private describe;
31
- /** Mounts the chain, reads what the leaf resolved to, and takes it back out. */
32
- private probeChain;
33
- private createNode;
34
- private injectProbeMagic;
35
- private readAnimTimings;
36
- private parseDurationsS;
37
- private evalAnims;
38
- }
39
- //# sourceMappingURL=AnimationProbe.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AnimationProbe.d.ts","sourceRoot":"","sources":["../../../../src/modules/rendering/subtitle/AnimationProbe.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AA2B/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IAEjE,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;IAwCvE,KAAK,IAAI,IAAI;IAIb,2FAA2F;IAC3F,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,QAAQ;IAIhB,gFAAgF;IAChF,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,SAAS;CA6BlB"}