@remotion/web-renderer 4.0.399 → 4.0.401

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 (110) hide show
  1. package/dist/compose.d.ts +19 -4
  2. package/dist/create-scaffold.d.ts +4 -5
  3. package/dist/drawing/border-radius.d.ts +2 -2
  4. package/dist/drawing/calculate-transforms.d.ts +1 -1
  5. package/dist/drawing/draw-background.d.ts +22 -5
  6. package/dist/drawing/draw-box-shadow.d.ts +1 -2
  7. package/dist/drawing/draw-element.d.ts +19 -4
  8. package/dist/drawing/drawn-fn.d.ts +1 -1
  9. package/dist/drawing/get-clipped-background.d.ts +19 -4
  10. package/dist/drawing/handle-3d-transform.d.ts +18 -2
  11. package/dist/drawing/precompose.d.ts +19 -4
  12. package/dist/drawing/process-node.d.ts +19 -4
  13. package/dist/drawing/text/draw-text.d.ts +1 -2
  14. package/dist/drawing/text/handle-text-node.d.ts +19 -4
  15. package/dist/drawing/transform-in-3d.d.ts +19 -2
  16. package/dist/drawing/transform-rect-with-matrix.d.ts +1 -1
  17. package/dist/esm/index.mjs +551 -397
  18. package/dist/get-audio-sample-source.d.ts +8 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/internal-state.d.ts +9 -1
  21. package/dist/mediabunny-cleanups.d.ts +10 -0
  22. package/dist/mediabunny-mappings.d.ts +2 -2
  23. package/dist/props-if-has-props.d.ts +1 -2
  24. package/dist/render-still-on-web.d.ts +18 -2
  25. package/dist/symbol-dispose.d.ts +0 -0
  26. package/dist/take-screenshot.d.ts +38 -6
  27. package/dist/wait-for-ready.d.ts +21 -3
  28. package/package.json +9 -8
  29. package/dist/add-sample.js +0 -20
  30. package/dist/artifact.js +0 -56
  31. package/dist/audio.js +0 -42
  32. package/dist/calculate-transforms.d.ts +0 -9
  33. package/dist/calculate-transforms.js +0 -74
  34. package/dist/can-use-webfs-target.js +0 -19
  35. package/dist/composable.d.ts +0 -10
  36. package/dist/composable.js +0 -1
  37. package/dist/compose-canvas.d.ts +0 -1
  38. package/dist/compose-canvas.js +0 -12
  39. package/dist/compose-svg.d.ts +0 -1
  40. package/dist/compose-svg.js +0 -34
  41. package/dist/compose.js +0 -85
  42. package/dist/create-scaffold.js +0 -104
  43. package/dist/drawing/border-radius.js +0 -151
  44. package/dist/drawing/calculate-object-fit.js +0 -208
  45. package/dist/drawing/calculate-transforms.js +0 -127
  46. package/dist/drawing/clamp-rect-to-parent-bounds.js +0 -18
  47. package/dist/drawing/do-rects-intersect.js +0 -6
  48. package/dist/drawing/draw-background.js +0 -62
  49. package/dist/drawing/draw-border.js +0 -353
  50. package/dist/drawing/draw-box-shadow.js +0 -103
  51. package/dist/drawing/draw-dom-element.js +0 -85
  52. package/dist/drawing/draw-element-to-canvas.d.ts +0 -11
  53. package/dist/drawing/draw-element-to-canvas.js +0 -64
  54. package/dist/drawing/draw-element.js +0 -82
  55. package/dist/drawing/draw-outline.js +0 -93
  56. package/dist/drawing/draw-rounded.js +0 -34
  57. package/dist/drawing/drawn-fn.js +0 -1
  58. package/dist/drawing/fit-svg-into-its-dimensions.js +0 -35
  59. package/dist/drawing/get-clipped-background.js +0 -14
  60. package/dist/drawing/get-padding-box.js +0 -30
  61. package/dist/drawing/get-pretransform-rect.js +0 -49
  62. package/dist/drawing/go-rects-intersect.d.ts +0 -1
  63. package/dist/drawing/go-rects-intersect.js +0 -6
  64. package/dist/drawing/handle-3d-transform.js +0 -26
  65. package/dist/drawing/handle-mask.js +0 -21
  66. package/dist/drawing/has-transform.js +0 -14
  67. package/dist/drawing/mask-image.js +0 -14
  68. package/dist/drawing/opacity.js +0 -7
  69. package/dist/drawing/overflow.js +0 -14
  70. package/dist/drawing/parse-linear-gradient.js +0 -260
  71. package/dist/drawing/parse-transform-origin.js +0 -7
  72. package/dist/drawing/precompose.js +0 -14
  73. package/dist/drawing/process-node.js +0 -115
  74. package/dist/drawing/round-to-expand-rect.js +0 -7
  75. package/dist/drawing/text/apply-text-transform.js +0 -12
  76. package/dist/drawing/text/draw-text.js +0 -53
  77. package/dist/drawing/text/find-line-breaks.text.js +0 -67
  78. package/dist/drawing/text/get-base-height.d.ts +0 -1
  79. package/dist/drawing/text/get-base-height.js +0 -13
  80. package/dist/drawing/text/get-collapsed-text.js +0 -46
  81. package/dist/drawing/text/handle-text-node.js +0 -24
  82. package/dist/drawing/transform-in-3d.js +0 -177
  83. package/dist/drawing/transform-rect-with-matrix.js +0 -19
  84. package/dist/drawing/transform.js +0 -10
  85. package/dist/drawing/turn-svg-into-drawable.js +0 -41
  86. package/dist/find-capturable-elements.d.ts +0 -2
  87. package/dist/find-capturable-elements.js +0 -28
  88. package/dist/frame-range.js +0 -15
  89. package/dist/get-audio-encoding-config.js +0 -18
  90. package/dist/get-biggest-bounding-client-rect.js +0 -43
  91. package/dist/index.js +0 -2
  92. package/dist/internal-state.js +0 -21
  93. package/dist/mediabunny-mappings.js +0 -63
  94. package/dist/output-target.js +0 -1
  95. package/dist/parse-transform-origin.d.ts +0 -4
  96. package/dist/parse-transform-origin.js +0 -7
  97. package/dist/props-if-has-props.js +0 -1
  98. package/dist/render-media-on-web.js +0 -297
  99. package/dist/render-operations-queue.js +0 -3
  100. package/dist/render-still-on-web.js +0 -109
  101. package/dist/send-telemetry-event.js +0 -22
  102. package/dist/take-screenshot.js +0 -30
  103. package/dist/throttle-progress.js +0 -43
  104. package/dist/tree-walker-cleanup-after-children.js +0 -33
  105. package/dist/update-time.js +0 -17
  106. package/dist/validate-video-frame.js +0 -34
  107. package/dist/wait-for-ready.js +0 -35
  108. package/dist/walk-tree.js +0 -14
  109. package/dist/web-fs-target.js +0 -41
  110. package/dist/with-resolvers.js +0 -9
