remotion 4.0.486 → 4.0.488

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.
@@ -1291,7 +1291,7 @@ var addSequenceStackTraces = (component) => {
1291
1291
  };
1292
1292
 
1293
1293
  // src/version.ts
1294
- var VERSION = "4.0.486";
1294
+ var VERSION = "4.0.488";
1295
1295
 
1296
1296
  // src/multiple-versions-warning.ts
1297
1297
  var checkMultipleRemotionVersions = () => {
@@ -5124,7 +5124,7 @@ var useEffectChainState = () => {
5124
5124
 
5125
5125
  // src/animated-image/canvas.tsx
5126
5126
  import { jsx as jsx13 } from "react/jsx-runtime";
5127
- var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects }, ref) => {
5127
+ var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effects, ...props }, ref) => {
5128
5128
  const canvasRef = useRef8(null);
5129
5129
  const chainState = useEffectChainState();
5130
5130
  const sourceCanvas = useMemo16(() => {
@@ -5188,7 +5188,8 @@ var CanvasRefForwardingFunction = ({ width, height, fit, className, style, effec
5188
5188
  return /* @__PURE__ */ jsx13("canvas", {
5189
5189
  ref: canvasRef,
5190
5190
  className,
5191
- style
5191
+ style,
5192
+ ...props
5192
5193
  });
5193
5194
  };
5194
5195
  var Canvas = React15.forwardRef(CanvasRefForwardingFunction);
@@ -5374,6 +5375,16 @@ var animatedImageSchema = {
5374
5375
  },
5375
5376
  ...transformSchema
5376
5377
  };
5378
+ var getCanvasPropsFromSequenceProps = (props) => {
5379
+ const canvasProps = {};
5380
+ const mutableCanvasProps = canvasProps;
5381
+ for (const key in props) {
5382
+ if (Object.prototype.hasOwnProperty.call(props, key) && (key.startsWith("data-") || key.startsWith("aria-"))) {
5383
+ mutableCanvasProps[key] = props[key];
5384
+ }
5385
+ }
5386
+ return canvasProps;
5387
+ };
5377
5388
  var AnimatedImageContent = forwardRef4(({
5378
5389
  src,
5379
5390
  width,
@@ -5528,6 +5539,7 @@ var AnimatedImageInner = ({
5528
5539
  useImperativeHandle2(ref, () => {
5529
5540
  return actualRef.current;
5530
5541
  }, []);
5542
+ const canvasProps = getCanvasPropsFromSequenceProps(sequenceProps);
5531
5543
  const animatedImageProps = {
5532
5544
  src,
5533
5545
  width,
@@ -5539,7 +5551,8 @@ var AnimatedImageInner = ({
5539
5551
  id,
5540
5552
  className,
5541
5553
  style,
5542
- requestInit
5554
+ requestInit,
5555
+ ...canvasProps
5543
5556
  };
5544
5557
  return /* @__PURE__ */ jsx14(Sequence, {
5545
5558
  layout: "none",
@@ -6567,6 +6580,7 @@ var SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled, pr
6567
6580
  return ({
6568
6581
  node,
6569
6582
  mediaTimestamp,
6583
+ sourceOffset,
6570
6584
  scheduledTime,
6571
6585
  duration,
6572
6586
  offset,
@@ -6595,7 +6609,7 @@ var SharedAudioContextProvider = ({ children, audioLatencyHint, audioEnabled, pr
6595
6609
  }
6596
6610
  }
6597
6611
  const scheduledEndTime = scheduledTime + duration / node.playbackRate.value;
6598
- const mediaTime = mediaTimestamp + offset;
6612
+ const mediaTime = mediaTimestamp + offset - sourceOffset;
6599
6613
  const mediaEndTime = mediaTime + duration;
6600
6614
  const latency = ctxAndGain.audioContext.baseLatency + ctxAndGain.audioContext.outputLatency;
6601
6615
  const timeDiff = scheduledTime - ctxAndGain.audioContext.currentTime;
@@ -7458,7 +7472,8 @@ var useBufferManager = (logLevel, mountTime) => {
7458
7472
  if (rendering) {
7459
7473
  return;
7460
7474
  }
7461
- if (blocks.length > 0) {
7475
+ if (blocks.length > 0 && !buffering.current) {
7476
+ buffering.current = true;
7462
7477
  onBufferingCallbacks.forEach((c2) => c2());
7463
7478
  playbackLogging({
7464
7479
  logLevel,
@@ -7473,7 +7488,8 @@ var useBufferManager = (logLevel, mountTime) => {
7473
7488
  if (rendering) {
7474
7489
  return;
7475
7490
  }
7476
- if (blocks.length === 0) {
7491
+ if (blocks.length === 0 && buffering.current) {
7492
+ buffering.current = false;
7477
7493
  onResumeCallbacks.forEach((c2) => c2());
7478
7494
  playbackLogging({
7479
7495
  logLevel,
@@ -7506,15 +7522,11 @@ var useIsPlayerBuffering = (bufferManager) => {
7506
7522
  const onResume = () => {
7507
7523
  setIsBuffering(false);
7508
7524
  };
7509
- bufferManager.listenForBuffering(onBuffer);
7510
- bufferManager.listenForResume(onResume);
7525
+ const buffer = bufferManager.listenForBuffering(onBuffer);
7526
+ const resume = bufferManager.listenForResume(onResume);
7511
7527
  return () => {
7512
- bufferManager.listenForBuffering(() => {
7513
- return;
7514
- });
7515
- bufferManager.listenForResume(() => {
7516
- return;
7517
- });
7528
+ buffer.remove();
7529
+ resume.remove();
7518
7530
  };
7519
7531
  }, [bufferManager]);
7520
7532
  return isBuffering;
@@ -7643,6 +7655,74 @@ var useBufferUntilFirstFrame = ({
7643
7655
  }, [bufferUntilFirstFrame]);
7644
7656
  };
7645
7657
 
7658
+ // src/get-media-sync-action.ts
7659
+ var getMediaSyncAction = (input) => {
7660
+ const {
7661
+ duration,
7662
+ currentTime,
7663
+ paused,
7664
+ ended,
7665
+ desiredUnclampedTime,
7666
+ mediaTagTime,
7667
+ mediaTagLastUpdate,
7668
+ rvcTime,
7669
+ rvcLastUpdate,
7670
+ isVariableFpsVideo,
7671
+ acceptableTimeShift,
7672
+ lastSeekDueToShift,
7673
+ playing,
7674
+ playbackRate,
7675
+ mediaTagBufferingOrStalled,
7676
+ playerBuffering,
7677
+ absoluteFrame,
7678
+ onlyWarnForMediaSeekingError,
7679
+ isPremounting,
7680
+ isPostmounting,
7681
+ pauseWhenBuffering
7682
+ } = input;
7683
+ const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration) ? Math.min(duration, desiredUnclampedTime) : desiredUnclampedTime;
7684
+ const timeShiftMediaTag = Math.abs(shouldBeTime - mediaTagTime);
7685
+ const timeShiftRvcTag = rvcTime ? Math.abs(shouldBeTime - rvcTime) : null;
7686
+ const mostRecentTimeshift = rvcLastUpdate && rvcTime > mediaTagLastUpdate ? timeShiftRvcTag : timeShiftMediaTag;
7687
+ const timeShift = timeShiftRvcTag && !isVariableFpsVideo ? mostRecentTimeshift : timeShiftMediaTag;
7688
+ if (timeShift > acceptableTimeShift && lastSeekDueToShift !== shouldBeTime) {
7689
+ return {
7690
+ type: "seek-due-to-shift",
7691
+ shouldBeTime,
7692
+ why: `because time shift is too big. shouldBeTime = ${shouldBeTime}, isTime = ${mediaTagTime}, requestVideoCallbackTime = ${rvcTime}, timeShift = ${timeShift}${isVariableFpsVideo ? ", isVariableFpsVideo = true" : ""}, isPremounting = ${isPremounting}, isPostmounting = ${isPostmounting}, pauseWhenBuffering = ${pauseWhenBuffering}`,
7693
+ bufferUntilFirstFrame: playing && playbackRate > 0,
7694
+ playReason: playing && paused ? "player is playing but media tag is paused, and just seeked" : null,
7695
+ warnAboutNonSeekable: !onlyWarnForMediaSeekingError
7696
+ };
7697
+ }
7698
+ const seekThreshold = playing ? 0.15 : 0.01;
7699
+ const makesSenseToSeek = Math.abs(currentTime - shouldBeTime) > seekThreshold;
7700
+ const isSomethingElseBuffering = playerBuffering && !mediaTagBufferingOrStalled;
7701
+ if (!playing || isSomethingElseBuffering) {
7702
+ return {
7703
+ type: "seek-if-not-playing",
7704
+ shouldBeTime,
7705
+ why: makesSenseToSeek ? `not playing or something else is buffering. time offset is over seek threshold (${seekThreshold})` : null
7706
+ };
7707
+ }
7708
+ if (!playing || playerBuffering) {
7709
+ return { type: "none" };
7710
+ }
7711
+ const pausedCondition = paused && !ended;
7712
+ const firstFrameCondition = absoluteFrame === 0;
7713
+ if (pausedCondition || firstFrameCondition) {
7714
+ const reason = pausedCondition ? "media tag is paused" : "absolute frame is 0";
7715
+ return {
7716
+ type: "play-and-seek",
7717
+ shouldBeTime,
7718
+ why: makesSenseToSeek ? `is over timeshift threshold (threshold = ${seekThreshold}) and ${reason}` : null,
7719
+ playReason: `player is playing and ${reason}`,
7720
+ bufferUntilFirstFrame: !isVariableFpsVideo && playbackRate > 0
7721
+ };
7722
+ }
7723
+ return { type: "none" };
7724
+ };
7725
+
7646
7726
  // src/media-tag-current-time-timestamp.ts
7647
7727
  import React21 from "react";
7648
7728
  var useCurrentTimeOfMediaTagWithUpdateTimeStamp = (mediaRef) => {
@@ -8078,89 +8158,93 @@ var useMediaPlayback = ({
8078
8158
  if (!src) {
8079
8159
  throw new Error(`No 'src' attribute was passed to the ${tagName} element.`);
8080
8160
  }
8081
- const { duration } = mediaRef.current;
8082
- const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration) ? Math.min(duration, desiredUnclampedTime) : desiredUnclampedTime;
8083
- const mediaTagTime = mediaTagCurrentTime.current.time;
8084
- const rvcTime = rvcCurrentTime.current?.time ?? null;
8085
- const isVariableFpsVideo = isVariableFpsVideoMap.current[src];
8086
- const timeShiftMediaTag = Math.abs(shouldBeTime - mediaTagTime);
8087
- const timeShiftRvcTag = rvcTime ? Math.abs(shouldBeTime - rvcTime) : null;
8088
- const mostRecentTimeshift = rvcCurrentTime.current?.lastUpdate && rvcCurrentTime.current.time > mediaTagCurrentTime.current.lastUpdate ? timeShiftRvcTag : timeShiftMediaTag;
8089
- const timeShift = timeShiftRvcTag && !isVariableFpsVideo ? mostRecentTimeshift : timeShiftMediaTag;
8090
- if (timeShift > acceptableTimeShiftButLessThanDuration && lastSeekDueToShift.current !== shouldBeTime) {
8161
+ const { current } = mediaRef;
8162
+ const action = getMediaSyncAction({
8163
+ duration: current.duration,
8164
+ currentTime: current.currentTime,
8165
+ paused: current.paused,
8166
+ ended: current.ended,
8167
+ desiredUnclampedTime,
8168
+ mediaTagTime: mediaTagCurrentTime.current.time,
8169
+ mediaTagLastUpdate: mediaTagCurrentTime.current.lastUpdate,
8170
+ rvcTime: rvcCurrentTime.current?.time ?? null,
8171
+ rvcLastUpdate: rvcCurrentTime.current?.lastUpdate ?? null,
8172
+ isVariableFpsVideo: Boolean(isVariableFpsVideoMap.current[src]),
8173
+ acceptableTimeShift: acceptableTimeShiftButLessThanDuration,
8174
+ lastSeekDueToShift: lastSeekDueToShift.current,
8175
+ playing,
8176
+ playbackRate,
8177
+ mediaTagBufferingOrStalled: isMediaTagBuffering || isBuffering(),
8178
+ playerBuffering: buffering.buffering.current,
8179
+ absoluteFrame,
8180
+ onlyWarnForMediaSeekingError,
8181
+ isPremounting,
8182
+ isPostmounting,
8183
+ pauseWhenBuffering
8184
+ });
8185
+ if (action.type === "none") {
8186
+ return;
8187
+ }
8188
+ if (action.type === "seek-due-to-shift") {
8091
8189
  lastSeek.current = seek({
8092
- mediaRef: mediaRef.current,
8093
- time: shouldBeTime,
8190
+ mediaRef: current,
8191
+ time: action.shouldBeTime,
8094
8192
  logLevel,
8095
- why: `because time shift is too big. shouldBeTime = ${shouldBeTime}, isTime = ${mediaTagTime}, requestVideoCallbackTime = ${rvcTime}, timeShift = ${timeShift}${isVariableFpsVideo ? ", isVariableFpsVideo = true" : ""}, isPremounting = ${isPremounting}, isPostmounting = ${isPostmounting}, pauseWhenBuffering = ${pauseWhenBuffering}`,
8193
+ why: action.why,
8096
8194
  mountTime
8097
8195
  });
8098
8196
  lastSeekDueToShift.current = lastSeek.current;
8099
- if (playing) {
8100
- if (playbackRate > 0) {
8101
- bufferUntilFirstFrame(shouldBeTime);
8102
- }
8103
- if (mediaRef.current.paused) {
8104
- playAndHandleNotAllowedError({
8105
- mediaRef,
8106
- mediaType,
8107
- onAutoPlayError,
8108
- logLevel,
8109
- mountTime,
8110
- reason: "player is playing but media tag is paused, and just seeked",
8111
- isPlayer: env.isPlayer
8112
- });
8113
- }
8114
- }
8115
- if (!onlyWarnForMediaSeekingError) {
8116
- warnAboutNonSeekableMedia(mediaRef.current, onlyWarnForMediaSeekingError ? "console-warning" : "console-error");
8197
+ if (action.bufferUntilFirstFrame) {
8198
+ bufferUntilFirstFrame(action.shouldBeTime);
8117
8199
  }
8118
- return;
8119
- }
8120
- const seekThreshold = playing ? 0.15 : 0.01;
8121
- const makesSenseToSeek = Math.abs(mediaRef.current.currentTime - shouldBeTime) > seekThreshold;
8122
- const isMediaTagBufferingOrStalled = isMediaTagBuffering || isBuffering();
8123
- const isSomethingElseBuffering = buffering.buffering.current && !isMediaTagBufferingOrStalled;
8124
- if (!playing || isSomethingElseBuffering) {
8125
- if (makesSenseToSeek) {
8126
- lastSeek.current = seek({
8127
- mediaRef: mediaRef.current,
8128
- time: shouldBeTime,
8200
+ if (action.playReason !== null) {
8201
+ playAndHandleNotAllowedError({
8202
+ mediaRef,
8203
+ mediaType,
8204
+ onAutoPlayError,
8129
8205
  logLevel,
8130
- why: `not playing or something else is buffering. time offset is over seek threshold (${seekThreshold})`,
8131
- mountTime
8206
+ mountTime,
8207
+ reason: action.playReason,
8208
+ isPlayer: env.isPlayer
8132
8209
  });
8133
8210
  }
8211
+ if (action.warnAboutNonSeekable) {
8212
+ warnAboutNonSeekableMedia(current, "console-error");
8213
+ }
8134
8214
  return;
8135
8215
  }
8136
- if (!playing || buffering.buffering.current) {
8137
- return;
8138
- }
8139
- const pausedCondition = mediaRef.current.paused && !mediaRef.current.ended;
8140
- const firstFrameCondition = absoluteFrame === 0;
8141
- if (pausedCondition || firstFrameCondition) {
8142
- const reason = pausedCondition ? "media tag is paused" : "absolute frame is 0";
8143
- if (makesSenseToSeek) {
8216
+ if (action.type === "seek-if-not-playing") {
8217
+ if (action.why !== null) {
8144
8218
  lastSeek.current = seek({
8145
- mediaRef: mediaRef.current,
8146
- time: shouldBeTime,
8219
+ mediaRef: current,
8220
+ time: action.shouldBeTime,
8147
8221
  logLevel,
8148
- why: `is over timeshift threshold (threshold = ${seekThreshold}) and ${reason}`,
8222
+ why: action.why,
8149
8223
  mountTime
8150
8224
  });
8151
8225
  }
8152
- playAndHandleNotAllowedError({
8153
- mediaRef,
8154
- mediaType,
8155
- onAutoPlayError,
8226
+ return;
8227
+ }
8228
+ if (action.why !== null) {
8229
+ lastSeek.current = seek({
8230
+ mediaRef: current,
8231
+ time: action.shouldBeTime,
8156
8232
  logLevel,
8157
- mountTime,
8158
- reason: `player is playing and ${reason}`,
8159
- isPlayer: env.isPlayer
8233
+ why: action.why,
8234
+ mountTime
8160
8235
  });
8161
- if (!isVariableFpsVideo && playbackRate > 0) {
8162
- bufferUntilFirstFrame(shouldBeTime);
8163
- }
8236
+ }
8237
+ playAndHandleNotAllowedError({
8238
+ mediaRef,
8239
+ mediaType,
8240
+ onAutoPlayError,
8241
+ logLevel,
8242
+ mountTime,
8243
+ reason: action.playReason,
8244
+ isPlayer: env.isPlayer
8245
+ });
8246
+ if (action.bufferUntilFirstFrame) {
8247
+ bufferUntilFirstFrame(action.shouldBeTime);
8164
8248
  }
8165
8249
  }, [
8166
8250
  absoluteFrame,
@@ -9457,13 +9541,18 @@ var CanvasImageContent = forwardRef10(({
9457
9541
  });
9458
9542
  const sequenceContext = useContext32(SequenceContext);
9459
9543
  const pendingLoadDelayRef = useRef23(null);
9460
- const continuePendingLoadDelay = useCallback17(() => {
9544
+ const [isLoadPending, setIsLoadPending] = useState16(false);
9545
+ const isPremounting = Boolean(sequenceContext?.premounting);
9546
+ const isPostmounting = Boolean(sequenceContext?.postmounting);
9547
+ const continuePendingLoadDelay = useCallback17(({ markAsReady }) => {
9461
9548
  const pending = pendingLoadDelayRef.current;
9462
9549
  if (!pending || pending.continued) {
9463
9550
  return;
9464
9551
  }
9465
9552
  pending.continued = true;
9466
- pending.unblock();
9553
+ if (markAsReady) {
9554
+ setIsLoadPending(false);
9555
+ }
9467
9556
  continueRender2(pending.handle);
9468
9557
  pendingLoadDelayRef.current = null;
9469
9558
  }, [continueRender2]);
@@ -9485,23 +9574,30 @@ var CanvasImageContent = forwardRef10(({
9485
9574
  }
9486
9575
  }, [ref, refForOutline]);
9487
9576
  useLayoutEffect10(() => {
9488
- const isPremounting = Boolean(sequenceContext?.premounting);
9489
- const isPostmounting = Boolean(sequenceContext?.postmounting);
9577
+ if (!pauseWhenLoading || !isLoadPending || isPremounting || isPostmounting) {
9578
+ return;
9579
+ }
9580
+ return delayPlayback().unblock;
9581
+ }, [
9582
+ delayPlayback,
9583
+ isLoadPending,
9584
+ isPostmounting,
9585
+ isPremounting,
9586
+ pauseWhenLoading
9587
+ ]);
9588
+ useLayoutEffect10(() => {
9490
9589
  const handle = delayRender2(`Rendering <CanvasImage> with src="${truncateSrcForLabel(actualSrc)}"`, {
9491
9590
  retries: delayRenderRetries ?? undefined,
9492
9591
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
9493
9592
  });
9494
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting ? delayPlayback().unblock : () => {
9495
- return;
9496
- };
9497
9593
  const controller = new AbortController;
9498
9594
  let cancelled = false;
9499
9595
  let errorCount = 0;
9500
9596
  let timeoutId = null;
9501
9597
  setLoadedImage(null);
9598
+ setIsLoadPending(true);
9502
9599
  pendingLoadDelayRef.current = {
9503
9600
  handle,
9504
- unblock,
9505
9601
  continued: false
9506
9602
  };
9507
9603
  const attemptLoad = () => {
@@ -9512,7 +9608,7 @@ var CanvasImageContent = forwardRef10(({
9512
9608
  setLoadedImage(image);
9513
9609
  }).catch((err) => {
9514
9610
  if (err.name === "AbortError") {
9515
- continuePendingLoadDelay();
9611
+ continuePendingLoadDelay({ markAsReady: false });
9516
9612
  return;
9517
9613
  }
9518
9614
  errorCount++;
@@ -9526,7 +9622,7 @@ var CanvasImageContent = forwardRef10(({
9526
9622
  }, backoff);
9527
9623
  } else if (onError) {
9528
9624
  onError(err);
9529
- continuePendingLoadDelay();
9625
+ continuePendingLoadDelay({ markAsReady: true });
9530
9626
  } else {
9531
9627
  cancelRender2(err);
9532
9628
  }
@@ -9539,21 +9635,17 @@ var CanvasImageContent = forwardRef10(({
9539
9635
  clearTimeout(timeoutId);
9540
9636
  }
9541
9637
  controller.abort();
9542
- continuePendingLoadDelay();
9638
+ continuePendingLoadDelay({ markAsReady: false });
9543
9639
  };
9544
9640
  }, [
9545
9641
  actualSrc,
9546
9642
  cancelRender2,
9547
9643
  continuePendingLoadDelay,
9548
- delayPlayback,
9549
9644
  delayRender2,
9550
9645
  delayRenderRetries,
9551
9646
  delayRenderTimeoutInMilliseconds,
9552
9647
  maxRetries,
9553
- onError,
9554
- pauseWhenLoading,
9555
- sequenceContext?.postmounting,
9556
- sequenceContext?.premounting
9648
+ onError
9557
9649
  ]);
9558
9650
  useLayoutEffect10(() => {
9559
9651
  if (!loadedImage || !outputCanvas || !sourceCanvas) {
@@ -9605,7 +9697,7 @@ var CanvasImageContent = forwardRef10(({
9605
9697
  return;
9606
9698
  }
9607
9699
  continueRenderOnce();
9608
- continuePendingLoadDelay();
9700
+ continuePendingLoadDelay({ markAsReady: true });
9609
9701
  }
9610
9702
  });
9611
9703
  }
@@ -9616,7 +9708,7 @@ var CanvasImageContent = forwardRef10(({
9616
9708
  if (onError) {
9617
9709
  onError(err);
9618
9710
  continueRenderOnce();
9619
- continuePendingLoadDelay();
9711
+ continuePendingLoadDelay({ markAsReady: true });
9620
9712
  } else {
9621
9713
  cancelRender2(err);
9622
9714
  }
@@ -9801,7 +9893,13 @@ var IFrameRefForwarding = ({
9801
9893
  };
9802
9894
  var IFrame = forwardRef11(IFrameRefForwarding);
9803
9895
  // src/Img.tsx
9804
- import { useCallback as useCallback19, useContext as useContext33, useLayoutEffect as useLayoutEffect11, useRef as useRef24 } from "react";
9896
+ import {
9897
+ useCallback as useCallback19,
9898
+ useContext as useContext33,
9899
+ useLayoutEffect as useLayoutEffect11,
9900
+ useRef as useRef24,
9901
+ useState as useState18
9902
+ } from "react";
9805
9903
  import { jsx as jsx28 } from "react/jsx-runtime";
9806
9904
  function exponentialBackoff2(errorCount) {
9807
9905
  return 1000 * 2 ** (errorCount - 1);
@@ -9824,6 +9922,7 @@ var ImgContent = ({
9824
9922
  const errors = useRef24({});
9825
9923
  const { delayPlayback } = useBufferState();
9826
9924
  const sequenceContext = useContext33(SequenceContext);
9925
+ const [isLoading, setIsLoading] = useState18(false);
9827
9926
  const _propsValid = true;
9828
9927
  if (!_propsValid) {
9829
9928
  throw new Error("typecheck error");
@@ -9856,6 +9955,8 @@ var ImgContent = ({
9856
9955
  }, timeout);
9857
9956
  }, []);
9858
9957
  const { delayRender: delayRender2, continueRender: continueRender2, cancelRender: cancelRender2 } = useDelayRender();
9958
+ const isPremounting = Boolean(sequenceContext?.premounting);
9959
+ const isPostmounting = Boolean(sequenceContext?.postmounting);
9859
9960
  const didGetError = useCallback19((e) => {
9860
9961
  if (!errors.current) {
9861
9962
  return;
@@ -9876,8 +9977,18 @@ var ImgContent = ({
9876
9977
  } catch {}
9877
9978
  }, [cancelRender2, maxRetries, onError, retryIn]);
9878
9979
  if (typeof window !== "undefined") {
9879
- const isPremounting = Boolean(sequenceContext?.premounting);
9880
- const isPostmounting = Boolean(sequenceContext?.postmounting);
9980
+ useLayoutEffect11(() => {
9981
+ if (!pauseWhenLoading || !isLoading || isPremounting || isPostmounting) {
9982
+ return;
9983
+ }
9984
+ return delayPlayback().unblock;
9985
+ }, [
9986
+ delayPlayback,
9987
+ isLoading,
9988
+ isPostmounting,
9989
+ isPremounting,
9990
+ pauseWhenLoading
9991
+ ]);
9881
9992
  useLayoutEffect11(() => {
9882
9993
  if (window.process?.env?.NODE_ENV === "test") {
9883
9994
  if (imageRef.current) {
@@ -9889,13 +10000,11 @@ var ImgContent = ({
9889
10000
  if (!current) {
9890
10001
  return;
9891
10002
  }
10003
+ setIsLoading(true);
9892
10004
  const newHandle = delayRender2("Loading <Img> with src=" + truncateSrcForLabel(actualSrc), {
9893
10005
  retries: delayRenderRetries ?? undefined,
9894
10006
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
9895
10007
  });
9896
- const unblock = pauseWhenLoading && !isPremounting && !isPostmounting ? delayPlayback().unblock : () => {
9897
- return;
9898
- };
9899
10008
  let unmounted = false;
9900
10009
  const onComplete = () => {
9901
10010
  if (unmounted) {
@@ -9909,7 +10018,7 @@ var ImgContent = ({
9909
10018
  if (current) {
9910
10019
  onImageFrame?.(current);
9911
10020
  }
9912
- unblock();
10021
+ setIsLoading(false);
9913
10022
  continueRender2(newHandle);
9914
10023
  };
9915
10024
  if (!imageRef.current) {
@@ -9928,17 +10037,12 @@ var ImgContent = ({
9928
10037
  return () => {
9929
10038
  unmounted = true;
9930
10039
  current.removeEventListener("load", onComplete);
9931
- unblock();
9932
10040
  continueRender2(newHandle);
9933
10041
  };
9934
10042
  }, [
9935
10043
  actualSrc,
9936
- delayPlayback,
9937
10044
  delayRenderRetries,
9938
10045
  delayRenderTimeoutInMilliseconds,
9939
- pauseWhenLoading,
9940
- isPremounting,
9941
- isPostmounting,
9942
10046
  onImageFrame,
9943
10047
  continueRender2,
9944
10048
  delayRender2
@@ -10264,7 +10368,7 @@ import {
10264
10368
  useImperativeHandle as useImperativeHandle8,
10265
10369
  useMemo as useMemo32,
10266
10370
  useRef as useRef26,
10267
- useState as useState18
10371
+ useState as useState19
10268
10372
  } from "react";
10269
10373
  import { jsx as jsx30 } from "react/jsx-runtime";
10270
10374
  var CompositionManagerProvider = ({
@@ -10274,9 +10378,9 @@ var CompositionManagerProvider = ({
10274
10378
  initialCompositions,
10275
10379
  initialCanvasContent
10276
10380
  }) => {
10277
- const [folders, setFolders] = useState18([]);
10278
- const [canvasContent, setCanvasContent] = useState18(initialCanvasContent);
10279
- const [compositions, setCompositions] = useState18(initialCompositions);
10381
+ const [folders, setFolders] = useState19([]);
10382
+ const [canvasContent, setCanvasContent] = useState19(initialCanvasContent);
10383
+ const [compositions, setCompositions] = useState19(initialCompositions);
10280
10384
  const currentcompositionsRef = useRef26(compositions);
10281
10385
  const updateCompositions = useCallback21((updateComps) => {
10282
10386
  setCompositions((comps) => {
@@ -10851,7 +10955,7 @@ import {
10851
10955
  useEffect as useEffect17,
10852
10956
  useLayoutEffect as useLayoutEffect12,
10853
10957
  useMemo as useMemo35,
10854
- useState as useState19
10958
+ useState as useState20
10855
10959
  } from "react";
10856
10960
 
10857
10961
  // src/video/offthread-video-source.ts
@@ -10966,7 +11070,7 @@ var OffthreadVideoForRendering = ({
10966
11070
  toneMapped
10967
11071
  });
10968
11072
  }, [toneMapped, currentTime, src, transparent]);
10969
- const [imageSrc, setImageSrc] = useState19(null);
11073
+ const [imageSrc, setImageSrc] = useState20(null);
10970
11074
  const { delayRender: delayRender2, continueRender: continueRender2 } = useDelayRender();
10971
11075
  useLayoutEffect12(() => {
10972
11076
  if (!window.remotion_videoEnabled) {
@@ -11078,7 +11182,7 @@ import React37, {
11078
11182
  useImperativeHandle as useImperativeHandle9,
11079
11183
  useMemo as useMemo36,
11080
11184
  useRef as useRef27,
11081
- useState as useState20
11185
+ useState as useState21
11082
11186
  } from "react";
11083
11187
 
11084
11188
  // src/video/emit-video-frame.ts
@@ -11189,7 +11293,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
11189
11293
  const parentSequence = useContext37(SequenceContext);
11190
11294
  const logLevel = useLogLevel();
11191
11295
  const mountTime = useMountTime();
11192
- const [timelineId] = useState20(() => String(Math.random()));
11296
+ const [timelineId] = useState21(() => String(Math.random()));
11193
11297
  if (typeof acceptableTimeShift !== "undefined") {
11194
11298
  throw new Error("acceptableTimeShift has been removed. Use acceptableTimeShiftInSeconds instead.");
11195
11299
  }
@@ -11260,7 +11364,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
11260
11364
  useImperativeHandle9(ref, () => {
11261
11365
  return videoRef.current;
11262
11366
  }, []);
11263
- useState20(() => playbackLogging({
11367
+ useState21(() => playbackLogging({
11264
11368
  logLevel,
11265
11369
  message: `Mounting video with source = ${actualSrc}, v=${VERSION}, user agent=${typeof navigator === "undefined" ? "server" : navigator.userAgent}`,
11266
11370
  tag: "video",
@@ -12009,6 +12113,7 @@ var Still = (props2) => {
12009
12113
  };
12010
12114
  return React42.createElement(Composition, newProps);
12011
12115
  };
12116
+ addSequenceStackTraces(Still);
12012
12117
  // src/video/html5-video.tsx
12013
12118
  import { forwardRef as forwardRef16, useCallback as useCallback25, useContext as useContext39 } from "react";
12014
12119
 
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.486";
2
+ var VERSION = "4.0.488";
3
3
  export {
4
4
  VERSION
5
5
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/core"
4
4
  },
5
5
  "name": "remotion",
6
- "version": "4.0.486",
6
+ "version": "4.0.488",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "react-dom": "19.2.3",
36
36
  "webpack": "5.105.0",
37
37
  "zod": "4.3.6",
38
- "@remotion/eslint-config-internal": "4.0.486",
38
+ "@remotion/eslint-config-internal": "4.0.488",
39
39
  "eslint": "9.19.0",
40
40
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
41
41
  },