@remotion/web-renderer 4.0.396 → 4.0.397

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 (48) hide show
  1. package/dist/compose.js +11 -5
  2. package/dist/create-scaffold.js +10 -3
  3. package/dist/drawing/border-radius.js +9 -32
  4. package/dist/drawing/calculate-transforms.d.ts +9 -3
  5. package/dist/drawing/calculate-transforms.js +31 -9
  6. package/dist/drawing/clamp-rect-to-parent-bounds.d.ts +4 -0
  7. package/dist/drawing/clamp-rect-to-parent-bounds.js +11 -0
  8. package/dist/drawing/do-rects-intersect.d.ts +1 -0
  9. package/dist/drawing/do-rects-intersect.js +6 -0
  10. package/dist/drawing/draw-box-shadow.d.ts +18 -0
  11. package/dist/drawing/draw-box-shadow.js +103 -0
  12. package/dist/drawing/draw-element.d.ts +4 -1
  13. package/dist/drawing/draw-element.js +37 -6
  14. package/dist/drawing/draw-outline.js +9 -32
  15. package/dist/drawing/draw-rounded.d.ts +9 -0
  16. package/dist/drawing/draw-rounded.js +34 -0
  17. package/dist/drawing/get-pretransform-rect.js +5 -0
  18. package/dist/drawing/handle-3d-transform.d.ts +9 -8
  19. package/dist/drawing/handle-3d-transform.js +11 -25
  20. package/dist/drawing/handle-mask.d.ts +8 -0
  21. package/dist/drawing/handle-mask.js +19 -0
  22. package/dist/drawing/mask-image.d.ts +3 -0
  23. package/dist/drawing/mask-image.js +14 -0
  24. package/dist/drawing/parse-linear-gradient.d.ts +14 -0
  25. package/dist/drawing/parse-linear-gradient.js +260 -0
  26. package/dist/drawing/precompose.d.ts +11 -0
  27. package/dist/drawing/precompose.js +13 -0
  28. package/dist/drawing/process-node.d.ts +4 -3
  29. package/dist/drawing/process-node.js +89 -14
  30. package/dist/drawing/round-to-expand-rect.d.ts +1 -0
  31. package/dist/drawing/round-to-expand-rect.js +7 -0
  32. package/dist/drawing/text/draw-text.d.ts +5 -1
  33. package/dist/drawing/text/draw-text.js +10 -5
  34. package/dist/drawing/text/find-line-breaks.text.d.ts +1 -1
  35. package/dist/drawing/text/find-line-breaks.text.js +2 -2
  36. package/dist/drawing/text/handle-text-node.d.ts +2 -1
  37. package/dist/drawing/text/handle-text-node.js +3 -2
  38. package/dist/drawing/transform-in-3d.d.ts +3 -1
  39. package/dist/drawing/transform-in-3d.js +30 -28
  40. package/dist/drawing/transform.d.ts +2 -1
  41. package/dist/drawing/transform.js +6 -2
  42. package/dist/esm/index.mjs +788 -211
  43. package/dist/get-biggest-bounding-client-rect.js +19 -4
  44. package/dist/internal-state.d.ts +2 -2
  45. package/dist/internal-state.js +7 -7
  46. package/dist/render-media-on-web.d.ts +1 -0
  47. package/dist/render-media-on-web.js +22 -14
  48. package/package.json +6 -6
@@ -6,7 +6,7 @@ import {
6
6
  StreamTarget,
7
7
  VideoSampleSource
8
8
  } from "mediabunny";
9
- import { Internals as Internals6 } from "remotion";
9
+ import { Internals as Internals7 } from "remotion";
10
10
 
11
11
  // src/add-sample.ts
12
12
  import { AudioSample, VideoSample } from "mediabunny";