@@ -1,11 +1,43 @@
1
+ var __dispose = Symbol.dispose || /* @__PURE__ */ Symbol.for("Symbol.dispose");
2
+ var __asyncDispose = Symbol.asyncDispose || /* @__PURE__ */ Symbol.for("Symbol.asyncDispose");
3
+ var __using = (stack, value, async) => {
4
+ if (value != null) {
5
+ if (typeof value !== "object" && typeof value !== "function")
6
+ throw TypeError('Object expected to be assigned to "using" declaration');
7
+ var dispose;
8
+ if (async)
9
+ dispose = value[__asyncDispose];
10
+ if (dispose === undefined)
11
+ dispose = value[__dispose];
12
+ if (typeof dispose !== "function")
13
+ throw TypeError("Object not disposable");
14
+ stack.push([async, dispose, value]);
15
+ } else if (async) {
16
+ stack.push([async]);
17
+ }
18
+ return value;
19
+ };
20
+ var __callDispose = (stack, error, hasError) => {
21
+ var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
22
+ return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
23
+ }, fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e), next = (it) => {
24
+ while (it = stack.pop()) {
25
+ try {
26
+ var result = it[1] && it[1].call(it[2]);
27
+ if (it[0])
28
+ return Promise.resolve(result).then(next, (e) => (fail(e), next()));
29
+ } catch (e) {
30
+ fail(e);
31
+ }
32
+ }
33
+ if (hasError)
34
+ throw error;
35
+ };
36
+ return next();
37
+ };
38
+
1
39
  // src/render-media-on-web.tsx
2
- import {
3
- AudioSampleSource,
4
- BufferTarget,
5
- Output,
6
- StreamTarget,
7
- VideoSampleSource
8
- } from "mediabunny";
40
+ import { BufferTarget, StreamTarget } from "mediabunny";
9
41
  import { Internals as Internals7 } from "remotion";
10
42
 
11
43
  // src/add-sample.ts
