remotion 4.0.186 → 4.0.188

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ if (typeof react_1.createContext !== 'function') {
5
+ const err = [
6
+ 'Remotion requires React.createContext, but it is "undefined".',
7
+ 'If you are in a React Server Component, turn it into a client component by adding "use client" at the top of the file.',
8
+ '',
9
+ 'Before:',
10
+ ' import {useCurrentFrame} from "remotion";',
11
+ '',
12
+ 'After:',
13
+ ' "use client";',
14
+ ' import {useCurrentFrame} from "remotion";',
15
+ ];
16
+ throw new Error(err.join('\n'));
17
+ }
@@ -86,6 +86,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
86
86
  stack: _remotionInternalStack,
87
87
  showInTimeline,
88
88
  premountDisplay: null,
89
+ onAutoPlayError: null,
89
90
  });
90
91
  (0, use_media_playback_js_1.useMediaPlayback)({
91
92
  mediaRef: audioRef,
@@ -97,6 +98,7 @@ const AudioForDevelopmentForwardRefFunction = (props, ref) => {
97
98
  isPremounting: Boolean(sequenceContext === null || sequenceContext === void 0 ? void 0 : sequenceContext.premounting),
98
99
  pauseWhenBuffering,
99
100
  debugSeeking: _remotionDebugSeeking,
101
+ onAutoPlayError: null,
100
102
  });
101
103
  (0, react_1.useImperativeHandle)(ref, () => {
102
104
  return audioRef.current;
@@ -31,9 +31,9 @@ type SharedContext = {
31
31
  };
32
32
  export declare const SharedAudioContext: React.Context<SharedContext | null>;
33
33
  export declare const SharedAudioContextProvider: React.FC<{
34
- numberOfAudioTags: number;
35
- children: React.ReactNode;
36
- component: LazyExoticComponent<ComponentType<Record<string, unknown>>> | null;
34
+ readonly numberOfAudioTags: number;
35
+ readonly children: React.ReactNode;
36
+ readonly component: LazyExoticComponent<ComponentType<Record<string, unknown>>> | null;
37
37
  }>;
38
38
  export declare const useSharedAudio: (aud: RemotionAudioProps, audioId: string) => AudioElem;
39
39
  export {};
@@ -158,7 +158,7 @@ const SharedAudioContextProvider = ({ children, numberOfAudioTags, component })
158
158
  }, [rerenderAudios]);
159
159
  const playAllAudios = (0, react_1.useCallback)(() => {
160
160
  refs.forEach((ref) => {
161
- (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(ref.ref, 'audio');
161
+ (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(ref.ref, 'audio', null);
162
162
  });
163
163
  }, [refs]);
164
164
  const value = (0, react_1.useMemo)(() => {
@@ -1,7 +1,8 @@
1
- export declare const useBufferUntilFirstFrame: ({ mediaRef, mediaType, onVariableFpsVideoDetected, }: {
1
+ export declare const useBufferUntilFirstFrame: ({ mediaRef, mediaType, onVariableFpsVideoDetected, pauseWhenBuffering, }: {
2
2
  mediaRef: React.RefObject<HTMLVideoElement | HTMLAudioElement>;
3
3
  mediaType: 'video' | 'audio';
4
4
  onVariableFpsVideoDetected: () => void;
5
+ pauseWhenBuffering: boolean;
5
6
  }) => {
6
7
  isBuffering: () => boolean;
7
8
  bufferUntilFirstFrame: (requestedTime: number) => void;
@@ -3,13 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useBufferUntilFirstFrame = void 0;
4
4
  const react_1 = require("react");
5
5
  const use_buffer_state_1 = require("./use-buffer-state");
6
- const useBufferUntilFirstFrame = ({ mediaRef, mediaType, onVariableFpsVideoDetected, }) => {
6
+ const useBufferUntilFirstFrame = ({ mediaRef, mediaType, onVariableFpsVideoDetected, pauseWhenBuffering, }) => {
7
7
  const bufferingRef = (0, react_1.useRef)(false);
8
8
  const { delayPlayback } = (0, use_buffer_state_1.useBufferState)();
9
9
  const bufferUntilFirstFrame = (0, react_1.useCallback)((requestedTime) => {
10
10
  if (mediaType !== 'video') {
11
11
  return;
12
12
  }
13
+ if (!pauseWhenBuffering) {
14
+ return;
15
+ }
13
16
  const current = mediaRef.current;
14
17
  if (!current) {
15
18
  return;
@@ -47,7 +50,13 @@ const useBufferUntilFirstFrame = ({ mediaRef, mediaType, onVariableFpsVideoDetec
47
50
  });
48
51
  current.addEventListener('ended', onEndedOrPause, { once: true });
49
52
  current.addEventListener('pause', onEndedOrPause, { once: true });
50
- }, [delayPlayback, mediaRef, mediaType, onVariableFpsVideoDetected]);
53
+ }, [
54
+ delayPlayback,
55
+ mediaRef,
56
+ mediaType,
57
+ onVariableFpsVideoDetected,
58
+ pauseWhenBuffering,
59
+ ]);
51
60
  return (0, react_1.useMemo)(() => {
52
61
  return {
53
62
  isBuffering: () => bufferingRef.current,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ if (typeof react_1.createContext !== 'function') {
5
+ throw new Error('React 18 is required for Remotion');
6
+ }
@@ -56,9 +56,9 @@ export declare const Internals: {
56
56
  numberOfAudioTags: number;
57
57
  } | null>;
58
58
  readonly SharedAudioContextProvider: import("react").FC<{
59
- numberOfAudioTags: number;
60
- children: import("react").ReactNode;
61
- component: import("react").LazyExoticComponent<import("react").ComponentType<Record<string, unknown>>> | null;
59
+ readonly numberOfAudioTags: number;
60
+ readonly children: import("react").ReactNode;
61
+ readonly component: import("react").LazyExoticComponent<import("react").ComponentType<Record<string, unknown>>> | null;
62
62
  }>;
63
63
  readonly invalidCompositionErrorMessage: string;
64
64
  readonly isCompositionIdValid: (id: string) => RegExpMatchArray | null;
@@ -1,2 +1,2 @@
1
1
  import type { RefObject } from 'react';
2
- export declare const playAndHandleNotAllowedError: (mediaRef: RefObject<HTMLVideoElement | HTMLAudioElement>, mediaType: 'audio' | 'video') => void;
2
+ export declare const playAndHandleNotAllowedError: (mediaRef: RefObject<HTMLVideoElement | HTMLAudioElement>, mediaType: 'audio' | 'video', onAutoPlayError: null | (() => void)) => void;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.playAndHandleNotAllowedError = void 0;
4
- const playAndHandleNotAllowedError = (mediaRef, mediaType) => {
4
+ const get_remotion_environment_1 = require("./get-remotion-environment");
5
+ const playAndHandleNotAllowedError = (mediaRef, mediaType, onAutoPlayError) => {
5
6
  const { current } = mediaRef;
6
7
  if (!current) {
7
8
  return;
@@ -35,8 +36,16 @@ const playAndHandleNotAllowedError = (mediaRef, mediaType) => {
35
36
  // eslint-disable-next-line no-console
36
37
  console.log(`Could not play ${mediaType} due to following error: `, err);
37
38
  if (!current.muted) {
39
+ if (onAutoPlayError) {
40
+ onAutoPlayError();
41
+ return;
42
+ }
38
43
  // eslint-disable-next-line no-console
39
44
  console.log(`The video will be muted and we'll retry playing it.`);
45
+ if (mediaType === 'video' && (0, get_remotion_environment_1.getRemotionEnvironment)().isPlayer) {
46
+ // eslint-disable-next-line no-console
47
+ console.log('Use onAutoPlayError() to handle this error yourself.');
48
+ }
40
49
  current.muted = true;
41
50
  current.play();
42
51
  }
@@ -1,6 +1,6 @@
1
1
  import type { RefObject } from 'react';
2
2
  import type { VolumeProp } from './volume-prop.js';
3
- export declare const useMediaInTimeline: ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, displayName, id, stack, showInTimeline, premountDisplay, }: {
3
+ export declare const useMediaInTimeline: ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, displayName, id, stack, showInTimeline, premountDisplay, onAutoPlayError, }: {
4
4
  volume: VolumeProp | undefined;
5
5
  mediaVolume: number;
6
6
  mediaRef: RefObject<HTMLAudioElement | HTMLVideoElement>;
@@ -12,4 +12,5 @@ export declare const useMediaInTimeline: ({ volume, mediaVolume, mediaRef, src,
12
12
  stack: string | null;
13
13
  showInTimeline: boolean;
14
14
  premountDisplay: number | null;
15
+ onAutoPlayError: null | (() => void);
15
16
  }) => void;
@@ -21,7 +21,7 @@ const warnOnce = (message) => {
21
21
  console.warn(message);
22
22
  didWarn[message] = true;
23
23
  };
24
- const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, displayName, id, stack, showInTimeline, premountDisplay, }) => {
24
+ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, playbackRate, displayName, id, stack, showInTimeline, premountDisplay, onAutoPlayError, }) => {
25
25
  const videoConfig = (0, use_video_config_js_1.useVideoConfig)();
26
26
  const { rootId, audioAndVideoTags } = (0, react_1.useContext)(timeline_position_state_js_1.TimelineContext);
27
27
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
@@ -125,13 +125,13 @@ const useMediaInTimeline = ({ volume, mediaVolume, mediaRef, src, mediaType, pla
125
125
  // Don't play if for example in a <Freeze> state.
126
126
  return;
127
127
  }
128
- return (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType);
128
+ return (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType, onAutoPlayError);
129
129
  },
130
130
  };
131
131
  audioAndVideoTags.current.push(tag);
132
132
  return () => {
133
133
  audioAndVideoTags.current = audioAndVideoTags.current.filter((a) => a.id !== id);
134
134
  };
135
- }, [audioAndVideoTags, id, mediaRef, mediaType, playing]);
135
+ }, [audioAndVideoTags, id, mediaRef, mediaType, onAutoPlayError, playing]);
136
136
  };
137
137
  exports.useMediaInTimeline = useMediaInTimeline;
@@ -1,6 +1,6 @@
1
1
  import type { RefObject } from 'react';
2
2
  export declare const DEFAULT_ACCEPTABLE_TIMESHIFT = 0.45;
3
- export declare const useMediaPlayback: ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, pauseWhenBuffering, isPremounting, debugSeeking, }: {
3
+ export declare const useMediaPlayback: ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, pauseWhenBuffering, isPremounting, debugSeeking, onAutoPlayError, }: {
4
4
  mediaRef: RefObject<HTMLVideoElement | HTMLAudioElement>;
5
5
  src: string | undefined;
6
6
  mediaType: 'audio' | 'video';
@@ -10,4 +10,5 @@ export declare const useMediaPlayback: ({ mediaRef, src, mediaType, playbackRate
10
10
  pauseWhenBuffering: boolean;
11
11
  isPremounting: boolean;
12
12
  debugSeeking: boolean;
13
+ onAutoPlayError: null | (() => void);
13
14
  }) => void;
@@ -23,7 +23,7 @@ const seek = (mediaRef, time) => {
23
23
  const timeToSet = (0, video_fragment_js_1.isIosSafari)() ? Number(time.toFixed(1)) : time;
24
24
  mediaRef.current.currentTime = timeToSet;
25
25
  };
26
- const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, pauseWhenBuffering, isPremounting, debugSeeking, }) => {
26
+ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybackRate, onlyWarnForMediaSeekingError, acceptableTimeshift, pauseWhenBuffering, isPremounting, debugSeeking, onAutoPlayError, }) => {
27
27
  const { playbackRate: globalPlaybackRate } = (0, react_1.useContext)(timeline_position_state_js_1.TimelineContext);
28
28
  const frame = (0, use_current_frame_js_1.useCurrentFrame)();
29
29
  const absoluteFrame = (0, timeline_position_state_js_1.useTimelinePosition)();
@@ -32,21 +32,10 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
32
32
  const { fps } = (0, use_video_config_js_1.useVideoConfig)();
33
33
  const mediaStartsAt = (0, use_audio_frame_js_1.useMediaStartsAt)();
34
34
  const lastSeekDueToShift = (0, react_1.useRef)(null);
35
+ const lastSeek = (0, react_1.useRef)(null);
35
36
  if (!buffering) {
36
37
  throw new Error('useMediaPlayback must be used inside a <BufferingContext>');
37
38
  }
38
- const currentTime = (0, use_request_video_callback_time_js_1.useRequestVideoCallbackTime)(mediaRef, mediaType);
39
- const desiredUnclampedTime = (0, get_current_time_js_1.getMediaTime)({
40
- frame,
41
- playbackRate: localPlaybackRate,
42
- startFrom: -mediaStartsAt,
43
- fps,
44
- });
45
- const isMediaTagBuffering = (0, use_media_buffering_js_1.useMediaBuffering)({
46
- element: mediaRef,
47
- shouldBuffer: pauseWhenBuffering,
48
- isPremounting,
49
- });
50
39
  const isVariableFpsVideoMap = (0, react_1.useRef)({});
51
40
  const onVariableFpsVideoDetected = (0, react_1.useCallback)(() => {
52
41
  if (!src) {
@@ -58,10 +47,28 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
58
47
  }
59
48
  isVariableFpsVideoMap.current[src] = true;
60
49
  }, [debugSeeking, src]);
50
+ const currentTime = (0, use_request_video_callback_time_js_1.useRequestVideoCallbackTime)({
51
+ mediaRef,
52
+ mediaType,
53
+ lastSeek,
54
+ onVariableFpsVideoDetected,
55
+ });
56
+ const desiredUnclampedTime = (0, get_current_time_js_1.getMediaTime)({
57
+ frame,
58
+ playbackRate: localPlaybackRate,
59
+ startFrom: -mediaStartsAt,
60
+ fps,
61
+ });
62
+ const isMediaTagBuffering = (0, use_media_buffering_js_1.useMediaBuffering)({
63
+ element: mediaRef,
64
+ shouldBuffer: pauseWhenBuffering,
65
+ isPremounting,
66
+ });
61
67
  const { bufferUntilFirstFrame, isBuffering } = (0, buffer_until_first_frame_js_1.useBufferUntilFirstFrame)({
62
68
  mediaRef,
63
69
  mediaType,
64
70
  onVariableFpsVideoDetected,
71
+ pauseWhenBuffering,
65
72
  });
66
73
  const playbackRate = localPlaybackRate * globalPlaybackRate;
67
74
  // For short audio, a lower acceptable time shift is used
@@ -137,14 +144,16 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
137
144
  isTime: mediaTagTime,
138
145
  rvcTime,
139
146
  timeShift,
147
+ isVariableFpsVideo,
140
148
  });
141
149
  }
142
150
  seek(mediaRef, shouldBeTime);
151
+ lastSeek.current = shouldBeTime;
143
152
  lastSeekDueToShift.current = shouldBeTime;
144
153
  if (playing && !isVariableFpsVideo) {
145
154
  bufferUntilFirstFrame(shouldBeTime);
146
155
  if (mediaRef.current.paused) {
147
- (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType);
156
+ (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType, onAutoPlayError);
148
157
  }
149
158
  }
150
159
  if (!onlyWarnForMediaSeekingError) {
@@ -164,6 +173,7 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
164
173
  if (!playing || isSomethingElseBuffering) {
165
174
  if (makesSenseToSeek) {
166
175
  seek(mediaRef, shouldBeTime);
176
+ lastSeek.current = shouldBeTime;
167
177
  }
168
178
  return;
169
179
  }
@@ -172,8 +182,9 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
172
182
  absoluteFrame === 0) {
173
183
  if (makesSenseToSeek) {
174
184
  seek(mediaRef, shouldBeTime);
185
+ lastSeek.current = shouldBeTime;
175
186
  }
176
- (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType);
187
+ (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType, onAutoPlayError);
177
188
  if (!isVariableFpsVideo) {
178
189
  bufferUntilFirstFrame(shouldBeTime);
179
190
  }
@@ -194,6 +205,7 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
194
205
  playbackRate,
195
206
  playing,
196
207
  src,
208
+ onAutoPlayError,
197
209
  ]);
198
210
  };
199
211
  exports.useMediaPlayback = useMediaPlayback;
@@ -1,2 +1,7 @@
1
1
  import type { RefObject } from 'react';
2
- export declare const useRequestVideoCallbackTime: (mediaRef: RefObject<HTMLVideoElement | HTMLAudioElement>, mediaType: 'video' | 'audio') => import("react").MutableRefObject<number | null>;
2
+ export declare const useRequestVideoCallbackTime: ({ mediaRef, mediaType, lastSeek, onVariableFpsVideoDetected, }: {
3
+ mediaRef: RefObject<HTMLVideoElement | HTMLAudioElement>;
4
+ mediaType: 'video' | 'audio';
5
+ lastSeek: React.MutableRefObject<number | null>;
6
+ onVariableFpsVideoDetected: () => void;
7
+ }) => import("react").MutableRefObject<number | null>;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useRequestVideoCallbackTime = void 0;
4
4
  const react_1 = require("react");
5
- const useRequestVideoCallbackTime = (mediaRef, mediaType) => {
5
+ const useRequestVideoCallbackTime = ({ mediaRef, mediaType, lastSeek, onVariableFpsVideoDetected, }) => {
6
6
  const currentTime = (0, react_1.useRef)(null);
7
7
  (0, react_1.useEffect)(() => {
8
8
  const { current } = mediaRef;
@@ -27,6 +27,20 @@ const useRequestVideoCallbackTime = (mediaRef, mediaType) => {
27
27
  return;
28
28
  }
29
29
  const cb = videoTag.requestVideoFrameCallback((_, info) => {
30
+ if (currentTime.current !== null) {
31
+ const difference = Math.abs(currentTime.current - info.mediaTime);
32
+ const differenceToLastSeek = Math.abs(lastSeek.current === null
33
+ ? Infinity
34
+ : info.mediaTime - lastSeek.current);
35
+ // If a video suddenly jumps to a position much further than previously
36
+ // and there was no relevant seek
37
+ // Case to be seen with 66a4a49b0862333a56c7d03c.mp4 and autoPlay and pauseWhenBuffering
38
+ if (difference > 0.5 &&
39
+ differenceToLastSeek > 0.5 &&
40
+ info.mediaTime > currentTime.current) {
41
+ onVariableFpsVideoDetected();
42
+ }
43
+ }
30
44
  currentTime.current = info.mediaTime;
31
45
  request();
32
46
  });
@@ -39,7 +53,7 @@ const useRequestVideoCallbackTime = (mediaRef, mediaType) => {
39
53
  return () => {
40
54
  cancel();
41
55
  };
42
- }, [mediaRef, mediaType]);
56
+ }, [lastSeek, mediaRef, mediaType, onVariableFpsVideoDetected]);
43
57
  return currentTime;
44
58
  };
45
59
  exports.useRequestVideoCallbackTime = useRequestVideoCallbackTime;
@@ -3,4 +3,4 @@
3
3
  * @see [Documentation](https://remotion.dev/docs/version)
4
4
  * @returns {string} The current version of the remotion package
5
5
  */
6
- export declare const VERSION = "4.0.186";
6
+ export declare const VERSION = "4.0.188";
@@ -7,4 +7,4 @@ exports.VERSION = void 0;
7
7
  * @see [Documentation](https://remotion.dev/docs/version)
8
8
  * @returns {string} The current version of the remotion package
9
9
  */
10
- exports.VERSION = '4.0.186';
10
+ exports.VERSION = '4.0.188';
@@ -35,7 +35,7 @@ const OffthreadVideo = (props) => {
35
35
  if (environment.isRendering) {
36
36
  return (0, jsx_runtime_1.jsx)(OffthreadVideoForRendering_js_1.OffthreadVideoForRendering, { ...otherProps });
37
37
  }
38
- const { transparent, toneMapped, _remotionDebugSeeking, ...withoutTransparent } = otherProps;
39
- return ((0, jsx_runtime_1.jsx)(VideoForPreview_js_1.VideoForPreview, { _remotionInternalStack: stack !== null && stack !== void 0 ? stack : null, _remotionInternalNativeLoopPassed: false, _remotionDebugSeeking: _remotionDebugSeeking !== null && _remotionDebugSeeking !== void 0 ? _remotionDebugSeeking : false, onDuration: onDuration, onlyWarnForMediaSeekingError: true, pauseWhenBuffering: pauseWhenBuffering !== null && pauseWhenBuffering !== void 0 ? pauseWhenBuffering : false, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, ...withoutTransparent }));
38
+ const { transparent, toneMapped, _remotionDebugSeeking, onAutoPlayError, ...withoutTransparent } = otherProps;
39
+ return ((0, jsx_runtime_1.jsx)(VideoForPreview_js_1.VideoForPreview, { _remotionInternalStack: stack !== null && stack !== void 0 ? stack : null, _remotionInternalNativeLoopPassed: false, _remotionDebugSeeking: _remotionDebugSeeking !== null && _remotionDebugSeeking !== void 0 ? _remotionDebugSeeking : false, onDuration: onDuration, onlyWarnForMediaSeekingError: true, pauseWhenBuffering: pauseWhenBuffering !== null && pauseWhenBuffering !== void 0 ? pauseWhenBuffering : false, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, onAutoPlayError: onAutoPlayError !== null && onAutoPlayError !== void 0 ? onAutoPlayError : undefined, ...withoutTransparent }));
40
40
  };
41
41
  exports.OffthreadVideo = OffthreadVideo;
@@ -130,10 +130,19 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
130
130
  const blob = await res.blob();
131
131
  const url = URL.createObjectURL(blob);
132
132
  cleanup.push(() => URL.revokeObjectURL(url));
133
- setImageSrc(url);
134
- (0, delay_render_js_1.continueRender)(newHandle);
133
+ setImageSrc({
134
+ src: url,
135
+ handle: newHandle,
136
+ });
135
137
  }
136
138
  catch (err) {
139
+ // If component is unmounted, we should not throw
140
+ if (err.message.includes('aborted')) {
141
+ return;
142
+ }
143
+ if (controller.signal.aborted) {
144
+ return;
145
+ }
137
146
  if (onError) {
138
147
  onError(err);
139
148
  }
@@ -174,6 +183,7 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
174
183
  if (!imageSrc) {
175
184
  return null;
176
185
  }
177
- return ((0, jsx_runtime_1.jsx)(Img_js_1.Img, { src: imageSrc, className: className, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, ...props, onError: onErr }));
186
+ (0, delay_render_js_1.continueRender)(imageSrc.handle);
187
+ return ((0, jsx_runtime_1.jsx)(Img_js_1.Img, { src: imageSrc.src, className: className, delayRenderRetries: delayRenderRetries, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds, ...props, onError: onErr }));
178
188
  };
179
189
  exports.OffthreadVideoForRendering = OffthreadVideoForRendering;
@@ -17,6 +17,7 @@ export declare const Video: React.ForwardRefExoticComponent<Omit<Omit<React.Deta
17
17
  loopVolumeCurveBehavior?: import("../audio/use-audio-frame.js").LoopVolumeCurveBehavior | undefined;
18
18
  delayRenderRetries?: number | undefined;
19
19
  onError?: ((err: Error) => void) | undefined;
20
+ onAutoPlayError?: (() => void) | undefined;
20
21
  } & RemotionMainVideoProps & {
21
22
  /**
22
23
  * @deprecated For internal use only
@@ -19,7 +19,7 @@ const VideoForRendering_js_1 = require("./VideoForRendering.js");
19
19
  const duration_state_js_1 = require("./duration-state.js");
20
20
  const VideoForwardingFunction = (props, ref) => {
21
21
  var _a, _b;
22
- const { startFrom, endAt, name, pauseWhenBuffering, stack, _remotionInternalNativeLoopPassed, showInTimeline, ...otherProps } = props;
22
+ const { startFrom, endAt, name, pauseWhenBuffering, stack, _remotionInternalNativeLoopPassed, showInTimeline, onAutoPlayError, ...otherProps } = props;
23
23
  const { loop, _remotionDebugSeeking, ...propsOtherThanLoop } = props;
24
24
  const { fps } = (0, use_video_config_js_1.useVideoConfig)();
25
25
  const environment = (0, get_remotion_environment_js_1.getRemotionEnvironment)();
@@ -56,7 +56,7 @@ const VideoForwardingFunction = (props, ref) => {
56
56
  }
57
57
  return ((0, jsx_runtime_1.jsx)(VideoForPreview_js_1.VideoForPreview, { onlyWarnForMediaSeekingError: false, ...otherProps, ref: ref,
58
58
  // Proposal: Make this default to true in v5
59
- pauseWhenBuffering: pauseWhenBuffering !== null && pauseWhenBuffering !== void 0 ? pauseWhenBuffering : false, onDuration: onDuration, _remotionInternalStack: stack !== null && stack !== void 0 ? stack : null, _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed !== null && _remotionInternalNativeLoopPassed !== void 0 ? _remotionInternalNativeLoopPassed : false, _remotionDebugSeeking: _remotionDebugSeeking !== null && _remotionDebugSeeking !== void 0 ? _remotionDebugSeeking : false, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true }));
59
+ pauseWhenBuffering: pauseWhenBuffering !== null && pauseWhenBuffering !== void 0 ? pauseWhenBuffering : false, onDuration: onDuration, _remotionInternalStack: stack !== null && stack !== void 0 ? stack : null, _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed !== null && _remotionInternalNativeLoopPassed !== void 0 ? _remotionInternalNativeLoopPassed : false, _remotionDebugSeeking: _remotionDebugSeeking !== null && _remotionDebugSeeking !== void 0 ? _remotionDebugSeeking : false, showInTimeline: showInTimeline !== null && showInTimeline !== void 0 ? showInTimeline : true, onAutoPlayError: onAutoPlayError !== null && onAutoPlayError !== void 0 ? onAutoPlayError : undefined }));
60
60
  };
61
61
  /**
62
62
  * @description allows you to include a video file in your Remotion project. It wraps the native HTMLVideoElement.
@@ -19,7 +19,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
19
19
  const videoRef = (0, react_1.useRef)(null);
20
20
  const { volume, muted, playbackRate, onlyWarnForMediaSeekingError, src, onDuration,
21
21
  // @ts-expect-error
22
- acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, _remotionInternalNativeLoopPassed, _remotionInternalStack, _remotionDebugSeeking, style, pauseWhenBuffering, showInTimeline, loopVolumeCurveBehavior, onError, ...nativeProps } = props;
22
+ acceptableTimeShift, acceptableTimeShiftInSeconds, toneFrequency, name, _remotionInternalNativeLoopPassed, _remotionInternalStack, _remotionDebugSeeking, style, pauseWhenBuffering, showInTimeline, loopVolumeCurveBehavior, onError, onAutoPlayError, ...nativeProps } = props;
23
23
  const volumePropFrame = (0, use_audio_frame_js_1.useFrameForVolumeProp)(loopVolumeCurveBehavior !== null && loopVolumeCurveBehavior !== void 0 ? loopVolumeCurveBehavior : 'repeat');
24
24
  const { fps, durationInFrames } = (0, use_video_config_js_1.useVideoConfig)();
25
25
  const parentSequence = (0, react_1.useContext)(SequenceContext_js_1.SequenceContext);
@@ -44,6 +44,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
44
44
  stack: _remotionInternalStack,
45
45
  showInTimeline,
46
46
  premountDisplay: null,
47
+ onAutoPlayError: onAutoPlayError !== null && onAutoPlayError !== void 0 ? onAutoPlayError : null,
47
48
  });
48
49
  (0, use_sync_volume_with_media_tag_js_1.useSyncVolumeWithMediaTag)({
49
50
  volumePropFrame,
@@ -62,6 +63,7 @@ const VideoForDevelopmentRefForwardingFunction = (props, ref) => {
62
63
  isPremounting: Boolean(parentSequence === null || parentSequence === void 0 ? void 0 : parentSequence.premounting),
63
64
  pauseWhenBuffering,
64
65
  debugSeeking: _remotionDebugSeeking,
66
+ onAutoPlayError: onAutoPlayError !== null && onAutoPlayError !== void 0 ? onAutoPlayError : null,
65
67
  });
66
68
  const actualFrom = parentSequence ? parentSequence.relativeFrom : 0;
67
69
  const duration = parentSequence
@@ -13,6 +13,7 @@ export declare const VideoForRendering: ForwardRefExoticComponent<Omit<React.Det
13
13
  loopVolumeCurveBehavior?: import("../audio/use-audio-frame.js").LoopVolumeCurveBehavior | undefined;
14
14
  delayRenderRetries?: number | undefined;
15
15
  onError?: ((err: Error) => void) | undefined;
16
+ onAutoPlayError?: (() => void) | undefined;
16
17
  } & {
17
18
  readonly onDuration: (src: string, durationInSeconds: number) => void;
18
19
  } & RefAttributes<HTMLVideoElement>>;
@@ -23,6 +23,7 @@ export type RemotionVideoProps = Omit<React.DetailedHTMLProps<React.VideoHTMLAtt
23
23
  loopVolumeCurveBehavior?: LoopVolumeCurveBehavior;
24
24
  delayRenderRetries?: number;
25
25
  onError?: (err: Error) => void;
26
+ onAutoPlayError?: () => void;
26
27
  };
27
28
  type DeprecatedOffthreadVideoProps = {
28
29
  /**
@@ -54,5 +55,6 @@ export type OffthreadVideoProps = {
54
55
  */
55
56
  stack?: string;
56
57
  showInTimeline?: boolean;
58
+ onAutoPlayError?: null | (() => void);
57
59
  } & RemotionMainVideoProps & DeprecatedOffthreadVideoProps;
58
60
  export {};
@@ -138,7 +138,7 @@ function truthy(value) {
138
138
  }
139
139
 
140
140
  // src/version.ts
141
- var VERSION = "4.0.186";
141
+ var VERSION = "4.0.188";
142
142
 
143
143
  // src/multiple-versions-warning.ts
144
144
  var checkMultipleRemotionVersions = () => {
@@ -300,46 +300,14 @@ var useNonce = () => {
300
300
  // src/timeline-position-state.ts
301
301
  var exports_timeline_position_state = {};
302
302
  __export(exports_timeline_position_state, {
303
- useTimelineSetFrame: () => {
304
- {
305
- return useTimelineSetFrame;
306
- }
307
- },
308
- useTimelinePosition: () => {
309
- {
310
- return useTimelinePosition;
311
- }
312
- },
313
- usePlayingState: () => {
314
- {
315
- return usePlayingState;
316
- }
317
- },
318
- persistCurrentFrame: () => {
319
- {
320
- return persistCurrentFrame;
321
- }
322
- },
323
- getInitialFrameState: () => {
324
- {
325
- return getInitialFrameState;
326
- }
327
- },
328
- getFrameForComposition: () => {
329
- {
330
- return getFrameForComposition;
331
- }
332
- },
333
- TimelineContext: () => {
334
- {
335
- return TimelineContext;
336
- }
337
- },
338
- SetTimelineContext: () => {
339
- {
340
- return SetTimelineContext;
341
- }
342
- }
303
+ useTimelineSetFrame: () => useTimelineSetFrame,
304
+ useTimelinePosition: () => useTimelinePosition,
305
+ usePlayingState: () => usePlayingState,
306
+ persistCurrentFrame: () => persistCurrentFrame,
307
+ getInitialFrameState: () => getInitialFrameState,
308
+ getFrameForComposition: () => getFrameForComposition,
309
+ TimelineContext: () => TimelineContext,
310
+ SetTimelineContext: () => SetTimelineContext
343
311
  });
344
312
  import {createContext as createContext8, useContext as useContext7, useMemo as useMemo7} from "react";
345
313
 
@@ -2149,7 +2117,7 @@ var getAssetDisplayName = (filename) => {
2149
2117
  };
2150
2118
 
2151
2119
  // src/play-and-handle-not-allowed-error.ts
2152
- var playAndHandleNotAllowedError = (mediaRef, mediaType) => {
2120
+ var playAndHandleNotAllowedError = (mediaRef, mediaType, onAutoPlayError) => {
2153
2121
  const { current } = mediaRef;
2154
2122
  if (!current) {
2155
2123
  return;
@@ -2177,7 +2145,14 @@ var playAndHandleNotAllowedError = (mediaRef, mediaType) => {
2177
2145
  }
2178
2146
  console.log(`Could not play ${mediaType} due to following error: `, err);
2179
2147
  if (!current.muted) {
2148
+ if (onAutoPlayError) {
2149
+ onAutoPlayError();
2150
+ return;
2151
+ }
2180
2152
  console.log(`The video will be muted and we'll retry playing it.`);
2153
+ if (mediaType === "video" && getRemotionEnvironment().isPlayer) {
2154
+ console.log("Use onAutoPlayError() to handle this error yourself.");
2155
+ }
2181
2156
  current.muted = true;
2182
2157
  current.play();
2183
2158
  }
@@ -2232,7 +2207,8 @@ var useMediaInTimeline = ({
2232
2207
  id,
2233
2208
  stack,
2234
2209
  showInTimeline,
2235
- premountDisplay
2210
+ premountDisplay,
2211
+ onAutoPlayError
2236
2212
  }) => {
2237
2213
  const videoConfig = useVideoConfig();
2238
2214
  const { rootId, audioAndVideoTags } = useContext16(TimelineContext);
@@ -2327,14 +2303,14 @@ var useMediaInTimeline = ({
2327
2303
  if (!playing) {
2328
2304
  return;
2329
2305
  }
2330
- return playAndHandleNotAllowedError(mediaRef, mediaType);
2306
+ return playAndHandleNotAllowedError(mediaRef, mediaType, onAutoPlayError);
2331
2307
  }
2332
2308
  };
2333
2309
  audioAndVideoTags.current.push(tag);
2334
2310
  return () => {
2335
2311
  audioAndVideoTags.current = audioAndVideoTags.current.filter((a) => a.id !== id);
2336
2312
  };
2337
- }, [audioAndVideoTags, id, mediaRef, mediaType, playing]);
2313
+ }, [audioAndVideoTags, id, mediaRef, mediaType, onAutoPlayError, playing]);
2338
2314
  };
2339
2315
 
2340
2316
  // src/use-media-playback.ts
@@ -2430,7 +2406,8 @@ var useBufferState = () => {
2430
2406
  var useBufferUntilFirstFrame = ({
2431
2407
  mediaRef,
2432
2408
  mediaType,
2433
- onVariableFpsVideoDetected
2409
+ onVariableFpsVideoDetected,
2410
+ pauseWhenBuffering
2434
2411
  }) => {
2435
2412
  const bufferingRef = useRef3(false);
2436
2413
  const { delayPlayback } = useBufferState();
@@ -2438,6 +2415,9 @@ var useBufferUntilFirstFrame = ({
2438
2415
  if (mediaType !== "video") {
2439
2416
  return;
2440
2417
  }
2418
+ if (!pauseWhenBuffering) {
2419
+ return;
2420
+ }
2441
2421
  const current = mediaRef.current;
2442
2422
  if (!current) {
2443
2423
  return;
@@ -2471,7 +2451,13 @@ var useBufferUntilFirstFrame = ({
2471
2451
  });
2472
2452
  current.addEventListener("ended", onEndedOrPause, { once: true });
2473
2453
  current.addEventListener("pause", onEndedOrPause, { once: true });
2474
- }, [delayPlayback, mediaRef, mediaType, onVariableFpsVideoDetected]);
2454
+ }, [
2455
+ delayPlayback,
2456
+ mediaRef,
2457
+ mediaType,
2458
+ onVariableFpsVideoDetected,
2459
+ pauseWhenBuffering
2460
+ ]);
2475
2461
  return useMemo17(() => {
2476
2462
  return {
2477
2463
  isBuffering: () => bufferingRef.current,
@@ -2556,7 +2542,12 @@ var useMediaBuffering = ({
2556
2542
 
2557
2543
  // src/use-request-video-callback-time.ts
2558
2544
  import {useEffect as useEffect11, useRef as useRef4} from "react";
2559
- var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2545
+ var useRequestVideoCallbackTime = ({
2546
+ mediaRef,
2547
+ mediaType,
2548
+ lastSeek,
2549
+ onVariableFpsVideoDetected
2550
+ }) => {
2560
2551
  const currentTime = useRef4(null);
2561
2552
  useEffect11(() => {
2562
2553
  const { current } = mediaRef;
@@ -2582,6 +2573,13 @@ var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2582
2573
  return;
2583
2574
  }
2584
2575
  const cb = videoTag.requestVideoFrameCallback((_, info) => {
2576
+ if (currentTime.current !== null) {
2577
+ const difference = Math.abs(currentTime.current - info.mediaTime);
2578
+ const differenceToLastSeek = Math.abs(lastSeek.current === null ? Infinity : info.mediaTime - lastSeek.current);
2579
+ if (difference > 0.5 && differenceToLastSeek > 0.5 && info.mediaTime > currentTime.current) {
2580
+ onVariableFpsVideoDetected();
2581
+ }
2582
+ }
2585
2583
  currentTime.current = info.mediaTime;
2586
2584
  request();
2587
2585
  });
@@ -2596,7 +2594,7 @@ var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2596
2594
  return () => {
2597
2595
  cancel();
2598
2596
  };
2599
- }, [mediaRef, mediaType]);
2597
+ }, [lastSeek, mediaRef, mediaType, onVariableFpsVideoDetected]);
2600
2598
  return currentTime;
2601
2599
  };
2602
2600
 
@@ -2855,7 +2853,8 @@ var useMediaPlayback = ({
2855
2853
  acceptableTimeshift,
2856
2854
  pauseWhenBuffering,
2857
2855
  isPremounting,
2858
- debugSeeking
2856
+ debugSeeking,
2857
+ onAutoPlayError
2859
2858
  }) => {
2860
2859
  const { playbackRate: globalPlaybackRate } = useContext18(TimelineContext);
2861
2860
  const frame = useCurrentFrame();
@@ -2865,10 +2864,26 @@ var useMediaPlayback = ({
2865
2864
  const { fps } = useVideoConfig();
2866
2865
  const mediaStartsAt = useMediaStartsAt();
2867
2866
  const lastSeekDueToShift = useRef6(null);
2867
+ const lastSeek = useRef6(null);
2868
2868
  if (!buffering3) {
2869
2869
  throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
2870
2870
  }
2871
- const currentTime = useRequestVideoCallbackTime(mediaRef, mediaType);
2871
+ const isVariableFpsVideoMap = useRef6({});
2872
+ const onVariableFpsVideoDetected = useCallback7(() => {
2873
+ if (!src) {
2874
+ return;
2875
+ }
2876
+ if (debugSeeking) {
2877
+ console.log(`Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
2878
+ }
2879
+ isVariableFpsVideoMap.current[src] = true;
2880
+ }, [debugSeeking, src]);
2881
+ const currentTime = useRequestVideoCallbackTime({
2882
+ mediaRef,
2883
+ mediaType,
2884
+ lastSeek,
2885
+ onVariableFpsVideoDetected
2886
+ });
2872
2887
  const desiredUnclampedTime = getMediaTime({
2873
2888
  frame,
2874
2889
  playbackRate: localPlaybackRate,
@@ -2880,20 +2895,11 @@ var useMediaPlayback = ({
2880
2895
  shouldBuffer: pauseWhenBuffering,
2881
2896
  isPremounting
2882
2897
  });
2883
- const isVariableFpsVideoMap = useRef6({});
2884
- const onVariableFpsVideoDetected = useCallback7(() => {
2885
- if (!src) {
2886
- return;
2887
- }
2888
- if (debugSeeking) {
2889
- console.log(`Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
2890
- }
2891
- isVariableFpsVideoMap.current[src] = true;
2892
- }, [debugSeeking, src]);
2893
2898
  const { bufferUntilFirstFrame, isBuffering } = useBufferUntilFirstFrame({
2894
2899
  mediaRef,
2895
2900
  mediaType,
2896
- onVariableFpsVideoDetected
2901
+ onVariableFpsVideoDetected,
2902
+ pauseWhenBuffering
2897
2903
  });
2898
2904
  const playbackRate = localPlaybackRate * globalPlaybackRate;
2899
2905
  const acceptableTimeShiftButLessThanDuration = (() => {
@@ -2955,15 +2961,17 @@ var useMediaPlayback = ({
2955
2961
  shouldBeTime,
2956
2962
  isTime: mediaTagTime,
2957
2963
  rvcTime,
2958
- timeShift
2964
+ timeShift,
2965
+ isVariableFpsVideo
2959
2966
  });
2960
2967
  }
2961
2968
  seek(mediaRef, shouldBeTime);
2969
+ lastSeek.current = shouldBeTime;
2962
2970
  lastSeekDueToShift.current = shouldBeTime;
2963
2971
  if (playing && !isVariableFpsVideo) {
2964
2972
  bufferUntilFirstFrame(shouldBeTime);
2965
2973
  if (mediaRef.current.paused) {
2966
- playAndHandleNotAllowedError(mediaRef, mediaType);
2974
+ playAndHandleNotAllowedError(mediaRef, mediaType, onAutoPlayError);
2967
2975
  }
2968
2976
  }
2969
2977
  if (!onlyWarnForMediaSeekingError) {
@@ -2978,14 +2986,16 @@ var useMediaPlayback = ({
2978
2986
  if (!playing || isSomethingElseBuffering) {
2979
2987
  if (makesSenseToSeek) {
2980
2988
  seek(mediaRef, shouldBeTime);
2989
+ lastSeek.current = shouldBeTime;
2981
2990
  }
2982
2991
  return;
2983
2992
  }
2984
2993
  if (mediaRef.current.paused && !mediaRef.current.ended || absoluteFrame === 0) {
2985
2994
  if (makesSenseToSeek) {
2986
2995
  seek(mediaRef, shouldBeTime);
2996
+ lastSeek.current = shouldBeTime;
2987
2997
  }
2988
- playAndHandleNotAllowedError(mediaRef, mediaType);
2998
+ playAndHandleNotAllowedError(mediaRef, mediaType, onAutoPlayError);
2989
2999
  if (!isVariableFpsVideo) {
2990
3000
  bufferUntilFirstFrame(shouldBeTime);
2991
3001
  }
@@ -3005,7 +3015,8 @@ var useMediaPlayback = ({
3005
3015
  onlyWarnForMediaSeekingError,
3006
3016
  playbackRate,
3007
3017
  playing,
3008
- src
3018
+ src,
3019
+ onAutoPlayError
3009
3020
  ]);
3010
3021
  };
3011
3022
 
@@ -3231,7 +3242,7 @@ var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) =>
3231
3242
  }, [rerenderAudios]);
3232
3243
  const playAllAudios = useCallback8(() => {
3233
3244
  refs.forEach((ref) => {
3234
- playAndHandleNotAllowedError(ref.ref, "audio");
3245
+ playAndHandleNotAllowedError(ref.ref, "audio", null);
3235
3246
  });
3236
3247
  }, [refs]);
3237
3248
  const value = useMemo19(() => {
@@ -3394,7 +3405,8 @@ var AudioForDevelopmentForwardRefFunction = (props, ref) => {
3394
3405
  id: timelineId,
3395
3406
  stack: _remotionInternalStack,
3396
3407
  showInTimeline,
3397
- premountDisplay: null
3408
+ premountDisplay: null,
3409
+ onAutoPlayError: null
3398
3410
  });
3399
3411
  useMediaPlayback({
3400
3412
  mediaRef: audioRef,
@@ -3405,7 +3417,8 @@ var AudioForDevelopmentForwardRefFunction = (props, ref) => {
3405
3417
  acceptableTimeshift: acceptableTimeShiftInSeconds ?? DEFAULT_ACCEPTABLE_TIMESHIFT,
3406
3418
  isPremounting: Boolean(sequenceContext?.premounting),
3407
3419
  pauseWhenBuffering,
3408
- debugSeeking: _remotionDebugSeeking
3420
+ debugSeeking: _remotionDebugSeeking,
3421
+ onAutoPlayError: null
3409
3422
  });
3410
3423
  useImperativeHandle3(ref, () => {
3411
3424
  return audioRef.current;
@@ -4322,18 +4335,18 @@ class Easing {
4322
4335
  return (t) => t * t * ((s + 1) * t - s);
4323
4336
  }
4324
4337
  static bounce(t) {
4325
- if (t < 0.36363636363636365) {
4338
+ if (t < 1 / 2.75) {
4326
4339
  return 7.5625 * t * t;
4327
4340
  }
4328
- if (t < 0.7272727272727273) {
4329
- const t2_ = t - 0.5454545454545454;
4341
+ if (t < 2 / 2.75) {
4342
+ const t2_ = t - 1.5 / 2.75;
4330
4343
  return 7.5625 * t2_ * t2_ + 0.75;
4331
4344
  }
4332
- if (t < 0.9090909090909091) {
4333
- const t2_ = t - 0.8181818181818182;
4345
+ if (t < 2.5 / 2.75) {
4346
+ const t2_ = t - 2.25 / 2.75;
4334
4347
  return 7.5625 * t2_ * t2_ + 0.9375;
4335
4348
  }
4336
- const t2 = t - 0.9545454545454546;
4349
+ const t2 = t - 2.625 / 2.75;
4337
4350
  return 7.5625 * t2 * t2 + 0.984375;
4338
4351
  }
4339
4352
  static bezier(x1, y1, x2, y2) {
@@ -4548,21 +4561,9 @@ var Img = forwardRef7(ImgRefForwarding);
4548
4561
  // src/default-css.ts
4549
4562
  var exports_default_css = {};
4550
4563
  __export(exports_default_css, {
4551
- makeDefaultPreviewCSS: () => {
4552
- {
4553
- return makeDefaultPreviewCSS;
4554
- }
4555
- },
4556
- injectCSS: () => {
4557
- {
4558
- return injectCSS;
4559
- }
4560
- },
4561
- OFFTHREAD_VIDEO_CLASS_NAME: () => {
4562
- {
4563
- return OFFTHREAD_VIDEO_CLASS_NAME;
4564
- }
4565
- }
4564
+ makeDefaultPreviewCSS: () => makeDefaultPreviewCSS,
4565
+ injectCSS: () => injectCSS,
4566
+ OFFTHREAD_VIDEO_CLASS_NAME: () => OFFTHREAD_VIDEO_CLASS_NAME
4566
4567
  });
4567
4568
  var injected = {};
4568
4569
  var injectCSS = (css) => {
@@ -5050,23 +5051,23 @@ var hue2rgb = function(p, q, t) {
5050
5051
  if (t > 1) {
5051
5052
  t -= 1;
5052
5053
  }
5053
- if (t < 0.16666666666666666) {
5054
+ if (t < 1 / 6) {
5054
5055
  return p + (q - p) * 6 * t;
5055
5056
  }
5056
- if (t < 0.5) {
5057
+ if (t < 1 / 2) {
5057
5058
  return q;
5058
5059
  }
5059
- if (t < 0.6666666666666666) {
5060
- return p + (q - p) * (0.6666666666666666 - t) * 6;
5060
+ if (t < 2 / 3) {
5061
+ return p + (q - p) * (2 / 3 - t) * 6;
5061
5062
  }
5062
5063
  return p;
5063
5064
  };
5064
5065
  var hslToRgb = function(h, s, l) {
5065
5066
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
5066
5067
  const p = 2 * l - q;
5067
- const r = hue2rgb(p, q, h + 0.3333333333333333);
5068
+ const r = hue2rgb(p, q, h + 1 / 3);
5068
5069
  const g = hue2rgb(p, q, h);
5069
- const b2 = hue2rgb(p, q, h - 0.3333333333333333);
5070
+ const b2 = hue2rgb(p, q, h - 1 / 3);
5070
5071
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b2 * 255) << 8;
5071
5072
  };
5072
5073
  var parse255 = function(str) {
@@ -5898,9 +5899,17 @@ var OffthreadVideoForRendering = ({
5898
5899
  const blob = await res.blob();
5899
5900
  const url = URL.createObjectURL(blob);
5900
5901
  cleanup.push(() => URL.revokeObjectURL(url));
5901
- setImageSrc(url);
5902
- continueRender(newHandle);
5902
+ setImageSrc({
5903
+ src: url,
5904
+ handle: newHandle
5905
+ });
5903
5906
  } catch (err) {
5907
+ if (err.message.includes("aborted")) {
5908
+ return;
5909
+ }
5910
+ if (controller.signal.aborted) {
5911
+ return;
5912
+ }
5904
5913
  if (onError) {
5905
5914
  onError(err);
5906
5915
  } else {
@@ -5937,8 +5946,9 @@ var OffthreadVideoForRendering = ({
5937
5946
  if (!imageSrc) {
5938
5947
  return null;
5939
5948
  }
5949
+ continueRender(imageSrc.handle);
5940
5950
  return jsx29(Img, {
5941
- src: imageSrc,
5951
+ src: imageSrc.src,
5942
5952
  className,
5943
5953
  delayRenderRetries,
5944
5954
  delayRenderTimeoutInMilliseconds,
@@ -5981,6 +5991,7 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
5981
5991
  showInTimeline,
5982
5992
  loopVolumeCurveBehavior,
5983
5993
  onError,
5994
+ onAutoPlayError,
5984
5995
  ...nativeProps
5985
5996
  } = props2;
5986
5997
  const volumePropFrame = useFrameForVolumeProp(loopVolumeCurveBehavior ?? "repeat");
@@ -6006,7 +6017,8 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
6006
6017
  id: timelineId,
6007
6018
  stack: _remotionInternalStack,
6008
6019
  showInTimeline,
6009
- premountDisplay: null
6020
+ premountDisplay: null,
6021
+ onAutoPlayError: onAutoPlayError ?? null
6010
6022
  });
6011
6023
  useSyncVolumeWithMediaTag({
6012
6024
  volumePropFrame,
@@ -6024,7 +6036,8 @@ var VideoForDevelopmentRefForwardingFunction = (props2, ref) => {
6024
6036
  acceptableTimeshift: acceptableTimeShiftInSeconds ?? DEFAULT_ACCEPTABLE_TIMESHIFT,
6025
6037
  isPremounting: Boolean(parentSequence?.premounting),
6026
6038
  pauseWhenBuffering,
6027
- debugSeeking: _remotionDebugSeeking
6039
+ debugSeeking: _remotionDebugSeeking,
6040
+ onAutoPlayError: onAutoPlayError ?? null
6028
6041
  });
6029
6042
  const actualFrom = parentSequence ? parentSequence.relativeFrom : 0;
6030
6043
  const duration = parentSequence ? Math.min(parentSequence.durationInFrames, durationInFrames) : durationInFrames;
@@ -6164,6 +6177,7 @@ var OffthreadVideo = (props2) => {
6164
6177
  transparent,
6165
6178
  toneMapped,
6166
6179
  _remotionDebugSeeking,
6180
+ onAutoPlayError,
6167
6181
  ...withoutTransparent
6168
6182
  } = otherProps;
6169
6183
  return jsx31(VideoForPreview, {
@@ -6174,6 +6188,7 @@ var OffthreadVideo = (props2) => {
6174
6188
  onlyWarnForMediaSeekingError: true,
6175
6189
  pauseWhenBuffering: pauseWhenBuffering ?? false,
6176
6190
  showInTimeline: showInTimeline ?? true,
6191
+ onAutoPlayError: onAutoPlayError ?? undefined,
6177
6192
  ...withoutTransparent
6178
6193
  });
6179
6194
  };
@@ -6484,6 +6499,7 @@ var VideoForwardingFunction = (props2, ref) => {
6484
6499
  stack,
6485
6500
  _remotionInternalNativeLoopPassed,
6486
6501
  showInTimeline,
6502
+ onAutoPlayError,
6487
6503
  ...otherProps
6488
6504
  } = props2;
6489
6505
  const { loop: loop4, _remotionDebugSeeking, ...propsOtherThanLoop } = props2;
@@ -6553,7 +6569,8 @@ var VideoForwardingFunction = (props2, ref) => {
6553
6569
  _remotionInternalStack: stack ?? null,
6554
6570
  _remotionInternalNativeLoopPassed: _remotionInternalNativeLoopPassed ?? false,
6555
6571
  _remotionDebugSeeking: _remotionDebugSeeking ?? false,
6556
- showInTimeline: showInTimeline ?? true
6572
+ showInTimeline: showInTimeline ?? true,
6573
+ onAutoPlayError: onAutoPlayError ?? undefined
6557
6574
  });
6558
6575
  };
6559
6576
  var Video = forwardRef11(VideoForwardingFunction);
@@ -318,23 +318,23 @@ var hue2rgb = function(p, q, t) {
318
318
  if (t > 1) {
319
319
  t -= 1;
320
320
  }
321
- if (t < 0.16666666666666666) {
321
+ if (t < 1 / 6) {
322
322
  return p + (q - p) * 6 * t;
323
323
  }
324
- if (t < 0.5) {
324
+ if (t < 1 / 2) {
325
325
  return q;
326
326
  }
327
- if (t < 0.6666666666666666) {
328
- return p + (q - p) * (0.6666666666666666 - t) * 6;
327
+ if (t < 2 / 3) {
328
+ return p + (q - p) * (2 / 3 - t) * 6;
329
329
  }
330
330
  return p;
331
331
  };
332
332
  var hslToRgb = function(h, s, l) {
333
333
  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
334
334
  const p = 2 * l - q;
335
- const r = hue2rgb(p, q, h + 0.3333333333333333);
335
+ const r = hue2rgb(p, q, h + 1 / 3);
336
336
  const g = hue2rgb(p, q, h);
337
- const b = hue2rgb(p, q, h - 0.3333333333333333);
337
+ const b = hue2rgb(p, q, h - 1 / 3);
338
338
  return Math.round(r * 255) << 24 | Math.round(g * 255) << 16 | Math.round(b * 255) << 8;
339
339
  };
340
340
  var parse255 = function(str) {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.186";
2
+ var VERSION = "4.0.188";
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.186",
6
+ "version": "4.0.188",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",