remotion 4.0.176 → 4.0.178

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.
@@ -138,7 +138,7 @@ function truthy(value) {
138
138
  }
139
139
 
140
140
  // src/version.ts
141
- var VERSION = "4.0.176";
141
+ var VERSION = "4.0.178";
142
142
 
143
143
  // src/multiple-versions-warning.ts
144
144
  var checkMultipleRemotionVersions = () => {
@@ -527,6 +527,41 @@ var staticFile = (path) => {
527
527
  // src/input-props-serialization.ts
528
528
  var DATE_TOKEN = "remotion-date:";
529
529
  var FILE_TOKEN = "remotion-file:";
530
+ var serializeJSONWithDate = ({
531
+ data,
532
+ indent,
533
+ staticBase
534
+ }) => {
535
+ let customDateUsed = false;
536
+ let customFileUsed = false;
537
+ let mapUsed = false;
538
+ let setUsed = false;
539
+ try {
540
+ const serializedString = JSON.stringify(data, function(key, value) {
541
+ const item = this[key];
542
+ if (item instanceof Date) {
543
+ customDateUsed = true;
544
+ return `${DATE_TOKEN}${item.toISOString()}`;
545
+ }
546
+ if (item instanceof Map) {
547
+ mapUsed = true;
548
+ return value;
549
+ }
550
+ if (item instanceof Set) {
551
+ setUsed = true;
552
+ return value;
553
+ }
554
+ if (typeof item === "string" && staticBase !== null && item.startsWith(staticBase)) {
555
+ customFileUsed = true;
556
+ return `${FILE_TOKEN}${item.replace(staticBase + "/", "")}`;
557
+ }
558
+ return value;
559
+ }, indent);
560
+ return { serializedString, customDateUsed, customFileUsed, mapUsed, setUsed };
561
+ } catch (err) {
562
+ throw new Error("Could not serialize the passed input props to JSON: " + err.message);
563
+ }
564
+ };
530
565
  var deserializeJSONWithCustomFields = (data) => {
531
566
  return JSON.parse(data, (_, value) => {
532
567
  if (typeof value === "string" && value.startsWith(DATE_TOKEN)) {
@@ -538,6 +573,16 @@ var deserializeJSONWithCustomFields = (data) => {
538
573
  return value;
539
574
  });
540
575
  };
576
+ var serializeThenDeserializeInStudio = (props) => {
577
+ if (getRemotionEnvironment().isStudio) {
578
+ return deserializeJSONWithCustomFields(serializeJSONWithDate({
579
+ data: props,
580
+ indent: 2,
581
+ staticBase: window.remotion_staticBase
582
+ }).serializedString);
583
+ }
584
+ return props;
585
+ };
541
586
 
542
587
  // src/config/input-props.ts
543
588
  var didWarnSSRImport = false;
@@ -711,8 +756,8 @@ var resolveVideoConfig = ({
711
756
  fps,
712
757
  durationInFrames,
713
758
  id: compositionId,
714
- defaultProps,
715
- props: c.props ?? originalProps,
759
+ defaultProps: serializeThenDeserializeInStudio(defaultProps),
760
+ props: serializeThenDeserializeInStudio(c.props ?? originalProps),
716
761
  defaultCodec: defaultCodec ?? null
717
762
  };
718
763
  });
@@ -729,19 +774,33 @@ var resolveVideoConfig = ({
729
774
  return {
730
775
  ...data,
731
776
  id: compositionId,
732
- defaultProps: defaultProps ?? {},
733
- props: originalProps,
777
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
778
+ props: serializeThenDeserializeInStudio(originalProps),
734
779
  defaultCodec: null
735
780
  };
736
781
  }
737
782
  return {
738
783
  ...data,
739
784
  id: compositionId,
740
- defaultProps: defaultProps ?? {},
741
- props: calculatedProm.props ?? originalProps,
785
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
786
+ props: serializeThenDeserializeInStudio(calculatedProm.props ?? originalProps),
742
787
  defaultCodec: calculatedProm.defaultCodec ?? null
743
788
  };
744
789
  };
790
+ var resolveVideoConfigOrCatch = (params) => {
791
+ try {
792
+ const promiseOrReturnValue = resolveVideoConfig(params);
793
+ return {
794
+ type: "success",
795
+ result: promiseOrReturnValue
796
+ };
797
+ } catch (err) {
798
+ return {
799
+ type: "error",
800
+ error: err
801
+ };
802
+ }
803
+ };
745
804
 
746
805
  // src/ResolveCompositionConfig.tsx
747
806
  import {
@@ -788,7 +847,7 @@ var ResolveCompositionConfig = ({ children }) => {
788
847
  return controller;
789
848
  }
790
849
  const { signal } = controller;
791
- const promOrNot = resolveVideoConfig({
850
+ const result = resolveVideoConfigOrCatch({
792
851
  compositionId,
793
852
  calculateMetadata,
794
853
  originalProps: combinedProps,
@@ -799,6 +858,17 @@ var ResolveCompositionConfig = ({ children }) => {
799
858
  compositionHeight,
800
859
  compositionWidth
801
860
  });
861
+ if (result.type === "error") {
862
+ setResolvedConfigs((r) => ({
863
+ ...r,
864
+ [compositionId]: {
865
+ type: "error",
866
+ error: result.error
867
+ }
868
+ }));
869
+ return controller;
870
+ }
871
+ const promOrNot = result.result;
802
872
  if (typeof promOrNot === "object" && "then" in promOrNot) {
803
873
  setResolvedConfigs((r) => {
804
874
  const prev = r[compositionId];
@@ -1611,7 +1681,7 @@ var Artifact = ({ filename, content }) => {
1611
1681
  return null;
1612
1682
  };
1613
1683
  // src/audio/Audio.tsx
1614
- import {forwardRef as forwardRef5, useCallback as useCallback8, useContext as useContext23} from "react";
1684
+ import {forwardRef as forwardRef5, useCallback as useCallback9, useContext as useContext23} from "react";
1615
1685
 
1616
1686
  // src/absolute-src.ts
1617
1687
  var getAbsoluteSrc = (relativeSrc) => {
@@ -2005,7 +2075,7 @@ useContext as useContext21,
2005
2075
  useEffect as useEffect16,
2006
2076
  useImperativeHandle as useImperativeHandle3,
2007
2077
  useMemo as useMemo20,
2008
- useRef as useRef7,
2078
+ useRef as useRef8,
2009
2079
  useState as useState14
2010
2080
  } from "react";
2011
2081
 
@@ -2262,7 +2332,7 @@ var useMediaInTimeline = ({
2262
2332
  };
2263
2333
 
2264
2334
  // src/use-media-playback.ts
2265
- import {useContext as useContext18, useEffect as useEffect12} from "react";
2335
+ import {useCallback as useCallback7, useContext as useContext18, useEffect as useEffect12, useRef as useRef6} from "react";
2266
2336
 
2267
2337
  // src/buffer-until-first-frame.ts
2268
2338
  import {useCallback as useCallback6, useMemo as useMemo17, useRef as useRef3} from "react";
@@ -2353,11 +2423,12 @@ var useBufferState = () => {
2353
2423
  // src/buffer-until-first-frame.ts
2354
2424
  var useBufferUntilFirstFrame = ({
2355
2425
  mediaRef,
2356
- mediaType
2426
+ mediaType,
2427
+ onVariableFpsVideoDetected
2357
2428
  }) => {
2358
2429
  const bufferingRef = useRef3(false);
2359
2430
  const { delayPlayback } = useBufferState();
2360
- const bufferUntilFirstFrame = useCallback6(() => {
2431
+ const bufferUntilFirstFrame = useCallback6((requestedTime) => {
2361
2432
  if (mediaType !== "video") {
2362
2433
  return;
2363
2434
  }
@@ -2383,14 +2454,18 @@ var useBufferUntilFirstFrame = ({
2383
2454
  const onEndedOrPause = () => {
2384
2455
  unblock();
2385
2456
  };
2386
- current.requestVideoFrameCallback(() => {
2457
+ current.requestVideoFrameCallback((_, info) => {
2458
+ const differenceFromRequested = Math.abs(info.mediaTime - requestedTime);
2459
+ if (differenceFromRequested > 0.5) {
2460
+ onVariableFpsVideoDetected();
2461
+ }
2387
2462
  current.requestVideoFrameCallback(() => {
2388
2463
  unblock();
2389
2464
  });
2390
2465
  });
2391
2466
  current.addEventListener("ended", onEndedOrPause, { once: true });
2392
2467
  current.addEventListener("pause", onEndedOrPause, { once: true });
2393
- }, [delayPlayback, mediaRef, mediaType]);
2468
+ }, [delayPlayback, mediaRef, mediaType, onVariableFpsVideoDetected]);
2394
2469
  return useMemo17(() => {
2395
2470
  return {
2396
2471
  isBuffering: () => bufferingRef.current,
@@ -2783,6 +2858,7 @@ var useMediaPlayback = ({
2783
2858
  const buffering3 = useContext18(BufferingContextReact);
2784
2859
  const { fps } = useVideoConfig();
2785
2860
  const mediaStartsAt = useMediaStartsAt();
2861
+ const lastSeekDueToShift = useRef6(null);
2786
2862
  if (!buffering3) {
2787
2863
  throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
2788
2864
  }
@@ -2798,9 +2874,20 @@ var useMediaPlayback = ({
2798
2874
  shouldBuffer: pauseWhenBuffering,
2799
2875
  isPremounting
2800
2876
  });
2877
+ const isVariableFpsVideoMap = useRef6({});
2878
+ const onVariableFpsVideoDetected = useCallback7(() => {
2879
+ if (!src) {
2880
+ return;
2881
+ }
2882
+ if (debugSeeking) {
2883
+ console.log(`Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
2884
+ }
2885
+ isVariableFpsVideoMap.current[src] = true;
2886
+ }, [debugSeeking, src]);
2801
2887
  const { bufferUntilFirstFrame, isBuffering } = useBufferUntilFirstFrame({
2802
2888
  mediaRef,
2803
- mediaType
2889
+ mediaType,
2890
+ onVariableFpsVideoDetected
2804
2891
  });
2805
2892
  const playbackRate = localPlaybackRate * globalPlaybackRate;
2806
2893
  const acceptableTimeShiftButLessThanDuration = (() => {
@@ -2840,27 +2927,35 @@ var useMediaPlayback = ({
2840
2927
  }
2841
2928
  const { duration } = mediaRef.current;
2842
2929
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration) ? Math.min(duration, desiredUnclampedTime) : desiredUnclampedTime;
2843
- const isTime = mediaRef.current.currentTime;
2930
+ const mediaTagTime = mediaRef.current.currentTime;
2844
2931
  const rvcTime = currentTime.current ?? null;
2845
- const timeShiftMediaTag = Math.abs(shouldBeTime - isTime);
2932
+ const isVariableFpsVideo = isVariableFpsVideoMap.current[src];
2933
+ const timeShiftMediaTag = Math.abs(shouldBeTime - mediaTagTime);
2846
2934
  const timeShiftRvcTag = rvcTime ? Math.abs(shouldBeTime - rvcTime) : null;
2847
- const timeShift = timeShiftRvcTag ? timeShiftRvcTag : timeShiftMediaTag;
2935
+ const timeShift = timeShiftRvcTag && !isVariableFpsVideo ? timeShiftRvcTag : timeShiftMediaTag;
2848
2936
  if (debugSeeking) {
2849
2937
  console.log({
2850
- isTime,
2938
+ mediaTagTime,
2851
2939
  rvcTime,
2852
2940
  shouldBeTime,
2853
2941
  state: mediaRef.current.readyState,
2854
- playing: !mediaRef.current.paused
2942
+ playing: !mediaRef.current.paused,
2943
+ isVariableFpsVideo
2855
2944
  });
2856
2945
  }
2857
- if (timeShift > acceptableTimeShiftButLessThanDuration) {
2946
+ if (timeShift > acceptableTimeShiftButLessThanDuration && lastSeekDueToShift.current !== shouldBeTime) {
2858
2947
  if (debugSeeking) {
2859
- console.log("Seeking", { shouldBeTime, isTime, rvcTime, timeShift });
2948
+ console.log("Seeking", {
2949
+ shouldBeTime,
2950
+ isTime: mediaTagTime,
2951
+ rvcTime,
2952
+ timeShift
2953
+ });
2860
2954
  }
2861
2955
  seek(mediaRef, shouldBeTime);
2862
- if (playing) {
2863
- bufferUntilFirstFrame();
2956
+ lastSeekDueToShift.current = shouldBeTime;
2957
+ if (playing && !isVariableFpsVideo) {
2958
+ bufferUntilFirstFrame(shouldBeTime);
2864
2959
  if (mediaRef.current.paused) {
2865
2960
  playAndHandleNotAllowedError(mediaRef, mediaType);
2866
2961
  }
@@ -2885,7 +2980,9 @@ var useMediaPlayback = ({
2885
2980
  seek(mediaRef, shouldBeTime);
2886
2981
  }
2887
2982
  playAndHandleNotAllowedError(mediaRef, mediaType);
2888
- bufferUntilFirstFrame();
2983
+ if (!isVariableFpsVideo) {
2984
+ bufferUntilFirstFrame(shouldBeTime);
2985
+ }
2889
2986
  }
2890
2987
  }, [
2891
2988
  absoluteFrame,
@@ -2996,11 +3093,11 @@ var useMediaMutedState = () => {
2996
3093
  import React12, {
2997
3094
  createContext as createContext15,
2998
3095
  createRef as createRef2,
2999
- useCallback as useCallback7,
3096
+ useCallback as useCallback8,
3000
3097
  useContext as useContext20,
3001
3098
  useEffect as useEffect15,
3002
3099
  useMemo as useMemo19,
3003
- useRef as useRef6,
3100
+ useRef as useRef7,
3004
3101
  useState as useState13
3005
3102
  } from "react";
3006
3103
  import {
@@ -3035,7 +3132,7 @@ var didPropChange = (key, newProp, prevProp) => {
3035
3132
  };
3036
3133
  var SharedAudioContext = createContext15(null);
3037
3134
  var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) => {
3038
- const audios = useRef6([]);
3135
+ const audios = useRef7([]);
3039
3136
  const [initialNumberOfAudioTags] = useState13(numberOfAudioTags);
3040
3137
  if (numberOfAudioTags !== initialNumberOfAudioTags) {
3041
3138
  throw new Error("The number of shared audio tags has changed dynamically. Once you have set this property, you cannot change it afterwards.");
@@ -3045,8 +3142,8 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3045
3142
  return { id: Math.random(), ref: createRef2() };
3046
3143
  });
3047
3144
  }, [numberOfAudioTags]);
3048
- const takenAudios = useRef6(new Array(numberOfAudioTags).fill(false));
3049
- const rerenderAudios = useCallback7(() => {
3145
+ const takenAudios = useRef7(new Array(numberOfAudioTags).fill(false));
3146
+ const rerenderAudios = useCallback8(() => {
3050
3147
  refs.forEach(({ ref, id }) => {
3051
3148
  const data = audios.current?.find((a) => a.id === id);
3052
3149
  const { current } = ref;
@@ -3067,7 +3164,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3067
3164
  });
3068
3165
  });
3069
3166
  }, [refs]);
3070
- const registerAudio = useCallback7((aud, audioId) => {
3167
+ const registerAudio = useCallback8((aud, audioId) => {
3071
3168
  const found = audios.current?.find((a) => a.audioId === audioId);
3072
3169
  if (found) {
3073
3170
  return found;
@@ -3090,7 +3187,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3090
3187
  rerenderAudios();
3091
3188
  return newElem;
3092
3189
  }, [numberOfAudioTags, refs, rerenderAudios]);
3093
- const unregisterAudio = useCallback7((id) => {
3190
+ const unregisterAudio = useCallback8((id) => {
3094
3191
  const cloned = [...takenAudios.current];
3095
3192
  const index = refs.findIndex((r) => r.id === id);
3096
3193
  if (index === -1) {
@@ -3101,7 +3198,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3101
3198
  audios.current = audios.current?.filter((a) => a.id !== id);
3102
3199
  rerenderAudios();
3103
3200
  }, [refs, rerenderAudios]);
3104
- const updateAudio = useCallback7(({
3201
+ const updateAudio = useCallback8(({
3105
3202
  aud,
3106
3203
  audioId,
3107
3204
  id
@@ -3126,7 +3223,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3126
3223
  rerenderAudios();
3127
3224
  }
3128
3225
  }, [rerenderAudios]);
3129
- const playAllAudios = useCallback7(() => {
3226
+ const playAllAudios = useCallback8(() => {
3130
3227
  refs.forEach((ref) => {
3131
3228
  playAndHandleNotAllowedError(ref.ref, "audio");
3132
3229
  });
@@ -3146,7 +3243,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3146
3243
  unregisterAudio,
3147
3244
  updateAudio
3148
3245
  ]);
3149
- const resetAudio = useCallback7(() => {
3246
+ const resetAudio = useCallback8(() => {
3150
3247
  takenAudios.current = new Array(numberOfAudioTags).fill(false);
3151
3248
  audios.current = [];
3152
3249
  rerenderAudios();
@@ -3307,7 +3404,7 @@ var AudioForDevelopmentForwardRefFunction = (props, ref) => {
3307
3404
  useImperativeHandle3(ref, () => {
3308
3405
  return audioRef.current;
3309
3406
  }, [audioRef]);
3310
- const currentOnDurationCallback = useRef7();
3407
+ const currentOnDurationCallback = useRef8();
3311
3408
  currentOnDurationCallback.current = onDuration;
3312
3409
  useEffect16(() => {
3313
3410
  const { current } = audioRef;
@@ -3345,7 +3442,7 @@ useEffect as useEffect17,
3345
3442
  useImperativeHandle as useImperativeHandle4,
3346
3443
  useLayoutEffect as useLayoutEffect3,
3347
3444
  useMemo as useMemo21,
3348
- useRef as useRef8
3445
+ useRef as useRef9
3349
3446
  } from "react";
3350
3447
 
3351
3448
  // src/delay-render.ts
@@ -3420,7 +3517,7 @@ import {
3420
3517
  jsx as jsx17
3421
3518
  } from "react/jsx-runtime";
3422
3519
  var AudioForRenderingRefForwardingFunction = (props, ref) => {
3423
- const audioRef = useRef8(null);
3520
+ const audioRef = useRef9(null);
3424
3521
  const {
3425
3522
  volume: volumeProp,
3426
3523
  playbackRate,
@@ -3571,7 +3668,7 @@ var AudioRefForwardingFunction = (props, ref) => {
3571
3668
  throw new TypeError(`The \`<Audio>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
3572
3669
  }
3573
3670
  const preloadedSrc = usePreload(props.src);
3574
- const onError = useCallback8((e) => {
3671
+ const onError = useCallback9((e) => {
3575
3672
  console.log(e.currentTarget.error);
3576
3673
  const errMessage = `Could not play audio with src ${preloadedSrc}: ${e.currentTarget.error}. See https://remotion.dev/docs/media-playback-error for help.`;
3577
3674
  if (loop3) {
@@ -3580,7 +3677,7 @@ var AudioRefForwardingFunction = (props, ref) => {
3580
3677
  console.warn(errMessage);
3581
3678
  }
3582
3679
  }, [loop3, preloadedSrc]);
3583
- const onDuration = useCallback8((src, durationInSeconds) => {
3680
+ const onDuration = useCallback9((src, durationInSeconds) => {
3584
3681
  setDurations({ type: "got-duration", durationInSeconds, src });
3585
3682
  }, [setDurations]);
3586
3683
  const durationFetched = durations[getAbsoluteSrc(preloadedSrc)] ?? durations[getAbsoluteSrc(props.src)];
@@ -3798,7 +3895,7 @@ var portalNode = () => {
3798
3895
  import React16, {useMemo as useMemo23} from "react";
3799
3896
  var useLazyComponent = (compProps) => {
3800
3897
  const lazy = useMemo23(() => {
3801
- if ("lazyComponent" in compProps) {
3898
+ if ("lazyComponent" in compProps && typeof compProps.lazyComponent !== "undefined") {
3802
3899
  return React16.lazy(compProps.lazyComponent);
3803
3900
  }
3804
3901
  if ("component" in compProps) {
@@ -3899,7 +3996,7 @@ var Composition = ({
3899
3996
  id,
3900
3997
  folderName,
3901
3998
  component: lazy,
3902
- defaultProps,
3999
+ defaultProps: serializeThenDeserializeInStudio(defaultProps ?? {}),
3903
4000
  nonce: nonce5,
3904
4001
  parentFolderName: parentName,
3905
4002
  schema: schema ?? null,
@@ -3959,10 +4056,10 @@ var Composition = ({
3959
4056
  };
3960
4057
  // src/CompositionManager.tsx
3961
4058
  import React18, {
3962
- useCallback as useCallback9,
4059
+ useCallback as useCallback10,
3963
4060
  useImperativeHandle as useImperativeHandle5,
3964
4061
  useMemo as useMemo25,
3965
- useRef as useRef9,
4062
+ useRef as useRef10,
3966
4063
  useState as useState15
3967
4064
  } from "react";
3968
4065
  import {
@@ -3971,18 +4068,18 @@ jsx as jsx22
3971
4068
  var compositionsRef = React18.createRef();
3972
4069
  var CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
3973
4070
  const [compositions, setCompositions] = useState15([]);
3974
- const currentcompositionsRef = useRef9(compositions);
4071
+ const currentcompositionsRef = useRef10(compositions);
3975
4072
  const [folders, setFolders] = useState15([]);
3976
4073
  const [canvasContent, setCanvasContent] = useState15(null);
3977
4074
  const [currentCompositionMetadata, setCurrentCompositionMetadata] = useState15(null);
3978
- const updateCompositions = useCallback9((updateComps) => {
4075
+ const updateCompositions = useCallback10((updateComps) => {
3979
4076
  setCompositions((comps) => {
3980
4077
  const updated = updateComps(comps);
3981
4078
  currentcompositionsRef.current = updated;
3982
4079
  return updated;
3983
4080
  });
3984
4081
  }, []);
3985
- const registerComposition = useCallback9((comp) => {
4082
+ const registerComposition = useCallback10((comp) => {
3986
4083
  updateCompositions((comps) => {
3987
4084
  if (comps.find((c) => c.id === comp.id)) {
3988
4085
  throw new Error(`Multiple composition with id ${comp.id} are registered.`);
@@ -3991,12 +4088,12 @@ var CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
3991
4088
  return value;
3992
4089
  });
3993
4090
  }, [updateCompositions]);
3994
- const unregisterComposition = useCallback9((id) => {
4091
+ const unregisterComposition = useCallback10((id) => {
3995
4092
  setCompositions((comps) => {
3996
4093
  return comps.filter((c) => c.id !== id);
3997
4094
  });
3998
4095
  }, []);
3999
- const registerFolder = useCallback9((name, parent) => {
4096
+ const registerFolder = useCallback10((name, parent) => {
4000
4097
  setFolders((prevFolders) => {
4001
4098
  return [
4002
4099
  ...prevFolders,
@@ -4007,7 +4104,7 @@ var CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
4007
4104
  ];
4008
4105
  });
4009
4106
  }, []);
4010
- const unregisterFolder = useCallback9((name, parent) => {
4107
+ const unregisterFolder = useCallback10((name, parent) => {
4011
4108
  setFolders((prevFolders) => {
4012
4109
  return prevFolders.filter((p) => !(p.name === name && p.parent === parent));
4013
4110
  });
@@ -4018,7 +4115,7 @@ var CompositionManagerProvider = ({ children, numberOfAudioTags }) => {
4018
4115
  };
4019
4116
  }, []);
4020
4117
  const composition = compositions.find((c) => canvasContent?.type === "composition" ? c.id === canvasContent.compositionId : null);
4021
- const updateCompositionDefaultProps = useCallback9((id, newDefaultProps) => {
4118
+ const updateCompositionDefaultProps = useCallback10((id, newDefaultProps) => {
4022
4119
  setCompositions((comps) => {
4023
4120
  const updated = comps.map((c) => {
4024
4121
  if (c.id === id) {
@@ -4286,7 +4383,7 @@ var getStaticFiles = () => {
4286
4383
  return window.remotion_staticFiles;
4287
4384
  };
4288
4385
  // src/IFrame.tsx
4289
- import {forwardRef as forwardRef6, useCallback as useCallback10, useState as useState16} from "react";
4386
+ import {forwardRef as forwardRef6, useCallback as useCallback11, useState as useState16} from "react";
4290
4387
  import {
4291
4388
  jsx as jsx23
4292
4389
  } from "react/jsx-runtime";
@@ -4301,11 +4398,11 @@ var IFrameRefForwarding = ({
4301
4398
  retries: delayRenderRetries ?? undefined,
4302
4399
  timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined
4303
4400
  }));
4304
- const didLoad = useCallback10((e) => {
4401
+ const didLoad = useCallback11((e) => {
4305
4402
  continueRender(handle);
4306
4403
  onLoad?.(e);
4307
4404
  }, [handle, onLoad]);
4308
- const didGetError = useCallback10((e) => {
4405
+ const didGetError = useCallback11((e) => {
4309
4406
  continueRender(handle);
4310
4407
  if (onError) {
4311
4408
  onError(e);
@@ -4324,11 +4421,11 @@ var IFrame = forwardRef6(IFrameRefForwarding);
4324
4421
  // src/Img.tsx
4325
4422
  import {
4326
4423
  forwardRef as forwardRef7,
4327
- useCallback as useCallback11,
4424
+ useCallback as useCallback12,
4328
4425
  useContext as useContext26,
4329
4426
  useImperativeHandle as useImperativeHandle6,
4330
4427
  useLayoutEffect as useLayoutEffect4,
4331
- useRef as useRef10
4428
+ useRef as useRef11
4332
4429
  } from "react";
4333
4430
  var exponentialBackoff = function(errorCount) {
4334
4431
  return 1000 * 2 ** (errorCount - 1);
@@ -4345,8 +4442,8 @@ var ImgRefForwarding = ({
4345
4442
  delayRenderTimeoutInMilliseconds,
4346
4443
  ...props2
4347
4444
  }, ref) => {
4348
- const imageRef = useRef10(null);
4349
- const errors = useRef10({});
4445
+ const imageRef = useRef11(null);
4446
+ const errors = useRef11({});
4350
4447
  const { delayPlayback } = useBufferState();
4351
4448
  const sequenceContext = useContext26(SequenceContext);
4352
4449
  if (!src) {
@@ -4356,7 +4453,7 @@ var ImgRefForwarding = ({
4356
4453
  return imageRef.current;
4357
4454
  }, []);
4358
4455
  const actualSrc = usePreload(src);
4359
- const retryIn = useCallback11((timeout) => {
4456
+ const retryIn = useCallback12((timeout) => {
4360
4457
  if (!imageRef.current) {
4361
4458
  return;
4362
4459
  }
@@ -4373,7 +4470,7 @@ var ImgRefForwarding = ({
4373
4470
  imageRef.current.setAttribute("src", newSrc);
4374
4471
  }, timeout);
4375
4472
  }, []);
4376
- const didGetError = useCallback11((e) => {
4473
+ const didGetError = useCallback12((e) => {
4377
4474
  if (!errors.current) {
4378
4475
  return;
4379
4476
  }
@@ -4547,7 +4644,7 @@ import {
4547
4644
  useEffect as useEffect20,
4548
4645
  useLayoutEffect as useLayoutEffect5,
4549
4646
  useMemo as useMemo26,
4550
- useRef as useRef11,
4647
+ useRef as useRef12,
4551
4648
  useState as useState17
4552
4649
  } from "react";
4553
4650
  import {
@@ -4557,10 +4654,10 @@ var RemotionRoot = ({ children, numberOfAudioTags }) => {
4557
4654
  const [remotionRootId] = useState17(() => String(random(null)));
4558
4655
  const [frame, setFrame] = useState17(() => getInitialFrameState());
4559
4656
  const [playing, setPlaying] = useState17(false);
4560
- const imperativePlaying = useRef11(false);
4657
+ const imperativePlaying = useRef12(false);
4561
4658
  const [fastRefreshes, setFastRefreshes] = useState17(0);
4562
4659
  const [playbackRate, setPlaybackRate] = useState17(1);
4563
- const audioAndVideoTags = useRef11([]);
4660
+ const audioAndVideoTags = useRef12([]);
4564
4661
  if (typeof window !== "undefined") {
4565
4662
  useLayoutEffect5(() => {
4566
4663
  window.remotion_setFrame = (f, composition, attempt) => {
@@ -5658,10 +5755,10 @@ var Still = (props2) => {
5658
5755
  return React27.createElement(Composition, newProps);
5659
5756
  };
5660
5757
  // src/video/OffthreadVideo.tsx
5661
- import {useCallback as useCallback13} from "react";
5758
+ import {useCallback as useCallback14} from "react";
5662
5759
 
5663
5760
  // src/video/OffthreadVideoForRendering.tsx
5664
- import {useCallback as useCallback12, useContext as useContext27, useEffect as useEffect21, useMemo as useMemo29} from "react";
5761
+ import {useCallback as useCallback13, useContext as useContext27, useEffect as useEffect21, useMemo as useMemo29} from "react";
5665
5762
  import {
5666
5763
  jsx as jsx29
5667
5764
  } from "react/jsx-runtime";
@@ -5759,9 +5856,9 @@ var OffthreadVideoForRendering = ({
5759
5856
  toneMapped
5760
5857
  });
5761
5858
  }, [toneMapped, currentTime, src, transparent]);
5762
- const onErr = useCallback12((e) => {
5859
+ const onErr = useCallback13(() => {
5763
5860
  if (onError) {
5764
- onError?.(e);
5861
+ onError?.(new Error("Failed to load image with src " + actualSrc));
5765
5862
  } else {
5766
5863
  cancelRender("Failed to load image with src " + actualSrc);
5767
5864
  }
@@ -5784,14 +5881,14 @@ useContext as useContext28,
5784
5881
  useEffect as useEffect22,
5785
5882
  useImperativeHandle as useImperativeHandle7,
5786
5883
  useMemo as useMemo30,
5787
- useRef as useRef12,
5884
+ useRef as useRef13,
5788
5885
  useState as useState18
5789
5886
  } from "react";
5790
5887
  import {
5791
5888
  jsx as jsx30
5792
5889
  } from "react/jsx-runtime";
5793
5890
  var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5794
- const videoRef = useRef12(null);
5891
+ const videoRef = useRef13(null);
5795
5892
  const {
5796
5893
  volume,
5797
5894
  muted,
@@ -5810,6 +5907,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5810
5907
  pauseWhenBuffering,
5811
5908
  showInTimeline,
5812
5909
  loopVolumeCurveBehavior,
5910
+ onError,
5813
5911
  ...nativeProps
5814
5912
  } = props2;
5815
5913
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
@@ -5872,22 +5970,29 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5872
5970
  return;
5873
5971
  }
5874
5972
  const errorHandler = () => {
5875
- if (current?.error) {
5973
+ if (current.error) {
5876
5974
  console.error("Error occurred in video", current?.error);
5877
- if (props2.onError) {
5975
+ if (onError) {
5976
+ const err = new Error(`Code ${current.error.code}: ${current.error.message}`);
5977
+ onError(err);
5878
5978
  return;
5879
5979
  }
5880
5980
  throw new Error(`The browser threw an error while playing the video ${src}: Code ${current.error.code} - ${current?.error?.message}. See https://remotion.dev/docs/media-playback-error for help. Pass an onError() prop to handle the error.`);
5881
5981
  } else {
5882
- throw new Error("The browser threw an error");
5982
+ if (onError) {
5983
+ const err = new Error(`The browser threw an error while playing the video ${src}`);
5984
+ onError(err);
5985
+ return;
5986
+ }
5987
+ throw new Error("The browser threw an error while playing the video");
5883
5988
  }
5884
5989
  };
5885
5990
  current.addEventListener("error", errorHandler, { once: true });
5886
5991
  return () => {
5887
5992
  current.removeEventListener("error", errorHandler);
5888
5993
  };
5889
- }, [props2.onError, src]);
5890
- const currentOnDurationCallback = useRef12();
5994
+ }, [onError, src]);
5995
+ const currentOnDurationCallback = useRef13();
5891
5996
  currentOnDurationCallback.current = onDuration;
5892
5997
  useEffect22(() => {
5893
5998
  const { current } = videoRef;
@@ -5950,7 +6055,7 @@ var OffthreadVideo = (props2) => {
5950
6055
  ...otherProps
5951
6056
  } = props2;
5952
6057
  const environment = getRemotionEnvironment();
5953
- const onDuration = useCallback13(() => {
6058
+ const onDuration = useCallback14(() => {
5954
6059
  return;
5955
6060
  }, []);
5956
6061
  if (typeof props2.src !== "string") {
@@ -5999,7 +6104,7 @@ var OffthreadVideo = (props2) => {
5999
6104
  });
6000
6105
  };
6001
6106
  // src/video/Video.tsx
6002
- import {forwardRef as forwardRef11, useCallback as useCallback14, useContext as useContext30} from "react";
6107
+ import {forwardRef as forwardRef11, useCallback as useCallback15, useContext as useContext30} from "react";
6003
6108
 
6004
6109
  // src/video/VideoForRendering.tsx
6005
6110
  import {
@@ -6009,7 +6114,7 @@ useEffect as useEffect23,
6009
6114
  useImperativeHandle as useImperativeHandle8,
6010
6115
  useLayoutEffect as useLayoutEffect6,
6011
6116
  useMemo as useMemo31,
6012
- useRef as useRef13
6117
+ useRef as useRef14
6013
6118
  } from "react";
6014
6119
 
6015
6120
  // src/video/seek-until-right.ts
@@ -6121,7 +6226,7 @@ var VideoForRenderingForwardFunction = ({
6121
6226
  const frame = useCurrentFrame();
6122
6227
  const volumePropsFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
6123
6228
  const videoConfig = useUnsafeVideoConfig();
6124
- const videoRef = useRef13(null);
6229
+ const videoRef = useRef14(null);
6125
6230
  const sequenceContext = useContext29(SequenceContext);
6126
6231
  const mediaStartsAt = useMediaStartsAt();
6127
6232
  const environment = getRemotionEnvironment();
@@ -6287,8 +6392,7 @@ var VideoForRenderingForwardFunction = ({
6287
6392
  }
6288
6393
  return jsx32("video", {
6289
6394
  ref: videoRef,
6290
- ...props2,
6291
- onError
6395
+ ...props2
6292
6396
  });
6293
6397
  };
6294
6398
  var VideoForRendering = forwardRef10(VideoForRenderingForwardFunction);
@@ -6319,7 +6423,7 @@ var VideoForwardingFunction = (props2, ref) => {
6319
6423
  throw new TypeError(`The \`<Video>\` tag requires a string for \`src\`, but got ${JSON.stringify(props2.src)} instead.`);
6320
6424
  }
6321
6425
  const preloadedSrc = usePreload(props2.src);
6322
- const onDuration = useCallback14((src, durationInSeconds) => {
6426
+ const onDuration = useCallback15((src, durationInSeconds) => {
6323
6427
  setDurations({ type: "got-duration", durationInSeconds, src });
6324
6428
  }, [setDurations]);
6325
6429
  const durationFetched = durations[getAbsoluteSrc(preloadedSrc)] ?? durations[getAbsoluteSrc(props2.src)];