@@ -231,16 +231,22 @@ async function createScaffold({
231
231
  throw new Error("@remotion/web-renderer requires React 18 or higher");
232
232
  }
233
233
  const div = document.createElement("div");
234
+ div.style.position = "fixed";
234
235
  div.style.display = "flex";
236
+ div.style.flexDirection = "column";
235
237
  div.style.backgroundColor = "transparent";
236
- div.style.position = "fixed";
237
238
  div.style.width = `${width}px`;
238
239
  div.style.height = `${height}px`;
239
240
  div.style.zIndex = "-9999";
240
241
  div.style.top = "0";
241
- div.style.visibility = "hidden";
242
242
  div.style.left = "0";
243
+ div.style.right = "0";
244
+ div.style.bottom = "0";
245
+ div.style.visibility = "hidden";
243
246
  div.style.pointerEvents = "none";
247
+ const scaffoldClassName = `remotion-scaffold-${Math.random().toString(36).substring(2, 15)}`;
248
+ div.className = scaffoldClassName;
249
+ const cleanupCSS = Internals2.CSSUtils.injectCSS(Internals2.CSSUtils.makeDefaultPreviewCSS(`.${scaffoldClassName}`, "white"));
244
250
  document.body.appendChild(div);
245
251
  const { promise, resolve, reject } = withResolvers();
246
252
  const root = ReactDOM.createRoot(div, {
@@ -336,6 +342,7 @@ async function createScaffold({
336
342
  cleanupScaffold: () => {
337
343
  root.unmount();
338
344
  div.remove();
345
+ cleanupCSS();
339
346
  },
340
347
  timeUpdater,
341
348
  collectAssets
@@ -384,17 +391,17 @@ var getDefaultAudioEncodingConfig = async () => {
384
391
 
385
392
  // src/internal-state.ts
386
393
  var makeInternalState = () => {
387
- let drawn3dPixels = 0;
388
- let drawn3dTextures = 0;
394
+ let drawnPrecomposedPixels = 0;
395
+ let precomposedTextures = 0;
389
396
  return {
390
- getDrawn3dPixels: () => drawn3dPixels,
391
- getDrawn3dTextures: () => drawn3dTextures,
392
- add3DTransform: ({
397
+ getDrawn3dPixels: () => drawnPrecomposedPixels,
398
+ getPrecomposedTiles: () => precomposedTextures,
399
+ addPrecompose: ({
393
400
  canvasWidth,
394
401
  canvasHeight
395
402
  }) => {
396
- drawn3dPixels += canvasWidth * canvasHeight;
397
- drawn3dTextures++;
403
+ drawnPrecomposedPixels += canvasWidth * canvasHeight;
404
+ precomposedTextures++;
398
405
  }
399
406
  };
400
407
  };
@@ -600,6 +607,9 @@ var drawDomElement = (node) => {
600
607
  return domDrawFn;
601
608
  };
602
609
 
610
+ // src/drawing/process-node.ts
611
+ import { Internals as Internals5 } from "remotion";
612
+
603
613
  // src/drawing/has-transform.ts
604
614
  var hasTransformCssValue = (style) => {
605
615
  return style.transform !== "none" && style.transform !== "";
@@ -614,6 +624,239 @@ var hasAnyTransformCssValue = (style) => {
614
624
  return hasTransformCssValue(style) || hasRotateCssValue(style) || hasScaleCssValue(style);
615
625
  };
616
626
 
627
+ // src/drawing/parse-linear-gradient.ts
628
+ import { NoReactInternals as NoReactInternals2 } from "remotion/no-react";
629
+ var isValidColor = (color) => {
630
+ try {
631
+ const result = NoReactInternals2.processColor(color);
632
+ return result !== null && result !== undefined;
633
+ } catch {
634
+ return false;
635
+ }
636
+ };
637
+ var parseDirection = (directionStr) => {
638
+ const trimmed = directionStr.trim().toLowerCase();
639
+ if (trimmed.startsWith("to ")) {
640
+ const direction = trimmed.substring(3).trim();
641
+ switch (direction) {
642
+ case "top":
643
+ return 0;
644
+ case "right":
645
+ return 90;
646
+ case "bottom":
647
+ return 180;
648
+ case "left":
649
+ return 270;
650
+ case "top right":
651
+ case "right top":
652
+ return 45;
653
+ case "bottom right":
654
+ case "right bottom":
655
+ return 135;
656
+ case "bottom left":
657
+ case "left bottom":
658
+ return 225;
659
+ case "top left":
660
+ case "left top":
661
+ return 315;
662
+ default:
663
+ return 180;
664
+ }
665
+ }
666
+ const angleMatch = trimmed.match(/^(-?\d+\.?\d*)(deg|rad|grad|turn)$/);
667
+ if (angleMatch) {
668
+ const value = parseFloat(angleMatch[1]);
669
+ const unit = angleMatch[2];
670
+ switch (unit) {
671
+ case "deg":
672
+ return value;
673
+ case "rad":
674
+ return value * 180 / Math.PI;
675
+ case "grad":
676
+ return value * 360 / 400;
677
+ case "turn":
678
+ return value * 360;
679
+ default:
680
+ return value;
681
+ }
682
+ }
683
+ return 180;
684
+ };
685
+ var parseColorStops = (colorStopsStr) => {
686
+ const parts = colorStopsStr.split(/,(?![^(]*\))/);
687
+ const stops = [];
688
+ for (const part of parts) {
689
+ const trimmed = part.trim();
690
+ if (!trimmed)
691
+ continue;
692
+ const colorMatch = trimmed.match(/(rgba?\([^)]+\)|hsla?\([^)]+\)|#[0-9a-f]{3,8}|[a-z]+)/i);
693
+ if (!colorMatch) {
694
+ continue;
695
+ }
696
+ const colorStr = colorMatch[0];
697
+ if (!isValidColor(colorStr)) {
698
+ continue;
699
+ }
700
+ const remaining = trimmed.substring(colorMatch.index + colorStr.length).trim();
701
+ const normalizedColor = colorStr;
702
+ let position = null;
703
+ if (remaining) {
704
+ const posMatch = remaining.match(/(-?\d+\.?\d*)(%|px)?/);
705
+ if (posMatch) {
706
+ const value = parseFloat(posMatch[1]);
707
+ const unit = posMatch[2];
708
+ if (unit === "%") {
709
+ position = value / 100;
710
+ } else if (unit === "px") {
711
+ position = null;
712
+ } else {
713
+ position = value / 100;
714
+ }
715
+ }
716
+ }
717
+ stops.push({
718
+ color: normalizedColor,
719
+ position: position !== null ? position : -1
720
+ });
721
+ }
722
+ if (stops.length === 0) {
723
+ return null;
724
+ }
725
+ let lastExplicitIndex = -1;
726
+ let lastExplicitPosition = 0;
727
+ for (let i = 0;i < stops.length; i++) {
728
+ if (stops[i].position !== -1) {
729
+ if (lastExplicitIndex >= 0) {
730
+ const numImplicit = i - lastExplicitIndex - 1;
731
+ if (numImplicit > 0) {
732
+ const step = (stops[i].position - lastExplicitPosition) / (numImplicit + 1);
733
+ for (let j = lastExplicitIndex + 1;j < i; j++) {
734
+ stops[j].position = lastExplicitPosition + step * (j - lastExplicitIndex);
735
+ }
736
+ }
737
+ } else {
738
+ const numImplicit = i;
739
+ if (numImplicit > 0) {
740
+ const step = stops[i].position / (numImplicit + 1);
741
+ for (let j = 0;j < i; j++) {
742
+ stops[j].position = step * (j + 1);
743
+ }
744
+ }
745
+ }
746
+ lastExplicitIndex = i;
747
+ lastExplicitPosition = stops[i].position;
748
+ }
749
+ }
750
+ if (stops.every((s) => s.position === -1)) {
751
+ if (stops.length === 1) {
752
+ stops[0].position = 0.5;
753
+ } else {
754
+ for (let i = 0;i < stops.length; i++) {
755
+ stops[i].position = i / (stops.length - 1);
756
+ }
757
+ }
758
+ } else if (lastExplicitIndex < stops.length - 1) {
759
+ const numImplicit = stops.length - 1 - lastExplicitIndex;
760
+ const step = (1 - lastExplicitPosition) / (numImplicit + 1);
761
+ for (let i = lastExplicitIndex + 1;i < stops.length; i++) {
762
+ stops[i].position = lastExplicitPosition + step * (i - lastExplicitIndex);
763
+ }
764
+ }
765
+ for (const stop of stops) {
766
+ stop.position = Math.max(0, Math.min(1, stop.position));
767
+ }
768
+ return stops;
769
+ };
770
+ var extractGradientContent = (backgroundImage) => {
771
+ const prefix = "linear-gradient(";
772
+ const startIndex = backgroundImage.toLowerCase().indexOf(prefix);
773
+ if (startIndex === -1) {
774
+ return null;
775
+ }
776
+ let depth = 0;
777
+ const contentStart = startIndex + prefix.length;
778
+ for (let i = contentStart;i < backgroundImage.length; i++) {
779
+ const char = backgroundImage[i];
780
+ if (char === "(") {
781
+ depth++;
782
+ } else if (char === ")") {
783
+ if (depth === 0) {
784
+ return backgroundImage.substring(contentStart, i).trim();
785
+ }
786
+ depth--;
787
+ }
788
+ }
789
+ return null;
790
+ };
791
+ var parseLinearGradient = (backgroundImage) => {
792
+ if (!backgroundImage || backgroundImage === "none") {
793
+ return null;
794
+ }
795
+ const content = extractGradientContent(backgroundImage);
796
+ if (!content) {
797
+ return null;
798
+ }
799
+ const parts = content.split(/,(?![^(]*\))/);
800
+ let angle = 180;
801
+ let colorStopsStart = 0;
802
+ if (parts.length > 0) {
803
+ const firstPart = parts[0].trim();
804
+ const isDirection = firstPart.startsWith("to ") || /^-?\d+\.?\d*(deg|rad|grad|turn)$/.test(firstPart);
805
+ if (isDirection) {
806
+ angle = parseDirection(firstPart);
807
+ colorStopsStart = 1;
808
+ }
809
+ }
810
+ const colorStopsStr = parts.slice(colorStopsStart).join(",");
811
+ const colorStops = parseColorStops(colorStopsStr);
812
+ if (!colorStops || colorStops.length === 0) {
813
+ return null;
814
+ }
815
+ return {
816
+ angle,
817
+ colorStops
818
+ };
819
+ };
820
+ var createCanvasGradient = ({
821
+ ctx,
822
+ rect,
823
+ gradientInfo
824
+ }) => {
825
+ const angleRad = (gradientInfo.angle - 90) * Math.PI / 180;
826
+ const centerX = rect.left + rect.width / 2;
827
+ const centerY = rect.top + rect.height / 2;
828
+ const cos = Math.cos(angleRad);
829
+ const sin = Math.sin(angleRad);
830
+ const halfWidth = rect.width / 2;
831
+ const halfHeight = rect.height / 2;
832
+ let length = Math.abs(cos) * halfWidth + Math.abs(sin) * halfHeight;
833
+ if (!Number.isFinite(length) || length === 0) {
834
+ length = Math.sqrt(halfWidth ** 2 + halfHeight ** 2);
835
+ }
836
+ const x0 = centerX - cos * length;
837
+ const y0 = centerY - sin * length;
838
+ const x1 = centerX + cos * length;
839
+ const y1 = centerY + sin * length;
840
+ const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
841
+ for (const stop of gradientInfo.colorStops) {
842
+ gradient.addColorStop(stop.position, stop.color);
843
+ }
844
+ return gradient;
845
+ };
846
+
847
+ // src/drawing/mask-image.ts
848
+ var getMaskImageValue = (computedStyle) => {
849
+ const { maskImage, webkitMaskImage } = computedStyle;
850
+ const value = maskImage || webkitMaskImage;
851
+ if (!value || value === "none") {
852
+ return null;
853
+ }
854
+ return value;
855
+ };
856
+ var parseMaskImage = (maskImageValue) => {
857
+ return parseLinearGradient(maskImageValue);
858
+ };
859
+
617
860
  // src/drawing/parse-transform-origin.ts
618
861
  var parseTransformOrigin = (transformOrigin) => {
619
862
  if (transformOrigin.trim() === "") {
@@ -633,30 +876,39 @@ var getInternalTransformOrigin = (transform) => {
633
876
  };
634
877
  return origin;
635
878
  };
636
- var getGlobalTransformOrigin = ({
637
- transform,
638
- offsetLeft,
639
- offsetTop
640
- }) => {
879
+ var getGlobalTransformOrigin = ({ transform }) => {
641
880
  const { x: originX, y: originY } = getInternalTransformOrigin(transform);
642
881
  return {
643
- x: originX + transform.boundingClientRect.left - offsetLeft,
644
- y: originY + transform.boundingClientRect.top - offsetTop
882
+ x: originX + transform.boundingClientRect.left,
883
+ y: originY + transform.boundingClientRect.top
645
884
  };
646
885
  };
647
886
  var calculateTransforms = ({
648
887
  element,
649
- offsetLeft,
650
- offsetTop
888
+ rootElement
651
889
  }) => {
652
890
  let parent = element;
653
891
  const transforms = [];
654
892
  const toReset = [];
893
+ let opacity = 1;
655
894
  let elementComputedStyle = null;
895
+ let maskImageInfo = null;
656
896
  while (parent) {
657
897
  const computedStyle = getComputedStyle(parent);
658
898
  if (parent === element) {
659
899
  elementComputedStyle = computedStyle;
900
+ opacity = parseFloat(computedStyle.opacity);
901
+ const maskImageValue = getMaskImageValue(computedStyle);
902
+ maskImageInfo = maskImageValue ? parseMaskImage(maskImageValue) : null;
903
+ const originalMaskImage = parent.style.maskImage;
904
+ const originalWebkitMaskImage = parent.style.webkitMaskImage;
905
+ parent.style.maskImage = "none";
906
+ parent.style.webkitMaskImage = "none";
907
+ const parentRef = parent;
908
+ toReset.push(() => {
909
+ parentRef.style.maskImage = originalMaskImage;
910
+ parentRef.style.webkitMaskImage = originalWebkitMaskImage;
911
+ });
660
912
  }
661
913
  if (hasAnyTransformCssValue(computedStyle) || parent === element) {
662
914
  const toParse = hasTransformCssValue(computedStyle) ? computedStyle.transform : undefined;
@@ -686,6 +938,9 @@ var calculateTransforms = ({
686
938
  parentRef.style.rotate = rotate;
687
939
  });
688
940
  }
941
+ if (parent === rootElement) {
942
+ break;
943
+ }
689
944
  parent = parent.parentElement;
690
945
  }
691
946
  for (const transform of transforms) {
@@ -697,9 +952,7 @@ var calculateTransforms = ({
697
952
  for (const transform of transforms.slice().reverse()) {
698
953
  for (const matrix of transform.matrices) {
699
954
  const globalTransformOrigin = getGlobalTransformOrigin({
700
- transform,
701
- offsetLeft,
702
- offsetTop
955
+ transform
703
956
  });
704
957
  const transformMatrix = new DOMMatrix().translate(globalTransformOrigin.x, globalTransformOrigin.y).multiply(matrix).translate(-globalTransformOrigin.x, -globalTransformOrigin.y);
705
958
  totalMatrix.multiplySelf(transformMatrix);
@@ -708,6 +961,8 @@ var calculateTransforms = ({
708
961
  if (!elementComputedStyle) {
709
962
  throw new Error("Element computed style not found");
710
963
  }
964
+ const needs3DTransformViaWebGL = !totalMatrix.is2D;
965
+ const needsMaskImage = maskImageInfo !== null;
711
966
  return {
712
967
  dimensions,
713
968
  totalMatrix,
@@ -718,10 +973,85 @@ var calculateTransforms = ({
718
973
  },
719
974
  nativeTransformOrigin,
720
975
  computedStyle: elementComputedStyle,
721
- opacity: elementComputedStyle.opacity && elementComputedStyle.opacity !== "" ? parseFloat(elementComputedStyle.opacity) : 1
976
+ opacity,
977
+ maskImageInfo,
978
+ precompositing: {
979
+ needs3DTransformViaWebGL,
980
+ needsMaskImage: maskImageInfo,
981
+ needsPrecompositing: Boolean(needs3DTransformViaWebGL || needsMaskImage)
982
+ }
722
983
  };
723
984
  };
724
985
 
986
+ // src/drawing/round-to-expand-rect.ts
987
+ var roundToExpandRect = (rect) => {
988
+ const left = Math.floor(rect.left);
989
+ const top = Math.floor(rect.top);
990
+ const right = Math.ceil(rect.right);
991
+ const bottom = Math.ceil(rect.bottom);
992
+ return new DOMRect(left, top, right - left, bottom - top);
993
+ };
994
+
995
+ // src/drawing/clamp-rect-to-parent-bounds.ts
996
+ var getNarrowerRect = ({
997
+ firstRect,
998
+ secondRect
999
+ }) => {
1000
+ const left = Math.max(firstRect.left, secondRect.left);
1001
+ const top = Math.max(firstRect.top, secondRect.top);
1002
+ const bottom = Math.min(firstRect.bottom, secondRect.bottom);
1003
+ const right = Math.min(firstRect.right, secondRect.right);
1004
+ return new DOMRect(left, top, right - left, bottom - top);
1005
+ };
1006
+ var getWiderRectAndExpand = ({
1007
+ firstRect,
1008
+ secondRect
1009
+ }) => {
1010
+ if (firstRect === null) {
1011
+ return roundToExpandRect(secondRect);
1012
+ }
1013
+ const left = Math.min(firstRect.left, secondRect.left);
1014
+ const top = Math.min(firstRect.top, secondRect.top);
1015
+ const bottom = Math.max(firstRect.bottom, secondRect.bottom);
1016
+ const right = Math.max(firstRect.right, secondRect.right);
1017
+ return roundToExpandRect(new DOMRect(left, top, right - left, bottom - top));
1018
+ };
1019
+
1020
+ // src/drawing/do-rects-intersect.ts
1021
+ function doRectsIntersect(rect1, rect2) {
1022
+ return !(rect1.right <= rect2.left || rect1.left >= rect2.right || rect1.bottom <= rect2.top || rect1.top >= rect2.bottom);
1023
+ }
1024
+
1025
+ // src/drawing/draw-rounded.ts
1026
+ var drawRoundedRectPath = ({
1027
+ ctx,
1028
+ x,
1029
+ y,
1030
+ width,
1031
+ height,
1032
+ borderRadius
1033
+ }) => {
1034
+ ctx.beginPath();
1035
+ ctx.moveTo(x + borderRadius.topLeft.horizontal, y);
1036
+ ctx.lineTo(x + width - borderRadius.topRight.horizontal, y);
1037
+ if (borderRadius.topRight.horizontal > 0 || borderRadius.topRight.vertical > 0) {
1038
+ ctx.ellipse(x + width - borderRadius.topRight.horizontal, y + borderRadius.topRight.vertical, borderRadius.topRight.horizontal, borderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
1039
+ }
1040
+ ctx.lineTo(x + width, y + height - borderRadius.bottomRight.vertical);
1041
+ if (borderRadius.bottomRight.horizontal > 0 || borderRadius.bottomRight.vertical > 0) {
1042
+ ctx.ellipse(x + width - borderRadius.bottomRight.horizontal, y + height - borderRadius.bottomRight.vertical, borderRadius.bottomRight.horizontal, borderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
1043
+ }
1044
+ ctx.lineTo(x + borderRadius.bottomLeft.horizontal, y + height);
1045
+ if (borderRadius.bottomLeft.horizontal > 0 || borderRadius.bottomLeft.vertical > 0) {
1046
+ ctx.ellipse(x + borderRadius.bottomLeft.horizontal, y + height - borderRadius.bottomLeft.vertical, borderRadius.bottomLeft.horizontal, borderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
1047
+ }
1048
+ ctx.lineTo(x, y + borderRadius.topLeft.vertical);
1049
+ if (borderRadius.topLeft.horizontal > 0 || borderRadius.topLeft.vertical > 0) {
1050
+ ctx.ellipse(x + borderRadius.topLeft.horizontal, y + borderRadius.topLeft.vertical, borderRadius.topLeft.horizontal, borderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
1051
+ }
1052
+ ctx.closePath();
1053
+ };
1054
+
725
1055
  // src/drawing/border-radius.ts
726
1056
  function parseValue({
727
1057
  value,
@@ -831,25 +1161,14 @@ function setBorderRadius({
831
1161
  return () => {};
832
1162
  }
833
1163
  ctx.save();
834
- ctx.beginPath();
835
- ctx.moveTo(rect.left + borderRadius.topLeft.horizontal, rect.top);
836
- ctx.lineTo(rect.left + rect.width - borderRadius.topRight.horizontal, rect.top);
837
- if (borderRadius.topRight.horizontal > 0 || borderRadius.topRight.vertical > 0) {
838
- ctx.ellipse(rect.left + rect.width - borderRadius.topRight.horizontal, rect.top + borderRadius.topRight.vertical, borderRadius.topRight.horizontal, borderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
839
- }
840
- ctx.lineTo(rect.left + rect.width, rect.top + rect.height - borderRadius.bottomRight.vertical);
841
- if (borderRadius.bottomRight.horizontal > 0 || borderRadius.bottomRight.vertical > 0) {
842
- ctx.ellipse(rect.left + rect.width - borderRadius.bottomRight.horizontal, rect.top + rect.height - borderRadius.bottomRight.vertical, borderRadius.bottomRight.horizontal, borderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
843
- }
844
- ctx.lineTo(rect.left + borderRadius.bottomLeft.horizontal, rect.top + rect.height);
845
- if (borderRadius.bottomLeft.horizontal > 0 || borderRadius.bottomLeft.vertical > 0) {
846
- ctx.ellipse(rect.left + borderRadius.bottomLeft.horizontal, rect.top + rect.height - borderRadius.bottomLeft.vertical, borderRadius.bottomLeft.horizontal, borderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
847
- }
848
- ctx.lineTo(rect.left, rect.top + borderRadius.topLeft.vertical);
849
- if (borderRadius.topLeft.horizontal > 0 || borderRadius.topLeft.vertical > 0) {
850
- ctx.ellipse(rect.left + borderRadius.topLeft.horizontal, rect.top + borderRadius.topLeft.vertical, borderRadius.topLeft.horizontal, borderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
851
- }
852
- ctx.closePath();
1164
+ drawRoundedRectPath({
1165
+ ctx,
1166
+ x: rect.left,
1167
+ y: rect.top,
1168
+ width: rect.width,
1169
+ height: rect.height,
1170
+ borderRadius
1171
+ });
853
1172
  ctx.clip();
854
1173
  return () => {
855
1174
  ctx.restore();
@@ -1193,6 +1512,107 @@ var drawBorder = ({
1193
1512
  ctx.setLineDash(originalLineDash);
1194
1513
  };
1195
1514
 
1515
+ // src/drawing/draw-box-shadow.ts
1516
+ import { Internals as Internals4 } from "remotion";
1517
+ var parseBoxShadow = (boxShadowValue) => {
1518
+ if (!boxShadowValue || boxShadowValue === "none") {
1519
+ return [];
1520
+ }
1521
+ const shadows = [];
1522
+ const shadowStrings = boxShadowValue.split(/,(?![^(]*\))/);
1523
+ for (const shadowStr of shadowStrings) {
1524
+ const trimmed = shadowStr.trim();
1525
+ if (!trimmed || trimmed === "none") {
1526
+ continue;
1527
+ }
1528
+ const shadow = {
1529
+ offsetX: 0,
1530
+ offsetY: 0,
1531
+ blurRadius: 0,
1532
+ color: "rgba(0, 0, 0, 0.5)",
1533
+ inset: false
1534
+ };
1535
+ shadow.inset = /\binset\b/i.test(trimmed);
1536
+ let remaining = trimmed.replace(/\binset\b/gi, "").trim();
1537
+ const colorMatch = remaining.match(/(rgba?\([^)]+\)|hsla?\([^)]+\)|#[0-9a-f]{3,8}|[a-z]+)/i);
1538
+ if (colorMatch) {
1539
+ shadow.color = colorMatch[0];
1540
+ remaining = remaining.replace(colorMatch[0], "").trim();
1541
+ }
1542
+ const numbers = remaining.match(/[+-]?\d*\.?\d+(?:px|em|rem|%)?/gi) || [];
1543
+ const values = numbers.map((n) => parseFloat(n) || 0);
1544
+ if (values.length >= 2) {
1545
+ shadow.offsetX = values[0];
1546
+ shadow.offsetY = values[1];
1547
+ if (values.length >= 3) {
1548
+ shadow.blurRadius = Math.max(0, values[2]);
1549
+ }
1550
+ }
1551
+ shadows.push(shadow);
1552
+ }
1553
+ return shadows;
1554
+ };
1555
+ var setBoxShadow = ({
1556
+ ctx,
1557
+ rect,
1558
+ borderRadius,
1559
+ computedStyle,
1560
+ logLevel
1561
+ }) => {
1562
+ const shadows = parseBoxShadow(computedStyle.boxShadow);
1563
+ if (shadows.length === 0) {
1564
+ return;
1565
+ }
1566
+ for (let i = shadows.length - 1;i >= 0; i--) {
1567
+ const shadow = shadows[i];
1568
+ const newLeft = rect.left + Math.min(shadow.offsetX, 0) - shadow.blurRadius;
1569
+ const newRight = rect.right + Math.max(shadow.offsetX, 0) + shadow.blurRadius;
1570
+ const newTop = rect.top + Math.min(shadow.offsetY, 0) - shadow.blurRadius;
1571
+ const newBottom = rect.bottom + Math.max(shadow.offsetY, 0) + shadow.blurRadius;
1572
+ const newRect = new DOMRect(newLeft, newTop, newRight - newLeft, newBottom - newTop);
1573
+ const leftOffset = rect.left - newLeft;
1574
+ const topOffset = rect.top - newTop;
1575
+ const newCanvas = new OffscreenCanvas(newRect.width, newRect.height);
1576
+ const newCtx = newCanvas.getContext("2d");
1577
+ if (!newCtx) {
1578
+ throw new Error("Failed to get context");
1579
+ }
1580
+ if (shadow.inset) {
1581
+ Internals4.Log.warn({
1582
+ logLevel,
1583
+ tag: "@remotion/web-renderer"
1584
+ }, 'Detected "box-shadow" with "inset". This is not yet supported in @remotion/web-renderer');
1585
+ continue;
1586
+ }
1587
+ newCtx.shadowBlur = shadow.blurRadius;
1588
+ newCtx.shadowColor = shadow.color;
1589
+ newCtx.shadowOffsetX = shadow.offsetX;
1590
+ newCtx.shadowOffsetY = shadow.offsetY;
1591
+ newCtx.fillStyle = "black";
1592
+ drawRoundedRectPath({
1593
+ ctx: newCtx,
1594
+ x: leftOffset,
1595
+ y: topOffset,
1596
+ width: rect.width,
1597
+ height: rect.height,
1598
+ borderRadius
1599
+ });
1600
+ newCtx.fill();
1601
+ newCtx.shadowColor = "transparent";
1602
+ newCtx.globalCompositeOperation = "destination-out";
1603
+ drawRoundedRectPath({
1604
+ ctx: newCtx,
1605
+ x: leftOffset,
1606
+ y: topOffset,
1607
+ width: rect.width,
1608
+ height: rect.height,
1609
+ borderRadius
1610
+ });
1611
+ newCtx.fill();
1612
+ ctx.drawImage(newCanvas, rect.left - leftOffset, rect.top - topOffset);
1613
+ }
1614
+ };
1615
+
1196
1616
  // src/drawing/draw-outline.ts
1197
1617
  var parseOutlineWidth = (value) => {
1198
1618
  return parseFloat(value) || 0;
@@ -1225,7 +1645,6 @@ var drawOutline = ({
1225
1645
  const originalStrokeStyle = ctx.strokeStyle;
1226
1646
  const originalLineWidth = ctx.lineWidth;
1227
1647
  const originalLineDash = ctx.getLineDash();
1228
- ctx.beginPath();
1229
1648
  ctx.strokeStyle = outlineColor;
1230
1649
  ctx.lineWidth = outlineWidth;
1231
1650
  ctx.setLineDash(getLineDashPattern2(outlineStyle, outlineWidth));
@@ -1253,24 +1672,14 @@ var drawOutline = ({
1253
1672
  vertical: borderRadius.bottomLeft.vertical === 0 ? 0 : Math.max(0, borderRadius.bottomLeft.vertical + offset)
1254
1673
  }
1255
1674
  };
1256
- ctx.moveTo(outlineX + adjustedBorderRadius.topLeft.horizontal, outlineY);
1257
- ctx.lineTo(outlineX + outlineW - adjustedBorderRadius.topRight.horizontal, outlineY);
1258
- if (adjustedBorderRadius.topRight.horizontal > 0 || adjustedBorderRadius.topRight.vertical > 0) {
1259
- ctx.ellipse(outlineX + outlineW - adjustedBorderRadius.topRight.horizontal, outlineY + adjustedBorderRadius.topRight.vertical, adjustedBorderRadius.topRight.horizontal, adjustedBorderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
1260
- }
1261
- ctx.lineTo(outlineX + outlineW, outlineY + outlineH - adjustedBorderRadius.bottomRight.vertical);
1262
- if (adjustedBorderRadius.bottomRight.horizontal > 0 || adjustedBorderRadius.bottomRight.vertical > 0) {
1263
- ctx.ellipse(outlineX + outlineW - adjustedBorderRadius.bottomRight.horizontal, outlineY + outlineH - adjustedBorderRadius.bottomRight.vertical, adjustedBorderRadius.bottomRight.horizontal, adjustedBorderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
1264
- }
1265
- ctx.lineTo(outlineX + adjustedBorderRadius.bottomLeft.horizontal, outlineY + outlineH);
1266
- if (adjustedBorderRadius.bottomLeft.horizontal > 0 || adjustedBorderRadius.bottomLeft.vertical > 0) {
1267
- ctx.ellipse(outlineX + adjustedBorderRadius.bottomLeft.horizontal, outlineY + outlineH - adjustedBorderRadius.bottomLeft.vertical, adjustedBorderRadius.bottomLeft.horizontal, adjustedBorderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
1268
- }
1269
- ctx.lineTo(outlineX, outlineY + adjustedBorderRadius.topLeft.vertical);
1270
- if (adjustedBorderRadius.topLeft.horizontal > 0 || adjustedBorderRadius.topLeft.vertical > 0) {
1271
- ctx.ellipse(outlineX + adjustedBorderRadius.topLeft.horizontal, outlineY + adjustedBorderRadius.topLeft.vertical, adjustedBorderRadius.topLeft.horizontal, adjustedBorderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
1272
- }
1273
- ctx.closePath();
1675
+ drawRoundedRectPath({
1676
+ ctx,
1677
+ x: outlineX,
1678
+ y: outlineY,
1679
+ width: outlineW,
1680
+ height: outlineH,
1681
+ borderRadius: adjustedBorderRadius
1682
+ });
1274
1683
  ctx.stroke();
1275
1684
  ctx.strokeStyle = originalStrokeStyle;
1276
1685
  ctx.lineWidth = originalLineWidth;
@@ -1310,9 +1719,11 @@ var setOverflowHidden = ({
1310
1719
  // src/drawing/transform.ts
1311
1720
  var setTransform = ({
1312
1721
  ctx,
1313
- transform
1722
+ transform,
1723
+ parentRect
1314
1724
  }) => {
1315
- ctx.setTransform(transform);
1725
+ const offsetMatrix = new DOMMatrix().translate(-parentRect.x, -parentRect.y).multiply(transform).translate(parentRect.x, parentRect.y);
1726
+ ctx.setTransform(offsetMatrix);
1316
1727
  return () => {
1317
1728
  ctx.setTransform(new DOMMatrix);
1318
1729
  };
@@ -1325,9 +1736,12 @@ var drawElement = async ({
1325
1736
  context,
1326
1737
  draw,
1327
1738
  opacity,
1328
- totalMatrix
1739
+ totalMatrix,
1740
+ parentRect,
1741
+ logLevel
1329
1742
  }) => {
1330
1743
  const background = computedStyle.backgroundColor;
1744
+ const { backgroundImage } = computedStyle;
1331
1745
  const borderRadius = parseBorderRadius({
1332
1746
  borderRadius: computedStyle.borderRadius,
1333
1747
  width: rect.width,
@@ -1335,19 +1749,43 @@ var drawElement = async ({
1335
1749
  });
1336
1750
  const finishTransform = setTransform({
1337
1751
  ctx: context,
1338
- transform: totalMatrix
1752
+ transform: totalMatrix,
1753
+ parentRect
1339
1754
  });
1340
- const finishBorderRadius = setBorderRadius({
1755
+ const finishOpacity = setOpacity({
1341
1756
  ctx: context,
1757
+ opacity
1758
+ });
1759
+ setBoxShadow({
1760
+ ctx: context,
1761
+ computedStyle,
1342
1762
  rect,
1343
1763
  borderRadius,
1344
- forceClipEvenWhenZero: false
1764
+ logLevel
1345
1765
  });
1346
- const finishOpacity = setOpacity({
1766
+ const finishBorderRadius = setBorderRadius({
1347
1767
  ctx: context,
1348
- opacity
1768
+ rect,
1769
+ borderRadius,
1770
+ forceClipEvenWhenZero: false
1349
1771
  });
1350
- if (background && background !== "transparent" && !(background.startsWith("rgba") && (background.endsWith(", 0)") || background.endsWith(",0")))) {
1772
+ let gradientDrawn = false;
1773
+ if (backgroundImage && backgroundImage !== "none") {
1774
+ const gradientInfo = parseLinearGradient(backgroundImage);
1775
+ if (gradientInfo) {
1776
+ const gradient = createCanvasGradient({
1777
+ ctx: context,
1778
+ rect,
1779
+ gradientInfo
1780
+ });
1781
+ const originalFillStyle = context.fillStyle;
1782
+ context.fillStyle = gradient;
1783
+ context.fillRect(rect.left, rect.top, rect.width, rect.height);
1784
+ context.fillStyle = originalFillStyle;
1785
+ gradientDrawn = true;
1786
+ }
1787
+ }
1788
+ if (!gradientDrawn && background && background !== "transparent" && !(background.startsWith("rgba") && (background.endsWith(", 0)") || background.endsWith(",0")))) {
1351
1789
  const originalFillStyle = context.fillStyle;
1352
1790
  context.fillStyle = background;
1353
1791
  context.fillRect(rect.left, rect.top, rect.width, rect.height);
@@ -1382,9 +1820,6 @@ var drawElement = async ({
1382
1820
  };
1383
1821
  };
1384
1822
 
1385
- // src/drawing/handle-3d-transform.ts
1386
- import { Internals as Internals4 } from "remotion";
1387
-
1388
1823
  // src/walk-tree.ts
1389
1824
  function skipToNextNonDescendant(treeWalker) {
1390
1825
  if (treeWalker.nextSibling()) {
@@ -1410,10 +1845,23 @@ var getBiggestBoundingClientRect = (element) => {
1410
1845
  const outlineWidth = parseOutlineWidth(computedStyle.outlineWidth);
1411
1846
  const outlineOffset = parseOutlineOffset(computedStyle.outlineOffset);
1412
1847
  const rect = treeWalker.currentNode.getBoundingClientRect();
1413
- mostLeft = Math.min(mostLeft, rect.left - outlineOffset - outlineWidth);
1414
- mostTop = Math.min(mostTop, rect.top - outlineOffset - outlineWidth);
1415
- mostRight = Math.max(mostRight, rect.right + outlineOffset + outlineWidth);
1416
- mostBottom = Math.max(mostBottom, rect.bottom + outlineOffset + outlineWidth);
1848
+ const shadows = parseBoxShadow(computedStyle.boxShadow);
1849
+ let shadowLeft = 0;
1850
+ let shadowRight = 0;
1851
+ let shadowTop = 0;
1852
+ let shadowBottom = 0;
1853
+ for (const shadow of shadows) {
1854
+ if (!shadow.inset) {
1855
+ shadowLeft = Math.max(shadowLeft, Math.abs(Math.min(shadow.offsetX, 0)) + shadow.blurRadius);
1856
+ shadowRight = Math.max(shadowRight, Math.max(shadow.offsetX, 0) + shadow.blurRadius);
1857
+ shadowTop = Math.max(shadowTop, Math.abs(Math.min(shadow.offsetY, 0)) + shadow.blurRadius);
1858
+ shadowBottom = Math.max(shadowBottom, Math.max(shadow.offsetY, 0) + shadow.blurRadius);
1859
+ }
1860
+ }
1861
+ mostLeft = Math.min(mostLeft, rect.left - outlineOffset - outlineWidth - shadowLeft);
1862
+ mostTop = Math.min(mostTop, rect.top - outlineOffset - outlineWidth - shadowTop);
1863
+ mostRight = Math.max(mostRight, rect.right + outlineOffset + outlineWidth + shadowRight);
1864
+ mostBottom = Math.max(mostBottom, rect.bottom + outlineOffset + outlineWidth + shadowBottom);
1417
1865
  if (computedStyle.overflow === "hidden") {
1418
1866
  if (!skipToNextNonDescendant(treeWalker)) {
1419
1867
  break;
@@ -1426,18 +1874,6 @@ var getBiggestBoundingClientRect = (element) => {
1426
1874
  return new DOMRect(mostLeft, mostTop, mostRight - mostLeft, mostBottom - mostTop);
1427
1875
  };
1428
1876
 
1429
- // src/drawing/clamp-rect-to-parent-bounds.ts
1430
- var getNarrowerRect = ({
1431
- firstRect,
1432
- secondRect
1433
- }) => {
1434
- const left = Math.max(firstRect.left, secondRect.left);
1435
- const top = Math.max(firstRect.top, secondRect.top);
1436
- const bottom = Math.min(firstRect.bottom, secondRect.bottom);
1437
- const right = Math.min(firstRect.right, secondRect.right);
1438
- return new DOMRect(left, top, right - left, bottom - top);
1439
- };
1440
-
1441
1877
  // src/drawing/get-pretransform-rect.ts
1442
1878
  function getPreTransformRect(targetRect, matrix) {
1443
1879
  const origin = new DOMPoint(0, 0).matrixTransform(matrix);
@@ -1454,6 +1890,10 @@ function getPreTransformRect(targetRect, matrix) {
1454
1890
  origin.y
1455
1891
  ]);
1456
1892
  const inverse2D = effective2D.inverse();
1893
+ const wasNotInvertible = isNaN(inverse2D.m11);
1894
+ if (wasNotInvertible) {
1895
+ return new DOMRect(0, 0, 0, 0);
1896
+ }
1457
1897
  const corners = [
1458
1898
  new DOMPoint(targetRect.x, targetRect.y),
1459
1899
  new DOMPoint(targetRect.x + targetRect.width, targetRect.y),
@@ -1466,26 +1906,6 @@ function getPreTransformRect(targetRect, matrix) {
1466
1906
  return new DOMRect(Math.min(...xs), Math.min(...ys), Math.max(...xs) - Math.min(...xs), Math.max(...ys) - Math.min(...ys));
1467
1907
  }
1468
1908
 
1469
- // src/drawing/transform-rect-with-matrix.ts
1470
- function transformDOMRect({
1471
- rect,
1472
- matrix
1473
- }) {
1474
- const topLeft = new DOMPointReadOnly(rect.left, rect.top);
1475
- const topRight = new DOMPointReadOnly(rect.right, rect.top);
1476
- const bottomLeft = new DOMPointReadOnly(rect.left, rect.bottom);
1477
- const bottomRight = new DOMPointReadOnly(rect.right, rect.bottom);
1478
- const transformedTopLeft = topLeft.matrixTransform(matrix);
1479
- const transformedTopRight = topRight.matrixTransform(matrix);
1480
- const transformedBottomLeft = bottomLeft.matrixTransform(matrix);
1481
- const transformedBottomRight = bottomRight.matrixTransform(matrix);
1482
- const minX = Math.min(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
1483
- const maxX = Math.max(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
1484
- const minY = Math.min(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
1485
- const maxY = Math.max(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
1486
- return new DOMRect(minX, minY, maxX - minX, maxY - minY);
1487
- }
1488
-
1489
1909
  // src/drawing/transform-in-3d.ts
1490
1910
  function compileShader(shaderGl, source, type) {
1491
1911
  const shader = shaderGl.createShader(type);
@@ -1501,24 +1921,14 @@ function compileShader(shaderGl, source, type) {
1501
1921
  }
1502
1922
  return shader;
1503
1923
  }
1504
- var helperCanvas = null;
1505
1924
  var createHelperCanvas = ({
1506
1925
  canvasWidth,
1507
1926
  canvasHeight
1508
1927
  }) => {
1509
- if (helperCanvas && helperCanvas.canvas.width >= canvasWidth && helperCanvas.canvas.height >= canvasHeight) {
1510
- helperCanvas.gl.clearColor(0, 0, 0, 0);
1511
- helperCanvas.gl.clear(helperCanvas.gl.COLOR_BUFFER_BIT);
1512
- return helperCanvas;
1513
- }
1514
- if (helperCanvas) {
1515
- helperCanvas.gl.deleteProgram(helperCanvas.program);
1516
- helperCanvas.gl.deleteShader(helperCanvas.vertexShader);
1517
- helperCanvas.gl.deleteShader(helperCanvas.fragmentShader);
1518
- helperCanvas = null;
1519
- }
1520
1928
  const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);
1521
- const gl = canvas.getContext("webgl");
1929
+ const gl = canvas.getContext("webgl", {
1930
+ premultipliedAlpha: true
1931
+ });
1522
1932
  if (!gl) {
1523
1933
  throw new Error("WebGL not supported");
1524
1934
  }
@@ -1557,21 +1967,17 @@ var createHelperCanvas = ({
1557
1967
  gl.clear(gl.COLOR_BUFFER_BIT);
1558
1968
  gl.enable(gl.BLEND);
1559
1969
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
1560
- helperCanvas = { canvas, gl, program, vertexShader, fragmentShader };
1561
- return helperCanvas;
1970
+ return { canvas, gl, program, vertexShader, fragmentShader };
1562
1971
  };
1563
1972
  var transformIn3d = ({
1564
1973
  matrix,
1565
1974
  sourceCanvas,
1566
- untransformedRect
1975
+ untransformedRect,
1976
+ rectAfterTransforms
1567
1977
  }) => {
1568
- const rectAfterTransforms = transformDOMRect({
1569
- rect: untransformedRect,
1570
- matrix
1571
- });
1572
1978
  const { canvas, gl, program } = createHelperCanvas({
1573
- canvasWidth: Math.ceil(rectAfterTransforms.width),
1574
- canvasHeight: Math.ceil(rectAfterTransforms.height)
1979
+ canvasWidth: rectAfterTransforms.width,
1980
+ canvasHeight: rectAfterTransforms.height
1575
1981
  });
1576
1982
  const vertexBuffer = gl.createBuffer();
1577
1983
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
@@ -1614,7 +2020,10 @@ var transformIn3d = ({
1614
2020
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
1615
2021
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
1616
2022
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
2023
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
1617
2024
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceCanvas);
2025
+ gl.enable(gl.BLEND);
2026
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
1618
2027
  const transformMatrix = matrix.toFloat32Array();
1619
2028
  const zScale = 1e9;
1620
2029
  const projectionMatrix = new Float32Array([
@@ -1642,19 +2051,31 @@ var transformIn3d = ({
1642
2051
  gl.uniformMatrix4fv(uProjection, false, projectionMatrix);
1643
2052
  gl.uniform1i(uTexture, 0);
1644
2053
  gl.drawArrays(gl.TRIANGLES, 0, 6);
2054
+ gl.disableVertexAttribArray(aPosition);
2055
+ gl.disableVertexAttribArray(aTexCoord);
1645
2056
  gl.deleteTexture(texture);
1646
2057
  gl.deleteBuffer(vertexBuffer);
1647
- return { canvas, rect: rectAfterTransforms };
2058
+ gl.bindTexture(gl.TEXTURE_2D, null);
2059
+ gl.deleteTexture(texture);
2060
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
2061
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
2062
+ return {
2063
+ canvas,
2064
+ rect: rectAfterTransforms,
2065
+ cleanup: () => {
2066
+ const loseContext = gl.getExtension("WEBGL_lose_context");
2067
+ if (loseContext) {
2068
+ loseContext.loseContext();
2069
+ }
2070
+ }
2071
+ };
1648
2072
  };
1649
2073
 
1650
2074
  // src/drawing/handle-3d-transform.ts
1651
- var handle3dTransform = async ({
2075
+ var getPrecomposeRectFor3DTransform = ({
1652
2076
  element,
1653
- matrix,
1654
2077
  parentRect,
1655
- context,
1656
- logLevel,
1657
- internalState
2078
+ matrix
1658
2079
  }) => {
1659
2080
  const unclampedBiggestBoundingClientRect = getBiggestBoundingClientRect(element);
1660
2081
  const biggestPossiblePretransformRect = getPreTransformRect(parentRect, matrix);
@@ -1662,33 +2083,93 @@ var handle3dTransform = async ({
1662
2083
  firstRect: unclampedBiggestBoundingClientRect,
1663
2084
  secondRect: biggestPossiblePretransformRect
1664
2085
  });
1665
- const start = Date.now();
1666
- const tempCanvas = new OffscreenCanvas(Math.ceil(preTransformRect.width), Math.ceil(preTransformRect.height));
2086
+ return preTransformRect;
2087
+ };
2088
+ var handle3dTransform = ({
2089
+ matrix,
2090
+ precomposeRect,
2091
+ tempCanvas,
2092
+ rectAfterTransforms
2093
+ }) => {
2094
+ const {
2095
+ canvas: transformed,
2096
+ rect: transformedRect,
2097
+ cleanup
2098
+ } = transformIn3d({
2099
+ untransformedRect: precomposeRect,
2100
+ matrix,
2101
+ sourceCanvas: tempCanvas,
2102
+ rectAfterTransforms
2103
+ });
2104
+ if (transformedRect.width <= 0 || transformedRect.height <= 0) {
2105
+ return null;
2106
+ }
2107
+ return [transformed, cleanup];
2108
+ };
2109
+
2110
+ // src/drawing/handle-mask.ts
2111
+ var getPrecomposeRectForMask = (element) => {
2112
+ const boundingRect = getBiggestBoundingClientRect(element);
2113
+ return boundingRect;
2114
+ };
2115
+ var handleMask = ({
2116
+ gradientInfo,
2117
+ rect,
2118
+ precomposeRect,
2119
+ tempContext
2120
+ }) => {
2121
+ const rectOffsetX = rect.left - precomposeRect.left;
2122
+ const rectOffsetY = rect.top - precomposeRect.top;
2123
+ const rectToFill = new DOMRect(rectOffsetX, rectOffsetY, rect.width, rect.height);
2124
+ const gradient = createCanvasGradient({
2125
+ ctx: tempContext,
2126
+ rect: rectToFill,
2127
+ gradientInfo
2128
+ });
2129
+ tempContext.globalCompositeOperation = "destination-in";
2130
+ tempContext.fillStyle = gradient;
2131
+ tempContext.fillRect(rectToFill.left, rectToFill.top, rectToFill.width, rectToFill.height);
2132
+ };
2133
+
2134
+ // src/drawing/precompose.ts
2135
+ var precomposeDOMElement = async ({
2136
+ boundingRect,
2137
+ element,
2138
+ logLevel,
2139
+ internalState
2140
+ }) => {
2141
+ const tempCanvas = new OffscreenCanvas(boundingRect.width, boundingRect.height);
2142
+ const tempContext = tempCanvas.getContext("2d");
1667
2143
  await compose({
1668
2144
  element,
1669
- context: tempCanvas.getContext("2d"),
2145
+ context: tempContext,
1670
2146
  logLevel,
1671
- parentRect: preTransformRect,
2147
+ parentRect: boundingRect,
1672
2148
  internalState
1673
2149
  });
1674
- const afterCompose = Date.now();
1675
- const { canvas: transformed, rect: transformedRect } = transformIn3d({
1676
- untransformedRect: preTransformRect,
1677
- matrix,
1678
- sourceCanvas: tempCanvas
1679
- });
1680
- context.drawImage(transformed, transformedRect.x, transformedRect.y);
1681
- const afterDraw = Date.now();
1682
- Internals4.Log.trace({
1683
- logLevel,
1684
- tag: "@remotion/web-renderer"
1685
- }, `Transforming element in 3D - canvas size: ${transformedRect.width}x${transformedRect.height} - compose: ${afterCompose - start}ms - draw: ${afterDraw - afterCompose}ms`);
1686
- internalState.add3DTransform({
1687
- canvasWidth: Math.ceil(transformedRect.width),
1688
- canvasHeight: Math.ceil(transformedRect.height)
1689
- });
2150
+ return { tempCanvas, tempContext };
1690
2151
  };
1691
2152
 
2153
+ // src/drawing/transform-rect-with-matrix.ts
2154
+ function transformDOMRect({
2155
+ rect,
2156
+ matrix
2157
+ }) {
2158
+ const topLeft = new DOMPointReadOnly(rect.left, rect.top);
2159
+ const topRight = new DOMPointReadOnly(rect.right, rect.top);
2160
+ const bottomLeft = new DOMPointReadOnly(rect.left, rect.bottom);
2161
+ const bottomRight = new DOMPointReadOnly(rect.right, rect.bottom);
2162
+ const transformedTopLeft = topLeft.matrixTransform(matrix);
2163
+ const transformedTopRight = topRight.matrixTransform(matrix);
2164
+ const transformedBottomLeft = bottomLeft.matrixTransform(matrix);
2165
+ const transformedBottomRight = bottomRight.matrixTransform(matrix);
2166
+ const minX = Math.min(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
2167
+ const maxX = Math.max(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
2168
+ const minY = Math.min(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
2169
+ const maxY = Math.max(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
2170
+ return new DOMRect(minX, minY, maxX - minX, maxY - minY);
2171
+ }
2172
+
1692
2173
  // src/drawing/process-node.ts
1693
2174
  var processNode = async ({
1694
2175
  element,
@@ -1696,48 +2177,124 @@ var processNode = async ({
1696
2177
  draw,
1697
2178
  logLevel,
1698
2179
  parentRect,
1699
- internalState
2180
+ internalState,
2181
+ rootElement
1700
2182
  }) => {
1701
- const transforms = calculateTransforms({
2183
+ const {
2184
+ totalMatrix,
2185
+ reset,
2186
+ dimensions,
2187
+ opacity,
2188
+ computedStyle,
2189
+ precompositing
2190
+ } = calculateTransforms({
1702
2191
  element,
1703
- offsetLeft: parentRect.x,
1704
- offsetTop: parentRect.y
2192
+ rootElement
1705
2193
  });
1706
- const { totalMatrix, reset, dimensions, opacity, computedStyle } = transforms;
1707
2194
  if (opacity === 0) {
1708
2195
  reset();
1709
- return { type: "continue", cleanupAfterChildren: () => {} };
2196
+ return { type: "skip-children" };
1710
2197
  }
1711
2198
  if (dimensions.width <= 0 || dimensions.height <= 0) {
1712
2199
  reset();
1713
- return { type: "continue", cleanupAfterChildren: () => {} };
1714
- }
1715
- if (!totalMatrix.is2D) {
1716
- await handle3dTransform({
2200
+ return { type: "continue", cleanupAfterChildren: null };
2201
+ }
2202
+ const rect = new DOMRect(dimensions.left - parentRect.x, dimensions.top - parentRect.y, dimensions.width, dimensions.height);
2203
+ if (precompositing.needsPrecompositing) {
2204
+ const start = Date.now();
2205
+ let precomposeRect = null;
2206
+ if (precompositing.needsMaskImage) {
2207
+ precomposeRect = getWiderRectAndExpand({
2208
+ firstRect: precomposeRect,
2209
+ secondRect: getPrecomposeRectForMask(element)
2210
+ });
2211
+ }
2212
+ if (precompositing.needs3DTransformViaWebGL) {
2213
+ precomposeRect = getWiderRectAndExpand({
2214
+ firstRect: precomposeRect,
2215
+ secondRect: getPrecomposeRectFor3DTransform({
2216
+ element,
2217
+ parentRect,
2218
+ matrix: totalMatrix
2219
+ })
2220
+ });
2221
+ }
2222
+ if (!precomposeRect) {
2223
+ throw new Error("Precompose rect not found");
2224
+ }
2225
+ if (precomposeRect.width <= 0 || precomposeRect.height <= 0) {
2226
+ return { type: "continue", cleanupAfterChildren: null };
2227
+ }
2228
+ if (!doRectsIntersect(precomposeRect, parentRect)) {
2229
+ return { type: "continue", cleanupAfterChildren: null };
2230
+ }
2231
+ const { tempCanvas, tempContext } = await precomposeDOMElement({
2232
+ boundingRect: precomposeRect,
1717
2233
  element,
1718
- matrix: totalMatrix,
1719
- parentRect,
1720
- context,
1721
2234
  logLevel,
1722
2235
  internalState
1723
2236
  });
2237
+ let drawable = tempCanvas;
2238
+ let cleanupWebGL = () => {};
2239
+ const rectAfterTransforms = roundToExpandRect(transformDOMRect({
2240
+ rect: precomposeRect,
2241
+ matrix: totalMatrix
2242
+ }));
2243
+ if (precompositing.needsMaskImage) {
2244
+ handleMask({
2245
+ gradientInfo: precompositing.needsMaskImage,
2246
+ rect,
2247
+ precomposeRect,
2248
+ tempContext
2249
+ });
2250
+ }
2251
+ if (precompositing.needs3DTransformViaWebGL) {
2252
+ const t = handle3dTransform({
2253
+ matrix: totalMatrix,
2254
+ precomposeRect,
2255
+ tempCanvas: drawable,
2256
+ rectAfterTransforms
2257
+ });
2258
+ if (t) {
2259
+ const [transformed, cleanup] = t;
2260
+ drawable = transformed;
2261
+ cleanupWebGL = cleanup;
2262
+ }
2263
+ }
2264
+ const previousTransform = context.getTransform();
2265
+ if (drawable) {
2266
+ context.setTransform(new DOMMatrix);
2267
+ context.drawImage(drawable, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
2268
+ context.setTransform(previousTransform);
2269
+ Internals5.Log.trace({
2270
+ logLevel,
2271
+ tag: "@remotion/web-renderer"
2272
+ }, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms`);
2273
+ internalState.addPrecompose({
2274
+ canvasWidth: precomposeRect.width,
2275
+ canvasHeight: precomposeRect.height
2276
+ });
2277
+ }
1724
2278
  reset();
2279
+ cleanupWebGL();
1725
2280
  return { type: "skip-children" };
1726
2281
  }
1727
2282
  const { cleanupAfterChildren } = await drawElement({
1728
- rect: new DOMRect(dimensions.left - parentRect.x, dimensions.top - parentRect.y, dimensions.width, dimensions.height),
2283
+ rect,
1729
2284
  computedStyle,
1730
2285
  context,
1731
2286
  draw,
1732
2287
  opacity,
1733
- totalMatrix
2288
+ totalMatrix,
2289
+ parentRect,
2290
+ logLevel
1734
2291
  });
1735
2292
  reset();
1736
2293
  return { type: "continue", cleanupAfterChildren };
1737
2294
  };
1738
2295
 
1739
2296
  // src/drawing/text/draw-text.ts
1740
- import { Internals as Internals5 } from "remotion";
2297
+ import { Internals as Internals6 } from "remotion";
1741
2298
 
1742
2299
  // src/drawing/text/apply-text-transform.ts
1743
2300
  var applyTextTransform = (text, transform) => {
@@ -1827,7 +2384,7 @@ function findLineBreaks(span, rtl) {
1827
2384
  const shouldCollapse = !computedStyle.whiteSpaceCollapse.includes("preserve");
1828
2385
  lines.push({
1829
2386
  text: shouldCollapse ? currentLine.trim() : currentLine,
1830
- offsetTop: currentHeight - previousRect.height,
2387
+ height: currentHeight - previousRect.height,
1831
2388
  offsetHorizontal
1832
2389
  });
1833
2390
  currentLine = wordsToAdd;
@@ -1843,7 +2400,7 @@ function findLineBreaks(span, rtl) {
1843
2400
  const offsetHorizontal = rtl ? lastRect.right - originalRect.right : lastRect.left - originalRect.left;
1844
2401
  lines.push({
1845
2402
  text: currentLine,
1846
- offsetTop: rect.height - previousRect.height,
2403
+ height: rect.height - lines.reduce((acc, curr) => acc + curr.height, 0),
1847
2404
  offsetHorizontal
1848
2405
  });
1849
2406
  }
@@ -1852,7 +2409,10 @@ function findLineBreaks(span, rtl) {
1852
2409
  }
1853
2410
 
1854
2411
  // src/drawing/text/draw-text.ts
1855
- var drawText = (span) => {
2412
+ var drawText = ({
2413
+ span,
2414
+ logLevel
2415
+ }) => {
1856
2416
  const drawFn = ({ dimensions: rect, computedStyle, contextToDraw }) => {
1857
2417
  const {
1858
2418
  fontFamily,
@@ -1866,8 +2426,8 @@ var drawText = (span) => {
1866
2426
  } = computedStyle;
1867
2427
  const isVertical = writingMode !== "horizontal-tb";
1868
2428
  if (isVertical) {
1869
- Internals5.Log.warn({
1870
- logLevel: "warn",
2429
+ Internals6.Log.warn({
2430
+ logLevel,
1871
2431
  tag: "@remotion/web-renderer"
1872
2432
  }, 'Detected "writing-mode" CSS property. Vertical text is not yet supported in @remotion/web-renderer');
1873
2433
  return;
@@ -1887,10 +2447,14 @@ var drawText = (span) => {
1887
2447
  const xPosition = isRTL ? rect.right : rect.left;
1888
2448
  const lines = findLineBreaks(span, isRTL);
1889
2449
  let offsetTop = 0;
1890
- const { fontBoundingBoxAscent } = contextToDraw.measureText(lines[0].text);
2450
+ const measurements = contextToDraw.measureText(lines[0].text);
2451
+ const { fontBoundingBoxDescent, fontBoundingBoxAscent } = measurements;
2452
+ const fontHeight = fontBoundingBoxAscent + fontBoundingBoxDescent;
1891
2453
  for (const line of lines) {
1892
- contextToDraw.fillText(line.text, xPosition + line.offsetHorizontal, rect.top + offsetTop + fontBoundingBoxAscent);
1893
- offsetTop += line.offsetTop;
2454
+ const leading = line.height - fontHeight;
2455
+ const halfLeading = leading / 2;
2456
+ contextToDraw.fillText(line.text, xPosition + line.offsetHorizontal, rect.top + halfLeading + fontBoundingBoxAscent + offsetTop);
2457
+ offsetTop += line.height;
1894
2458
  }
1895
2459
  span.textContent = originalText;
1896
2460
  contextToDraw.restore();
@@ -1904,7 +2468,8 @@ var handleTextNode = async ({
1904
2468
  context,
1905
2469
  logLevel,
1906
2470
  parentRect,
1907
- internalState
2471
+ internalState,
2472
+ rootElement
1908
2473
  }) => {
1909
2474
  const span = document.createElement("span");
1910
2475
  const parent = node.parentNode;
@@ -1916,10 +2481,11 @@ var handleTextNode = async ({
1916
2481
  const value = await processNode({
1917
2482
  context,
1918
2483
  element: span,
1919
- draw: drawText(span),
2484
+ draw: drawText({ span, logLevel }),
1920
2485
  logLevel,
1921
2486
  parentRect,
1922
- internalState
2487
+ internalState,
2488
+ rootElement
1923
2489
  });
1924
2490
  parent.insertBefore(node, span);
1925
2491
  parent.removeChild(span);
@@ -1932,7 +2498,8 @@ var walkOverNode = ({
1932
2498
  context,
1933
2499
  logLevel,
1934
2500
  parentRect,
1935
- internalState
2501
+ internalState,
2502
+ rootElement
1936
2503
  }) => {
1937
2504
  if (node instanceof HTMLElement || node instanceof SVGElement) {
1938
2505
  return processNode({
@@ -1941,7 +2508,8 @@ var walkOverNode = ({
1941
2508
  draw: drawDomElement(node),
1942
2509
  logLevel,
1943
2510
  parentRect,
1944
- internalState
2511
+ internalState,
2512
+ rootElement
1945
2513
  });
1946
2514
  }
1947
2515
  if (node instanceof Text) {
@@ -1950,7 +2518,8 @@ var walkOverNode = ({
1950
2518
  context,
1951
2519
  logLevel,
1952
2520
  parentRect,
1953
- internalState
2521
+ internalState,
2522
+ rootElement
1954
2523
  });
1955
2524
  }
1956
2525
  throw new Error("Unknown node type");
@@ -1988,17 +2557,20 @@ var compose = async ({
1988
2557
  context,
1989
2558
  logLevel,
1990
2559
  parentRect,
1991
- internalState
2560
+ internalState,
2561
+ rootElement: element
1992
2562
  });
1993
2563
  if (val.type === "skip-children") {
1994
2564
  if (!skipToNextNonDescendant(treeWalker)) {
1995
2565
  break;
1996
2566
  }
1997
2567
  } else {
1998
- cleanupAfterChildren.push({
1999
- element: treeWalker.currentNode,
2000
- cleanupFn: val.cleanupAfterChildren
2001
- });
2568
+ if (val.cleanupAfterChildren) {
2569
+ cleanupAfterChildren.unshift({
2570
+ element: treeWalker.currentNode,
2571
+ cleanupFn: val.cleanupAfterChildren
2572
+ });
2573
+ }
2002
2574
  if (!treeWalker.nextNode()) {
2003
2575
  break;
2004
2576
  }
@@ -2215,7 +2787,8 @@ var internalRenderMediaOnWeb = async ({
2215
2787
  onArtifact,
2216
2788
  onFrame,
2217
2789
  outputTarget: userDesiredOutputTarget,
2218
- licenseKey
2790
+ licenseKey,
2791
+ muted
2219
2792
  }) => {
2220
2793
  const outputTarget = userDesiredOutputTarget === null ? await canUseWebFsWriter() ? "web-fs" : "arraybuffer" : userDesiredOutputTarget;
2221
2794
  if (outputTarget === "web-fs") {
@@ -2226,7 +2799,7 @@ var internalRenderMediaOnWeb = async ({
2226
2799
  if (codec && !format.getSupportedCodecs().includes(codecToMediabunnyCodec(codec))) {
2227
2800
  return Promise.reject(new Error(`Codec ${codec} is not supported for container ${container}`));
2228
2801
  }
2229
- const resolved = await Internals6.resolveVideoConfig({
2802
+ const resolved = await Internals7.resolveVideoConfig({
2230
2803
  calculateMetadata: composition.calculateMetadata ?? null,
2231
2804
  signal: signal ?? new AbortController().signal,
2232
2805
  defaultProps: composition.defaultProps ?? {},
@@ -2253,7 +2826,7 @@ var internalRenderMediaOnWeb = async ({
2253
2826
  logLevel,
2254
2827
  mediaCacheSizeInBytes,
2255
2828
  schema: schema ?? null,
2256
- audioEnabled: true,
2829
+ audioEnabled: !muted,
2257
2830
  videoEnabled: true,
2258
2831
  initialFrame: 0,
2259
2832
  defaultCodec: resolved.defaultCodec,
@@ -2302,15 +2875,18 @@ var internalRenderMediaOnWeb = async ({
2302
2875
  videoSampleSource.close();
2303
2876
  });
2304
2877
  output.addVideoTrack(videoSampleSource);
2305
- const defaultAudioEncodingConfig = await getDefaultAudioEncodingConfig();
2306
- if (!defaultAudioEncodingConfig) {
2307
- return Promise.reject(new Error("No default audio encoding config found"));
2878
+ let audioSampleSource = null;
2879
+ if (!muted) {
2880
+ const defaultAudioEncodingConfig = await getDefaultAudioEncodingConfig();
2881
+ if (!defaultAudioEncodingConfig) {
2882
+ return Promise.reject(new Error("No default audio encoding config found"));
2883
+ }
2884
+ audioSampleSource = new AudioSampleSource(defaultAudioEncodingConfig);
2885
+ cleanupFns.push(() => {
2886
+ audioSampleSource?.close();
2887
+ });
2888
+ output.addAudioTrack(audioSampleSource);
2308
2889
  }
2309
- const audioSampleSource = new AudioSampleSource(defaultAudioEncodingConfig);
2310
- cleanupFns.push(() => {
2311
- audioSampleSource.close();
2312
- });
2313
- output.addAudioTrack(audioSampleSource);
2314
2890
  await output.start();
2315
2891
  if (signal?.aborted) {
2316
2892
  throw new Error("renderMediaOnWeb() was cancelled");
@@ -2356,7 +2932,7 @@ var internalRenderMediaOnWeb = async ({
2356
2932
  if (signal?.aborted) {
2357
2933
  throw new Error("renderMediaOnWeb() was cancelled");
2358
2934
  }
2359
- const audio = onlyInlineAudio({ assets, fps: resolved.fps, frame });
2935
+ const audio = muted ? null : onlyInlineAudio({ assets, fps: resolved.fps, frame });
2360
2936
  const timestamp = Math.round((frame - realFrameRange[0]) / resolved.fps * 1e6);
2361
2937
  const videoFrame = new VideoFrame(imageData, {
2362
2938
  timestamp
@@ -2379,7 +2955,7 @@ var internalRenderMediaOnWeb = async ({
2379
2955
  }
2380
2956
  await Promise.all([
2381
2957
  addVideoSampleAndCloseFrame(frameToEncode, videoSampleSource),
2382
- audio ? addAudioSample(audio, audioSampleSource) : Promise.resolve()
2958
+ audio && audioSampleSource ? addAudioSample(audio, audioSampleSource) : Promise.resolve()
2383
2959
  ]);
2384
2960
  progress.encodedFrames++;
2385
2961
  throttledOnProgress?.({ ...progress });
@@ -2389,7 +2965,7 @@ var internalRenderMediaOnWeb = async ({
2389
2965
  }
2390
2966
  onProgress?.({ ...progress });
2391
2967
  videoSampleSource.close();
2392
- audioSampleSource.close();
2968
+ audioSampleSource?.close();
2393
2969
  await output.finalize();
2394
2970
  const mimeType = getMimeType(container);
2395
2971
  if (webFsTarget) {
@@ -2424,7 +3000,7 @@ var internalRenderMediaOnWeb = async ({
2424
3000
  licenseKey: licenseKey ?? null,
2425
3001
  apiName: "renderMediaOnWeb"
2426
3002
  }).catch((err2) => {
2427
- Internals6.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3003
+ Internals7.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
2428
3004
  });
2429
3005
  throw err;
2430
3006
  } finally {
@@ -2452,13 +3028,14 @@ var renderMediaOnWeb = (options) => {
2452
3028
  onArtifact: options.onArtifact ?? null,
2453
3029
  onFrame: options.onFrame ?? null,
2454
3030
  outputTarget: options.outputTarget ?? null,
2455
- licenseKey: options.licenseKey ?? undefined
3031
+ licenseKey: options.licenseKey ?? undefined,
3032
+ muted: options.muted ?? false
2456
3033
  }));
2457
3034
  return onlyOneRenderAtATimeQueue.ref;
2458
3035
  };
2459
3036
  // src/render-still-on-web.tsx
2460
3037
  import {
2461
- Internals as Internals7
3038
+ Internals as Internals8
2462
3039
  } from "remotion";
2463
3040
  async function internalRenderStillOnWeb({
2464
3041
  frame,
@@ -2473,7 +3050,7 @@ async function internalRenderStillOnWeb({
2473
3050
  onArtifact,
2474
3051
  licenseKey
2475
3052
  }) {
2476
- const resolved = await Internals7.resolveVideoConfig({
3053
+ const resolved = await Internals8.resolveVideoConfig({
2477
3054
  calculateMetadata: composition.calculateMetadata ?? null,
2478
3055
  signal: signal ?? new AbortController().signal,
2479
3056
  defaultProps: composition.defaultProps ?? {},
@@ -2544,7 +3121,7 @@ async function internalRenderStillOnWeb({
2544
3121
  licenseKey: licenseKey ?? null,
2545
3122
  apiName: "renderStillOnWeb"
2546
3123
  }).catch((err2) => {
2547
- Internals7.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
3124
+ Internals8.Log.error({ logLevel: "error", tag: "web-renderer" }, "Failed to send usage event", err2);
2548
3125
  });
2549
3126
  throw err;
2550
3127
  } finally {