@@ -339,7 +371,7 @@ async function createScaffold({
339
371
  return {
340
372
  delayRenderScope,
341
373
  div,
342
- cleanupScaffold: () => {
374
+ [Symbol.dispose]: () => {
343
375
  root.unmount();
344
376
  div.remove();
345
377
  cleanupCSS();
@@ -366,6 +398,11 @@ var getRealFrameRange = (durationInFrames, frameRange) => {
366
398
  return frameRange;
367
399
  };
368
400
 
401
+ // src/get-audio-sample-source.ts
402
+ import {
403
+ AudioSampleSource
404
+ } from "mediabunny";
405
+
369
406
  // src/get-audio-encoding-config.ts
370
407
  import {
371
408
  canEncodeAudio,
@@ -389,10 +426,31 @@ var getDefaultAudioEncodingConfig = async () => {
389
426
  return null;
390
427
  };
391
428
 
429
+ // src/get-audio-sample-source.ts
430
+ var addAudioSampleSource = async ({
431
+ muted,
432
+ output
433
+ }) => {
434
+ if (muted) {
435
+ return null;
436
+ }
437
+ const defaultAudioEncodingConfig = await getDefaultAudioEncodingConfig();
438
+ if (!defaultAudioEncodingConfig) {
439
+ throw new Error("No default audio encoding config found");
440
+ }
441
+ const audioSampleSource = new AudioSampleSource(defaultAudioEncodingConfig);
442
+ output.addAudioTrack(audioSampleSource);
443
+ return { audioSampleSource, [Symbol.dispose]: () => audioSampleSource.close() };
444
+ };
445
+
392
446
  // src/internal-state.ts
393
447
  var makeInternalState = () => {
394
448
  let drawnPrecomposedPixels = 0;
395
449
  let precomposedTextures = 0;
450
+ let waitForReadyTime = 0;
451
+ let addSampleTime = 0;
452
+ let createFrameTime = 0;
453
+ let audioMixingTime = 0;
396
454
  const helperCanvasState = {
397
455
  current: null
398
456
  };
@@ -407,10 +465,50 @@ var makeInternalState = () => {
407
465
  precomposedTextures++;
408
466
  },
409
467
  helperCanvasState,
410
- cleanup: () => {
468
+ [Symbol.dispose]: () => {
411
469
  if (helperCanvasState.current) {
412
470
  helperCanvasState.current.cleanup();
413
471
  }
472
+ },
473
+ getWaitForReadyTime: () => waitForReadyTime,
474
+ addWaitForReadyTime: (time) => {
475
+ waitForReadyTime += time;
476
+ },
477
+ getAddSampleTime: () => addSampleTime,
478
+ addAddSampleTime: (time) => {
479
+ addSampleTime += time;
480
+ },
481
+ getCreateFrameTime: () => createFrameTime,
482
+ addCreateFrameTime: (time) => {
483
+ createFrameTime += time;
484
+ },
485
+ getAudioMixingTime: () => audioMixingTime,
486
+ addAudioMixingTime: (time) => {
487
+ audioMixingTime += time;
488
+ }
489
+ };
490
+ };
491
+
492
+ // src/mediabunny-cleanups.ts
493
+ import { Output, VideoSampleSource } from "mediabunny";
494
+ var makeOutputWithCleanup = (options) => {
495
+ const output = new Output(options);
496
+ return {
497
+ output,
498
+ [Symbol.dispose]: () => {
499
+ if (output.state === "finalized" || output.state === "canceled") {
500
+ return;
501
+ }
502
+ output.cancel();
503
+ }
504
+ };
505
+ };
506
+ var makeVideoSampleSourceCleanup = (encodingConfig) => {
507
+ const videoSampleSource = new VideoSampleSource(encodingConfig);
508
+ return {
509
+ videoSampleSource,
510
+ [Symbol.dispose]: () => {
511
+ videoSampleSource.close();
414
512
  }
415
513
  };
416
514
  };
@@ -1264,12 +1362,12 @@ var calculateTransforms = ({
1264
1362
  if (!elementComputedStyle) {
1265
1363
  throw new Error("Element computed style not found");
1266
1364
  }
1267
- const needs3DTransformViaWebGL = !totalMatrix.is2D;
1365
+ const needs3DTransformViaWebGL = !totalMatrix.isIdentity;
1268
1366
  const needsMaskImage = maskImageInfo !== null;
1269
1367
  return {
1270
1368
  dimensions,
1271
1369
  totalMatrix,
1272
- reset: () => {
1370
+ [Symbol.dispose]: () => {
1273
1371
  for (const reset of toReset) {
1274
1372
  reset();
1275
1373
  }
@@ -1561,7 +1659,9 @@ var drawBackground = async ({
1561
1659
  element,
1562
1660
  logLevel,
1563
1661
  internalState,
1564
- computedStyle
1662
+ computedStyle,
1663
+ offsetLeft: parentOffsetLeft,
1664
+ offsetTop: parentOffsetTop
1565
1665
  }) => {
1566
1666
  let contextToDraw = context;
1567
1667
  const originalCompositeOperation = context.globalCompositeOperation;
@@ -1583,7 +1683,7 @@ var drawBackground = async ({
1583
1683
  element.style.webkitBackgroundClip = "initial";
1584
1684
  const drawn = await getClippedBackground({
1585
1685
  element,
1586
- boundingRect,
1686
+ boundingRect: new DOMRect(boundingRect.left + parentOffsetLeft, boundingRect.top + parentOffsetTop, boundingRect.width, boundingRect.height),
1587
1687
  logLevel,
1588
1688
  internalState
1589
1689
  });
@@ -1612,7 +1712,7 @@ var drawBackground = async ({
1612
1712
  if (backgroundColor && backgroundColor !== "transparent" && !(backgroundColor.startsWith("rgba") && (backgroundColor.endsWith(", 0)") || backgroundColor.endsWith(",0")))) {
1613
1713
  const originalFillStyle = contextToDraw.fillStyle;
1614
1714
  contextToDraw.fillStyle = backgroundColor;
1615
- contextToDraw.fillRect(boundingRect.left - offsetLeft, boundingRect.top - offsetLeft, boundingRect.width, boundingRect.height);
1715
+ contextToDraw.fillRect(boundingRect.left - offsetLeft, boundingRect.top - offsetTop, boundingRect.width, boundingRect.height);
1616
1716
  contextToDraw.fillStyle = originalFillStyle;
1617
1717
  }
1618
1718
  finish();
@@ -2228,7 +2328,9 @@ var drawElement = async ({
2228
2328
  element,
2229
2329
  logLevel,
2230
2330
  internalState,
2231
- computedStyle
2331
+ computedStyle,
2332
+ offsetLeft: parentRect.left,
2333
+ offsetTop: parentRect.top
2232
2334
  });
2233
2335
  await draw({ dimensions: rect, computedStyle, contextToDraw: context });
2234
2336
  finishBorderRadius();
@@ -2650,116 +2752,113 @@ var processNode = async ({
2650
2752
  internalState,
2651
2753
  rootElement
2652
2754
  }) => {
2653
- const {
2654
- totalMatrix,
2655
- reset,
2656
- dimensions,
2657
- opacity,
2658
- computedStyle,
2659
- precompositing
2660
- } = calculateTransforms({
2661
- element,
2662
- rootElement
2663
- });
2664
- if (opacity === 0) {
2665
- reset();
2666
- return { type: "skip-children" };
2667
- }
2668
- if (dimensions.width <= 0 || dimensions.height <= 0) {
2669
- reset();
2670
- return { type: "continue", cleanupAfterChildren: null };
2671
- }
2672
- const rect = new DOMRect(dimensions.left - parentRect.x, dimensions.top - parentRect.y, dimensions.width, dimensions.height);
2673
- if (precompositing.needsPrecompositing) {
2674
- const start = Date.now();
2675
- let precomposeRect = null;
2676
- if (precompositing.needsMaskImage) {
2677
- precomposeRect = getWiderRectAndExpand({
2678
- firstRect: precomposeRect,
2679
- secondRect: getPrecomposeRectForMask(element)
2680
- });
2681
- }
2682
- if (precompositing.needs3DTransformViaWebGL) {
2683
- precomposeRect = getWiderRectAndExpand({
2684
- firstRect: precomposeRect,
2685
- secondRect: getPrecomposeRectFor3DTransform({
2686
- element,
2687
- parentRect,
2688
- matrix: totalMatrix
2689
- })
2690
- });
2691
- }
2692
- if (!precomposeRect) {
2693
- throw new Error("Precompose rect not found");
2755
+ let __stack = [];
2756
+ try {
2757
+ const transforms = __using(__stack, calculateTransforms({
2758
+ element,
2759
+ rootElement
2760
+ }), 0);
2761
+ const { opacity, computedStyle, totalMatrix, dimensions, precompositing } = transforms;
2762
+ if (opacity === 0) {
2763
+ return { type: "skip-children" };
2694
2764
  }
2695
- if (precomposeRect.width <= 0 || precomposeRect.height <= 0) {
2696
- return { type: "continue", cleanupAfterChildren: null };
2765
+ if (computedStyle.backfaceVisibility === "hidden" && totalMatrix.m33 < 0) {
2766
+ return { type: "skip-children" };
2697
2767
  }
2698
- if (!doRectsIntersect(precomposeRect, parentRect)) {
2768
+ if (dimensions.width <= 0 || dimensions.height <= 0) {
2699
2769
  return { type: "continue", cleanupAfterChildren: null };
2700
2770
  }
2701
- const { tempCanvas, tempContext } = await precomposeDOMElement({
2702
- boundingRect: precomposeRect,
2703
- element,
2704
- logLevel,
2705
- internalState
2706
- });
2707
- let drawable = tempCanvas;
2708
- const rectAfterTransforms = roundToExpandRect(transformDOMRect({
2709
- rect: precomposeRect,
2710
- matrix: totalMatrix
2711
- }));
2712
- if (precompositing.needsMaskImage) {
2713
- handleMask({
2714
- gradientInfo: precompositing.needsMaskImage,
2715
- rect,
2716
- precomposeRect,
2717
- tempContext
2718
- });
2719
- }
2720
- if (precompositing.needs3DTransformViaWebGL) {
2721
- const t = handle3dTransform({
2722
- matrix: totalMatrix,
2723
- precomposeRect,
2724
- tempCanvas: drawable,
2725
- rectAfterTransforms,
2726
- internalState
2727
- });
2728
- if (t) {
2729
- drawable = t;
2771
+ const rect = new DOMRect(dimensions.left - parentRect.x, dimensions.top - parentRect.y, dimensions.width, dimensions.height);
2772
+ if (precompositing.needsPrecompositing) {
2773
+ const start = Date.now();
2774
+ let precomposeRect = null;
2775
+ if (precompositing.needsMaskImage) {
2776
+ precomposeRect = getWiderRectAndExpand({
2777
+ firstRect: precomposeRect,
2778
+ secondRect: getPrecomposeRectForMask(element)
2779
+ });
2730
2780
  }
2731
- }
2732
- const previousTransform = context.getTransform();
2733
- if (drawable) {
2734
- context.setTransform(new DOMMatrix);
2735
- context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
2736
- context.setTransform(previousTransform);
2737
- Internals5.Log.trace({
2781
+ if (precompositing.needs3DTransformViaWebGL) {
2782
+ precomposeRect = getWiderRectAndExpand({
2783
+ firstRect: precomposeRect,
2784
+ secondRect: getPrecomposeRectFor3DTransform({
2785
+ element,
2786
+ parentRect,
2787
+ matrix: totalMatrix
2788
+ })
2789
+ });
2790
+ }
2791
+ if (!precomposeRect) {
2792
+ throw new Error("Precompose rect not found");
2793
+ }
2794
+ if (precomposeRect.width <= 0 || precomposeRect.height <= 0) {
2795
+ return { type: "continue", cleanupAfterChildren: null };
2796
+ }
2797
+ if (!doRectsIntersect(precomposeRect, parentRect)) {
2798
+ return { type: "continue", cleanupAfterChildren: null };
2799
+ }
2800
+ const { tempCanvas, tempContext } = await precomposeDOMElement({
2801
+ boundingRect: precomposeRect,
2802
+ element,
2738
2803
  logLevel,
2739
- tag: "@remotion/web-renderer"
2740
- }, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms`);
2741
- internalState.addPrecompose({
2742
- canvasWidth: precomposeRect.width,
2743
- canvasHeight: precomposeRect.height
2804
+ internalState
2744
2805
  });
2806
+ let drawable = tempCanvas;
2807
+ const rectAfterTransforms = roundToExpandRect(transformDOMRect({
2808
+ rect: precomposeRect,
2809
+ matrix: totalMatrix
2810
+ }));
2811
+ if (precompositing.needsMaskImage) {
2812
+ handleMask({
2813
+ gradientInfo: precompositing.needsMaskImage,
2814
+ rect,
2815
+ precomposeRect,
2816
+ tempContext
2817
+ });
2818
+ }
2819
+ if (precompositing.needs3DTransformViaWebGL) {
2820
+ drawable = handle3dTransform({
2821
+ matrix: totalMatrix,
2822
+ precomposeRect,
2823
+ tempCanvas: drawable,
2824
+ rectAfterTransforms,
2825
+ internalState
2826
+ });
2827
+ }
2828
+ const previousTransform = context.getTransform();
2829
+ if (drawable) {
2830
+ context.setTransform(new DOMMatrix);
2831
+ context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
2832
+ context.setTransform(previousTransform);
2833
+ Internals5.Log.trace({
2834
+ logLevel,
2835
+ tag: "@remotion/web-renderer"
2836
+ }, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms - helper canvas: ${drawable.width}x${drawable.height}`);
2837
+ internalState.addPrecompose({
2838
+ canvasWidth: precomposeRect.width,
2839
+ canvasHeight: precomposeRect.height
2840
+ });
2841
+ }
2842
+ return { type: "skip-children" };
2745
2843
  }
2746
- reset();
2747
- return { type: "skip-children" };
2844
+ const { cleanupAfterChildren } = await drawElement({
2845
+ rect,
2846
+ computedStyle,
2847
+ context,
2848
+ draw,
2849
+ opacity,
2850
+ totalMatrix,
2851
+ parentRect,
2852
+ logLevel,
2853
+ element,
2854
+ internalState
2855
+ });
2856
+ return { type: "continue", cleanupAfterChildren };
2857
+ } catch (_catch) {
2858
+ var _err = _catch, _hasErr = 1;
2859
+ } finally {
2860
+ __callDispose(__stack, _err, _hasErr);
2748
2861
  }
2749
- const { cleanupAfterChildren } = await drawElement({
2750
- rect,
2751
- computedStyle,
2752
- context,
2753
- draw,
2754
- opacity,
2755
- totalMatrix,
2756
- parentRect,
2757
- logLevel,
2758
- element,
2759
- internalState
2760
- });
2761
- reset();
2762
- return { type: "continue", cleanupAfterChildren };
2763
2862
  };
2764
2863
 
2765
2864
  // src/drawing/text/draw-text.ts
@@ -2820,6 +2919,33 @@ var getCollapsedText = (span) => {
2820
2919
  };
2821
2920
 
2822
2921
  // src/drawing/text/find-line-breaks.text.ts
2922
+ var cannotStartLine = (segment) => {
2923
+ if (segment.length === 0)
2924
+ return false;
2925
+ const firstChar = segment[0];
2926
+ const forbiddenLineStarts = [
2927
+ ".",
2928
+ ",",
2929
+ ";",
2930
+ ":",
2931
+ "!",
2932
+ "?",
2933
+ ")",
2934
+ "]",
2935
+ "}",
2936
+ '"',
2937
+ "'",
2938
+ '"',
2939
+ `'`,
2940
+ "»",
2941
+ "…",
2942
+ "‥",
2943
+ "·",
2944
+ "%",
2945
+ "‰"
2946
+ ];
2947
+ return forbiddenLineStarts.includes(firstChar);
2948
+ };
2823
2949
  function findLineBreaks(span, rtl) {
2824
2950
  const textNode = span.childNodes[0];
2825
2951
  const originalText = textNode.textContent;
@@ -2851,12 +2977,25 @@ function findLineBreaks(span, rtl) {
2851
2977
  if (previousRect && previousRect.height !== 0 && Math.abs(currentHeight - previousRect.height) > 2) {
2852
2978
  const offsetHorizontal = rtl ? previousRect.right - originalRect.right : previousRect.left - originalRect.left;
2853
2979
  const shouldCollapse = !computedStyle.whiteSpaceCollapse.includes("preserve");
2980
+ let textForPreviousLine = currentLine;
2981
+ let textForNewLine = wordsToAdd;
2982
+ if (cannotStartLine(word)) {
2983
+ const currentLineSegments = Array.from(segmenter.segment(currentLine)).map((s) => s.segment);
2984
+ let lastWordIndex = currentLineSegments.length - 1;
2985
+ while (lastWordIndex >= 0 && currentLineSegments[lastWordIndex].trim() === "") {
2986
+ lastWordIndex--;
2987
+ }
2988
+ if (lastWordIndex >= 0) {
2989
+ textForPreviousLine = currentLineSegments.slice(0, lastWordIndex).join("");
2990
+ textForNewLine = currentLineSegments.slice(lastWordIndex).join("") + wordsToAdd;
2991
+ }
2992
+ }
2854
2993
  lines.push({
2855
- text: shouldCollapse ? currentLine.trim() : currentLine,
2994
+ text: shouldCollapse ? textForPreviousLine.trim() : textForPreviousLine,
2856
2995
  height: currentHeight - previousRect.height,
2857
2996
  offsetHorizontal
2858
2997
  });
2859
- currentLine = wordsToAdd;
2998
+ currentLine = textForNewLine;
2860
2999
  } else {
2861
3000
  currentLine += wordsToAdd;
2862
3001
  }
@@ -3203,9 +3342,10 @@ var waitForReady = ({
3203
3342
  timeoutInMilliseconds,
3204
3343
  scope,
3205
3344
  signal,
3206
- apiName
3345
+ apiName,
3346
+ internalState
3207
3347
  }) => {
3208
- const start = Date.now();
3348
+ const start = performance.now();
3209
3349
  const { promise, resolve, reject } = withResolvers();
3210
3350
  let cancelled = false;
3211
3351
  const check = () => {
@@ -3214,20 +3354,24 @@ var waitForReady = ({
3214
3354
  }
3215
3355
  if (signal?.aborted) {
3216
3356
  cancelled = true;
3357
+ internalState?.addWaitForReadyTime(performance.now() - start);
3217
3358
  reject(new Error(`${apiName}() was cancelled`));
3218
3359
  return;
3219
3360
  }
3220
3361
  if (scope.remotion_renderReady === true) {
3362
+ internalState?.addWaitForReadyTime(performance.now() - start);
3221
3363
  resolve();
3222
3364
  return;
3223
3365
  }
3224
3366
  if (scope.remotion_cancelledError !== undefined) {
3225
3367
  cancelled = true;
3368
+ internalState?.addWaitForReadyTime(performance.now() - start);
3226
3369
  reject(scope.remotion_cancelledError);
3227
3370
  return;
3228
3371
  }
3229
- if (Date.now() - start > timeoutInMilliseconds + 3000) {
3372
+ if (performance.now() - start > timeoutInMilliseconds + 3000) {
3230
3373
  cancelled = true;
3374
+ internalState?.addWaitForReadyTime(performance.now() - start);
3231
3375
  reject(new Error(Object.values(scope.remotion_delayRenderTimeouts).map((d) => d.label).join(", ")));
3232
3376
  return;
3233
3377
  }
@@ -3299,226 +3443,228 @@ var internalRenderMediaOnWeb = async ({
3299
3443
  licenseKey,
3300
3444
  muted
3301
3445
  }) => {
3302
- const outputTarget = userDesiredOutputTarget === null ? await canUseWebFsWriter() ? "web-fs" : "arraybuffer" : userDesiredOutputTarget;
3303
- if (outputTarget === "web-fs") {
3304
- await cleanupStaleOpfsFiles();
3305
- }
3306
- const cleanupFns = [];
3307
- const format = containerToMediabunnyContainer(container);
3308
- if (codec && !format.getSupportedCodecs().includes(codecToMediabunnyCodec(codec))) {
3309
- return Promise.reject(new Error(`Codec ${codec} is not supported for container ${container}`));
3310
- }
3311
- const resolved = await Internals7.resolveVideoConfig({
3312
- calculateMetadata: composition.calculateMetadata ?? null,
3313
- signal: signal ?? new AbortController().signal,
3314
- defaultProps: composition.defaultProps ?? {},
3315
- inputProps: inputProps ?? {},
3316
- compositionId: composition.id,
3317
- compositionDurationInFrames: composition.durationInFrames ?? null,
3318
- compositionFps: composition.fps ?? null,
3319
- compositionHeight: composition.height ?? null,
3320
- compositionWidth: composition.width ?? null
3321
- });
3322
- const realFrameRange = getRealFrameRange(resolved.durationInFrames, frameRange);
3323
- if (signal?.aborted) {
3324
- return Promise.reject(new Error("renderMediaOnWeb() was cancelled"));
3325
- }
3326
- const { delayRenderScope, div, cleanupScaffold, timeUpdater, collectAssets } = await createScaffold({
3327
- width: resolved.width,
3328
- height: resolved.height,
3329
- fps: resolved.fps,
3330
- durationInFrames: resolved.durationInFrames,
3331
- Component: composition.component,
3332
- resolvedProps: resolved.props,
3333
- id: resolved.id,
3334
- delayRenderTimeoutInMilliseconds,
3335
- logLevel,
3336
- mediaCacheSizeInBytes,
3337
- schema: schema ?? null,
3338
- audioEnabled: !muted,
3339
- videoEnabled: true,
3340
- initialFrame: 0,
3341
- defaultCodec: resolved.defaultCodec,
3342
- defaultOutName: resolved.defaultOutName
3343
- });
3344
- const internalState = makeInternalState();
3345
- const artifactsHandler = handleArtifacts();
3346
- cleanupFns.push(() => {
3347
- cleanupScaffold();
3348
- });
3349
- const webFsTarget = outputTarget === "web-fs" ? await createWebFsTarget() : null;
3350
- const target = webFsTarget ? new StreamTarget(webFsTarget.stream) : new BufferTarget;
3351
- const output = new Output({
3352
- format,
3353
- target
3354
- });
3446
+ let __stack2 = [];
3355
3447
  try {
3356
- if (signal?.aborted) {
3357
- throw new Error("renderMediaOnWeb() was cancelled");
3358
- }
3359
- await waitForReady({
3360
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3361
- scope: delayRenderScope,
3362
- signal,
3363
- apiName: "renderMediaOnWeb"
3448
+ const outputTarget = userDesiredOutputTarget === null ? await canUseWebFsWriter() ? "web-fs" : "arraybuffer" : userDesiredOutputTarget;
3449
+ if (outputTarget === "web-fs") {
3450
+ await cleanupStaleOpfsFiles();
3451
+ }
3452
+ const format = containerToMediabunnyContainer(container);
3453
+ if (codec && !format.getSupportedCodecs().includes(codecToMediabunnyCodec(codec))) {
3454
+ return Promise.reject(new Error(`Codec ${codec} is not supported for container ${container}`));
3455
+ }
3456
+ const resolved = await Internals7.resolveVideoConfig({
3457
+ calculateMetadata: composition.calculateMetadata ?? null,
3458
+ signal: signal ?? new AbortController().signal,
3459
+ defaultProps: composition.defaultProps ?? {},
3460
+ inputProps: inputProps ?? {},
3461
+ compositionId: composition.id,
3462
+ compositionDurationInFrames: composition.durationInFrames ?? null,
3463
+ compositionFps: composition.fps ?? null,
3464
+ compositionHeight: composition.height ?? null,
3465
+ compositionWidth: composition.width ?? null
3364
3466
  });
3467
+ const realFrameRange = getRealFrameRange(resolved.durationInFrames, frameRange);
3365
3468
  if (signal?.aborted) {
3366
- throw new Error("renderMediaOnWeb() was cancelled");
3469
+ return Promise.reject(new Error("renderMediaOnWeb() was cancelled"));
3367
3470
  }
3368
- cleanupFns.push(() => {
3369
- if (output.state === "finalized" || output.state === "canceled") {
3370
- return;
3371
- }
3372
- output.cancel();
3373
- });
3374
- const videoSampleSource = new VideoSampleSource({
3375
- codec: codecToMediabunnyCodec(codec),
3376
- bitrate: typeof videoBitrate === "number" ? videoBitrate : getQualityForWebRendererQuality(videoBitrate),
3377
- sizeChangeBehavior: "deny",
3378
- hardwareAcceleration,
3379
- latencyMode: "quality",
3380
- keyFrameInterval: keyframeIntervalInSeconds,
3381
- alpha: transparent ? "keep" : "discard"
3382
- });
3383
- cleanupFns.push(() => {
3384
- videoSampleSource.close();
3385
- });
3386
- output.addVideoTrack(videoSampleSource);
3387
- let audioSampleSource = null;
3388
- if (!muted) {
3389
- const defaultAudioEncodingConfig = await getDefaultAudioEncodingConfig();
3390
- if (!defaultAudioEncodingConfig) {
3391
- return Promise.reject(new Error("No default audio encoding config found"));
3392
- }
3393
- audioSampleSource = new AudioSampleSource(defaultAudioEncodingConfig);
3394
- cleanupFns.push(() => {
3395
- audioSampleSource?.close();
3396
- });
3397
- output.addAudioTrack(audioSampleSource);
3398
- }
3399
- await output.start();
3400
- if (signal?.aborted) {
3401
- throw new Error("renderMediaOnWeb() was cancelled");
3402
- }
3403
- const progress = {
3404
- renderedFrames: 0,
3405
- encodedFrames: 0
3406
- };
3407
- const throttledOnProgress = createThrottledProgressCallback(onProgress);
3408
- for (let frame = realFrameRange[0];frame <= realFrameRange[1]; frame++) {
3409
- if (signal?.aborted) {
3410
- throw new Error("renderMediaOnWeb() was cancelled");
3411
- }
3412
- timeUpdater.current?.update(frame);
3413
- await waitForReady({
3414
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3415
- scope: delayRenderScope,
3416
- signal,
3417
- apiName: "renderMediaOnWeb"
3418
- });
3419
- if (signal?.aborted) {
3420
- throw new Error("renderMediaOnWeb() was cancelled");
3421
- }
3422
- const imageData = await createFrame({
3423
- div,
3424
- width: resolved.width,
3425
- height: resolved.height,
3426
- logLevel,
3427
- internalState
3428
- });
3429
- if (signal?.aborted) {
3430
- throw new Error("renderMediaOnWeb() was cancelled");
3431
- }
3432
- const assets = collectAssets.current.collectAssets();
3433
- if (onArtifact) {
3434
- await artifactsHandler.handle({
3435
- imageData,
3436
- frame,
3437
- assets,
3438
- onArtifact
3471
+ const scaffold = __using(__stack2, await createScaffold({
3472
+ width: resolved.width,
3473
+ height: resolved.height,
3474
+ fps: resolved.fps,
3475
+ durationInFrames: resolved.durationInFrames,
3476
+ Component: composition.component,
3477
+ resolvedProps: resolved.props,
3478
+ id: resolved.id,
3479
+ delayRenderTimeoutInMilliseconds,
3480
+ logLevel,
3481
+ mediaCacheSizeInBytes,
3482
+ schema: schema ?? null,
3483
+ audioEnabled: !muted,
3484
+ videoEnabled: true,
3485
+ initialFrame: 0,
3486
+ defaultCodec: resolved.defaultCodec,
3487
+ defaultOutName: resolved.defaultOutName
3488
+ }), 0);
3489
+ const { delayRenderScope, div, timeUpdater, collectAssets } = scaffold;
3490
+ const internalState = __using(__stack2, makeInternalState(), 0);
3491
+ const artifactsHandler = handleArtifacts();
3492
+ const webFsTarget = outputTarget === "web-fs" ? await createWebFsTarget() : null;
3493
+ const target = webFsTarget ? new StreamTarget(webFsTarget.stream) : new BufferTarget;
3494
+ const outputWithCleanup = __using(__stack2, makeOutputWithCleanup({
3495
+ format,
3496
+ target
3497
+ }), 0);
3498
+ try {
3499
+ let __stack = [];
3500
+ try {
3501
+ if (signal?.aborted) {
3502
+ throw new Error("renderMediaOnWeb() was cancelled");
3503
+ }
3504
+ await waitForReady({
3505
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3506
+ scope: delayRenderScope,
3507
+ signal,
3508
+ apiName: "renderMediaOnWeb",
3509
+ internalState
3439
3510
  });
3440
- }
3441
- if (signal?.aborted) {
3442
- throw new Error("renderMediaOnWeb() was cancelled");
3443
- }
3444
- const audio = muted ? null : onlyInlineAudio({ assets, fps: resolved.fps, frame });
3445
- const timestamp = Math.round((frame - realFrameRange[0]) / resolved.fps * 1e6);
3446
- const videoFrame = new VideoFrame(imageData, {
3447
- timestamp
3448
- });
3449
- progress.renderedFrames++;
3450
- throttledOnProgress?.({ ...progress });
3451
- let frameToEncode = videoFrame;
3452
- if (onFrame) {
3453
- const returnedFrame = await onFrame(videoFrame);
3454
3511
  if (signal?.aborted) {
3455
3512
  throw new Error("renderMediaOnWeb() was cancelled");
3456
3513
  }
3457
- frameToEncode = validateVideoFrame({
3458
- originalFrame: videoFrame,
3459
- returnedFrame,
3460
- expectedWidth: resolved.width,
3461
- expectedHeight: resolved.height,
3462
- expectedTimestamp: timestamp
3514
+ const videoSampleSource = __using(__stack, makeVideoSampleSourceCleanup({
3515
+ codec: codecToMediabunnyCodec(codec),
3516
+ bitrate: typeof videoBitrate === "number" ? videoBitrate : getQualityForWebRendererQuality(videoBitrate),
3517
+ sizeChangeBehavior: "deny",
3518
+ hardwareAcceleration,
3519
+ latencyMode: "quality",
3520
+ keyFrameInterval: keyframeIntervalInSeconds,
3521
+ alpha: transparent ? "keep" : "discard"
3522
+ }), 0);
3523
+ outputWithCleanup.output.addVideoTrack(videoSampleSource.videoSampleSource);
3524
+ const audioSampleSource = __using(__stack, await addAudioSampleSource({
3525
+ muted,
3526
+ output: outputWithCleanup.output
3527
+ }), 0);
3528
+ await outputWithCleanup.output.start();
3529
+ if (signal?.aborted) {
3530
+ throw new Error("renderMediaOnWeb() was cancelled");
3531
+ }
3532
+ const progress = {
3533
+ renderedFrames: 0,
3534
+ encodedFrames: 0
3535
+ };
3536
+ const throttledOnProgress = createThrottledProgressCallback(onProgress);
3537
+ for (let frame = realFrameRange[0];frame <= realFrameRange[1]; frame++) {
3538
+ if (signal?.aborted) {
3539
+ throw new Error("renderMediaOnWeb() was cancelled");
3540
+ }
3541
+ timeUpdater.current?.update(frame);
3542
+ await waitForReady({
3543
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3544
+ scope: delayRenderScope,
3545
+ signal,
3546
+ apiName: "renderMediaOnWeb",
3547
+ internalState
3548
+ });
3549
+ if (signal?.aborted) {
3550
+ throw new Error("renderMediaOnWeb() was cancelled");
3551
+ }
3552
+ const createFrameStart = performance.now();
3553
+ const imageData = await createFrame({
3554
+ div,
3555
+ width: resolved.width,
3556
+ height: resolved.height,
3557
+ logLevel,
3558
+ internalState
3559
+ });
3560
+ internalState.addCreateFrameTime(performance.now() - createFrameStart);
3561
+ if (signal?.aborted) {
3562
+ throw new Error("renderMediaOnWeb() was cancelled");
3563
+ }
3564
+ const timestamp = Math.round((frame - realFrameRange[0]) / resolved.fps * 1e6);
3565
+ const videoFrame = new VideoFrame(imageData, {
3566
+ timestamp
3567
+ });
3568
+ progress.renderedFrames++;
3569
+ throttledOnProgress?.({ ...progress });
3570
+ let frameToEncode = videoFrame;
3571
+ if (onFrame) {
3572
+ const returnedFrame = await onFrame(videoFrame);
3573
+ if (signal?.aborted) {
3574
+ throw new Error("renderMediaOnWeb() was cancelled");
3575
+ }
3576
+ frameToEncode = validateVideoFrame({
3577
+ originalFrame: videoFrame,
3578
+ returnedFrame,
3579
+ expectedWidth: resolved.width,
3580
+ expectedHeight: resolved.height,
3581
+ expectedTimestamp: timestamp
3582
+ });
3583
+ }
3584
+ const audioCombineStart = performance.now();
3585
+ const assets = collectAssets.current.collectAssets();
3586
+ if (onArtifact) {
3587
+ await artifactsHandler.handle({
3588
+ imageData,
3589
+ frame,
3590
+ assets,
3591
+ onArtifact
3592
+ });
3593
+ }
3594
+ if (signal?.aborted) {
3595
+ throw new Error("renderMediaOnWeb() was cancelled");
3596
+ }
3597
+ const audio = muted ? null : onlyInlineAudio({ assets, fps: resolved.fps, frame });
3598
+ internalState.addAudioMixingTime(performance.now() - audioCombineStart);
3599
+ const addSampleStart = performance.now();
3600
+ await Promise.all([
3601
+ addVideoSampleAndCloseFrame(frameToEncode, videoSampleSource.videoSampleSource),
3602
+ audio && audioSampleSource ? addAudioSample(audio, audioSampleSource.audioSampleSource) : Promise.resolve()
3603
+ ]);
3604
+ internalState.addAddSampleTime(performance.now() - addSampleStart);
3605
+ progress.encodedFrames++;
3606
+ throttledOnProgress?.({ ...progress });
3607
+ if (signal?.aborted) {
3608
+ throw new Error("renderMediaOnWeb() was cancelled");
3609
+ }
3610
+ }
3611
+ onProgress?.({ ...progress });
3612
+ videoSampleSource.videoSampleSource.close();
3613
+ audioSampleSource?.audioSampleSource.close();
3614
+ await outputWithCleanup.output.finalize();
3615
+ Internals7.Log.verbose({ logLevel, tag: "web-renderer" }, `Render timings: waitForReady=${internalState.getWaitForReadyTime().toFixed(2)}ms, createFrame=${internalState.getCreateFrameTime().toFixed(2)}ms, addSample=${internalState.getAddSampleTime().toFixed(2)}ms, audioMixing=${internalState.getAudioMixingTime().toFixed(2)}ms`);
3616
+ if (webFsTarget) {
3617
+ sendUsageEvent({
3618
+ licenseKey: licenseKey ?? null,
3619
+ succeeded: true,
3620
+ apiName: "renderMediaOnWeb"
3621
+ });
3622
+ await webFsTarget.close();
3623
+ return {
3624
+ getBlob: () => {
3625
+ return webFsTarget.getBlob();
3626
+ },
3627
+ internalState
3628
+ };
3629
+ }
3630
+ if (!(target instanceof BufferTarget)) {
3631
+ throw new Error("Expected target to be a BufferTarget");
3632
+ }
3633
+ sendUsageEvent({
3634
+ licenseKey: licenseKey ?? null,
3635
+ succeeded: true,
3636
+ apiName: "renderMediaOnWeb"
3463
3637
  });
3638
+ return {
3639
+ getBlob: () => {
3640
+ if (!target.buffer) {
3641
+ throw new Error("The resulting buffer is empty");
3642
+ }
3643
+ return Promise.resolve(new Blob([target.buffer], { type: getMimeType(container) }));
3644
+ },
3645
+ internalState
3646
+ };
3647
+ } catch (_catch) {
3648
+ var _err = _catch, _hasErr = 1;
3649
+ } finally {
3650
+ __callDispose(__stack, _err, _hasErr);
3464
3651
  }
3465
- await Promise.all([
3466
- addVideoSampleAndCloseFrame(frameToEncode, videoSampleSource),
3467
- audio && audioSampleSource ? addAudioSample(audio, audioSampleSource) : Promise.resolve()
3468
- ]);
3469
- progress.encodedFrames++;
3470
- throttledOnProgress?.({ ...progress });
3471
- if (signal?.aborted) {
3472
- throw new Error("renderMediaOnWeb() was cancelled");
3652
+ } catch (err) {
3653
+ if (!signal?.aborted) {
3654
+ sendUsageEvent({
3655
+ succeeded: false,
3656
+ licenseKey: licenseKey ?? null,
3657
+ apiName: "renderMediaOnWeb"
3658
+ }).catch((err2) => {
3659
+ Internals7.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3660
+ });
3473
3661
  }
3662
+ throw err;
3474
3663
  }
3475
- onProgress?.({ ...progress });
3476
- videoSampleSource.close();
3477
- audioSampleSource?.close();
3478
- await output.finalize();
3479
- const mimeType = getMimeType(container);
3480
- if (webFsTarget) {
3481
- sendUsageEvent({
3482
- licenseKey: licenseKey ?? null,
3483
- succeeded: true,
3484
- apiName: "renderMediaOnWeb"
3485
- });
3486
- await webFsTarget.close();
3487
- return {
3488
- getBlob: () => {
3489
- return webFsTarget.getBlob();
3490
- },
3491
- internalState
3492
- };
3493
- }
3494
- if (!(target instanceof BufferTarget)) {
3495
- throw new Error("Expected target to be a BufferTarget");
3496
- }
3497
- sendUsageEvent({
3498
- licenseKey: licenseKey ?? null,
3499
- succeeded: true,
3500
- apiName: "renderMediaOnWeb"
3501
- });
3502
- return {
3503
- getBlob: () => {
3504
- if (!target.buffer) {
3505
- throw new Error("The resulting buffer is empty");
3506
- }
3507
- return Promise.resolve(new Blob([target.buffer], { type: mimeType }));
3508
- },
3509
- internalState
3510
- };
3511
- } catch (err) {
3512
- sendUsageEvent({
3513
- succeeded: false,
3514
- licenseKey: licenseKey ?? null,
3515
- apiName: "renderMediaOnWeb"
3516
- }).catch((err2) => {
3517
- Internals7.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3518
- });
3519
- throw err;
3664
+ } catch (_catch2) {
3665
+ var _err2 = _catch2, _hasErr2 = 1;
3520
3666
  } finally {
3521
- cleanupFns.forEach((fn) => fn());
3667
+ __callDispose(__stack2, _err2, _hasErr2);
3522
3668
  }
3523
3669
  };
3524
3670
  var renderMediaOnWeb = (options) => {
@@ -3564,83 +3710,91 @@ async function internalRenderStillOnWeb({
3564
3710
  onArtifact,
3565
3711
  licenseKey
3566
3712
  }) {
3567
- const resolved = await Internals8.resolveVideoConfig({
3568
- calculateMetadata: composition.calculateMetadata ?? null,
3569
- signal: signal ?? new AbortController().signal,
3570
- defaultProps: composition.defaultProps ?? {},
3571
- inputProps: inputProps ?? {},
3572
- compositionId: composition.id,
3573
- compositionDurationInFrames: composition.durationInFrames ?? null,
3574
- compositionFps: composition.fps ?? null,
3575
- compositionHeight: composition.height ?? null,
3576
- compositionWidth: composition.width ?? null
3577
- });
3578
- if (signal?.aborted) {
3579
- return Promise.reject(new Error("renderStillOnWeb() was cancelled"));
3580
- }
3581
- const internalState = makeInternalState();
3582
- const { delayRenderScope, div, cleanupScaffold, collectAssets } = await createScaffold({
3583
- width: resolved.width,
3584
- height: resolved.height,
3585
- delayRenderTimeoutInMilliseconds,
3586
- logLevel,
3587
- resolvedProps: resolved.props,
3588
- id: resolved.id,
3589
- mediaCacheSizeInBytes,
3590
- audioEnabled: false,
3591
- Component: composition.component,
3592
- videoEnabled: true,
3593
- durationInFrames: resolved.durationInFrames,
3594
- fps: resolved.fps,
3595
- schema: schema ?? null,
3596
- initialFrame: frame,
3597
- defaultCodec: resolved.defaultCodec,
3598
- defaultOutName: resolved.defaultOutName
3599
- });
3600
- const artifactsHandler = handleArtifacts();
3713
+ let __stack = [];
3601
3714
  try {
3602
- if (signal?.aborted) {
3603
- throw new Error("renderStillOnWeb() was cancelled");
3604
- }
3605
- await waitForReady({
3606
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3607
- scope: delayRenderScope,
3608
- signal,
3609
- apiName: "renderStillOnWeb"
3715
+ const resolved = await Internals8.resolveVideoConfig({
3716
+ calculateMetadata: composition.calculateMetadata ?? null,
3717
+ signal: signal ?? new AbortController().signal,
3718
+ defaultProps: composition.defaultProps ?? {},
3719
+ inputProps: inputProps ?? {},
3720
+ compositionId: composition.id,
3721
+ compositionDurationInFrames: composition.durationInFrames ?? null,
3722
+ compositionFps: composition.fps ?? null,
3723
+ compositionHeight: composition.height ?? null,
3724
+ compositionWidth: composition.width ?? null
3610
3725
  });
3611
3726
  if (signal?.aborted) {
3612
- throw new Error("renderStillOnWeb() was cancelled");
3727
+ return Promise.reject(new Error("renderStillOnWeb() was cancelled"));
3613
3728
  }
3614
- const imageData = await takeScreenshot({
3615
- div,
3729
+ const internalState = __using(__stack, makeInternalState(), 0);
3730
+ const scaffold = __using(__stack, await createScaffold({
3616
3731
  width: resolved.width,
3617
3732
  height: resolved.height,
3618
- imageFormat,
3733
+ delayRenderTimeoutInMilliseconds,
3619
3734
  logLevel,
3620
- internalState
3621
- });
3622
- const assets = collectAssets.current.collectAssets();
3623
- if (onArtifact) {
3624
- await artifactsHandler.handle({ imageData, frame, assets, onArtifact });
3625
- }
3626
- sendUsageEvent({
3627
- licenseKey: licenseKey ?? null,
3628
- succeeded: true,
3629
- apiName: "renderStillOnWeb"
3630
- });
3631
- return { blob: imageData, internalState };
3632
- } catch (err) {
3633
- sendUsageEvent({
3634
- succeeded: false,
3635
- licenseKey: licenseKey ?? null,
3636
- apiName: "renderStillOnWeb"
3637
- }).catch((err2) => {
3638
- Internals8.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3639
- });
3640
- throw err;
3735
+ resolvedProps: resolved.props,
3736
+ id: resolved.id,
3737
+ mediaCacheSizeInBytes,
3738
+ audioEnabled: false,
3739
+ Component: composition.component,
3740
+ videoEnabled: true,
3741
+ durationInFrames: resolved.durationInFrames,
3742
+ fps: resolved.fps,
3743
+ schema: schema ?? null,
3744
+ initialFrame: frame,
3745
+ defaultCodec: resolved.defaultCodec,
3746
+ defaultOutName: resolved.defaultOutName
3747
+ }), 0);
3748
+ const { delayRenderScope, div, collectAssets } = scaffold;
3749
+ const artifactsHandler = handleArtifacts();
3750
+ try {
3751
+ if (signal?.aborted) {
3752
+ throw new Error("renderStillOnWeb() was cancelled");
3753
+ }
3754
+ await waitForReady({
3755
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds,
3756
+ scope: delayRenderScope,
3757
+ signal,
3758
+ apiName: "renderStillOnWeb",
3759
+ internalState: null
3760
+ });
3761
+ if (signal?.aborted) {
3762
+ throw new Error("renderStillOnWeb() was cancelled");
3763
+ }
3764
+ const imageData = await takeScreenshot({
3765
+ div,
3766
+ width: resolved.width,
3767
+ height: resolved.height,
3768
+ imageFormat,
3769
+ logLevel,
3770
+ internalState
3771
+ });
3772
+ const assets = collectAssets.current.collectAssets();
3773
+ if (onArtifact) {
3774
+ await artifactsHandler.handle({ imageData, frame, assets, onArtifact });
3775
+ }
3776
+ sendUsageEvent({
3777
+ licenseKey: licenseKey ?? null,
3778
+ succeeded: true,
3779
+ apiName: "renderStillOnWeb"
3780
+ });
3781
+ return { blob: imageData, internalState };
3782
+ } catch (err) {
3783
+ if (!signal?.aborted) {
3784
+ sendUsageEvent({
3785
+ succeeded: false,
3786
+ licenseKey: licenseKey ?? null,
3787
+ apiName: "renderStillOnWeb"
3788
+ }).catch((err2) => {
3789
+ Internals8.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3790
+ });
3791
+ }
3792
+ throw err;
3793
+ }
3794
+ } catch (_catch) {
3795
+ var _err = _catch, _hasErr = 1;
3641
3796
  } finally {
3642
- internalState.cleanup();
3643
- cleanupScaffold();
3797
+ __callDispose(__stack, _err, _hasErr);
3644
3798
  }
3645
3799
  }
3646
3800
  var renderStillOnWeb = (options) => {