remotion 4.0.187 → 4.0.189

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
+ }
@@ -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
+ }
@@ -1,5 +1,6 @@
1
1
  /// <reference types="bun-types" />
2
2
  /// <reference types="react" />
3
+ import './_check-rsc.js';
3
4
  import './asset-types.js';
4
5
  import type { Codec } from './codec.js';
5
6
  import type { TRenderAsset } from './CompositionManager.js';
package/dist/cjs/index.js CHANGED
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.Config = exports.Experimental = exports.watchStaticFile = exports.useCurrentScale = exports.useCurrentFrame = exports.useBufferState = exports.staticFile = exports.Series = exports.Sequence = exports.registerRoot = exports.prefetch = exports.random = exports.interpolate = exports.Loop = exports.interpolateColors = exports.Img = exports.getStaticFiles = exports.getRemotionEnvironment = exports.delayRender = exports.continueRender = exports.getInputProps = exports.Composition = exports.cancelRender = exports.Artifact = void 0;
18
+ require("./_check-rsc.js");
18
19
  require("./asset-types.js");
19
20
  const Clipper_js_1 = require("./Clipper.js");
20
21
  const enable_sequence_stack_traces_js_1 = require("./enable-sequence-stack-traces.js");
@@ -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,9 +144,11 @@ 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);
@@ -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,6 +182,7 @@ 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
187
  (0, play_and_handle_not_allowed_error_js_1.playAndHandleNotAllowedError)(mediaRef, mediaType, onAutoPlayError);
177
188
  if (!isVariableFpsVideo) {
@@ -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.187";
6
+ export declare const VERSION = "4.0.189";
@@ -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.187';
10
+ exports.VERSION = '4.0.189';
@@ -136,6 +136,13 @@ const OffthreadVideoForRendering = ({ onError, volume: volumeProp, playbackRate,
136
136
  });
137
137
  }
138
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
+ }
139
146
  if (onError) {
140
147
  onError(err);
141
148
  }
@@ -9,15 +9,32 @@ var __export = (target, all) => {
9
9
  });
10
10
  };
11
11
 
12
+ // src/_check-rsc.ts
13
+ import {createContext} from "react";
14
+ if (typeof createContext !== "function") {
15
+ const err = [
16
+ 'Remotion requires React.createContext, but it is "undefined".',
17
+ 'If you are in a React Server Component, turn it into a client component by adding "use client" at the top of the file.',
18
+ "",
19
+ "Before:",
20
+ ' import {useCurrentFrame} from "remotion";',
21
+ "",
22
+ "After:",
23
+ ' "use client";',
24
+ ' import {useCurrentFrame} from "remotion";'
25
+ ];
26
+ throw new Error(err.join("\n"));
27
+ }
28
+
12
29
  // src/Clipper.tsx
13
30
  import {useContext, useEffect} from "react";
14
31
 
15
32
  // src/NativeLayers.tsx
16
- import {createContext, useLayoutEffect, useMemo, useState} from "react";
33
+ import {createContext as createContext2, useLayoutEffect, useMemo, useState} from "react";
17
34
  import {
18
35
  jsx
19
36
  } from "react/jsx-runtime";
20
- var NativeLayersContext = createContext({
37
+ var NativeLayersContext = createContext2({
21
38
  setClipRegion: () => {
22
39
  throw new Error("NativeLayers not set");
23
40
  },
@@ -115,11 +132,11 @@ var addSequenceStackTraces = (component) => {
115
132
  };
116
133
 
117
134
  // src/is-player.tsx
118
- import {createContext as createContext2, useContext as useContext2} from "react";
135
+ import {createContext as createContext3, useContext as useContext2} from "react";
119
136
  import {
120
137
  jsx as jsx2
121
138
  } from "react/jsx-runtime";
122
- var IsPlayerContext = createContext2(false);
139
+ var IsPlayerContext = createContext3(false);
123
140
  var IsPlayerContextProvider = ({
124
141
  children
125
142
  }) => {
@@ -138,7 +155,7 @@ function truthy(value) {
138
155
  }
139
156
 
140
157
  // src/version.ts
141
- var VERSION = "4.0.187";
158
+ var VERSION = "4.0.189";
142
159
 
143
160
  // src/multiple-versions-warning.ts
144
161
  var checkMultipleRemotionVersions = () => {
@@ -221,8 +238,8 @@ var AbsoluteFillRefForwarding = (props, ref) => {
221
238
  var AbsoluteFill = forwardRef(AbsoluteFillRefForwarding);
222
239
 
223
240
  // src/SequenceContext.tsx
224
- import {createContext as createContext3} from "react";
225
- var SequenceContext = createContext3(null);
241
+ import {createContext as createContext4} from "react";
242
+ var SequenceContext = createContext4(null);
226
243
 
227
244
  // src/SequenceManager.tsx
228
245
  import React3, {useCallback, useMemo as useMemo3, useState as useState2} from "react";
@@ -278,8 +295,8 @@ var SequenceManagerProvider = ({ children }) => {
278
295
  };
279
296
 
280
297
  // src/nonce.ts
281
- import {createContext as createContext4, useContext as useContext4, useEffect as useEffect3, useRef, useState as useState3} from "react";
282
- var NonceContext = createContext4({
298
+ import {createContext as createContext5, useContext as useContext4, useEffect as useEffect3, useRef, useState as useState3} from "react";
299
+ var NonceContext = createContext5({
283
300
  getNonce: () => 0,
284
301
  fastRefreshes: 0
285
302
  });
@@ -309,14 +326,14 @@ __export(exports_timeline_position_state, {
309
326
  TimelineContext: () => TimelineContext,
310
327
  SetTimelineContext: () => SetTimelineContext
311
328
  });
312
- import {createContext as createContext8, useContext as useContext7, useMemo as useMemo7} from "react";
329
+ import {createContext as createContext9, useContext as useContext7, useMemo as useMemo7} from "react";
313
330
 
314
331
  // src/use-video.ts
315
332
  import {useContext as useContext6, useMemo as useMemo6} from "react";
316
333
 
317
334
  // src/CompositionManagerContext.tsx
318
- import {createContext as createContext5} from "react";
319
- var CompositionManager = createContext5({
335
+ import {createContext as createContext6} from "react";
336
+ var CompositionManager = createContext6({
320
337
  compositions: [],
321
338
  registerComposition: () => {
322
339
  return;
@@ -346,7 +363,7 @@ var CompositionManager = createContext5({
346
363
 
347
364
  // src/ResolveCompositionConfig.tsx
348
365
  import {
349
- createContext as createContext7,
366
+ createContext as createContext8,
350
367
  createRef,
351
368
  useCallback as useCallback3,
352
369
  useContext as useContext5,
@@ -358,7 +375,7 @@ useState as useState4
358
375
 
359
376
  // src/EditorProps.tsx
360
377
  import React4, {
361
- createContext as createContext6,
378
+ createContext as createContext7,
362
379
  useCallback as useCallback2,
363
380
  useImperativeHandle,
364
381
  useMemo as useMemo4
@@ -366,7 +383,7 @@ useMemo as useMemo4
366
383
  import {
367
384
  jsx as jsx5
368
385
  } from "react/jsx-runtime";
369
- var EditorPropsContext = createContext6({
386
+ var EditorPropsContext = createContext7({
370
387
  props: {},
371
388
  updateProps: () => {
372
389
  throw new Error("Not implemented");
@@ -774,7 +791,7 @@ var resolveVideoConfigOrCatch = (params) => {
774
791
  import {
775
792
  jsx as jsx6
776
793
  } from "react/jsx-runtime";
777
- var ResolveCompositionContext = createContext7(null);
794
+ var ResolveCompositionContext = createContext8(null);
778
795
  var resolveCompositionsRef = createRef();
779
796
  var needsResolution = (composition) => {
780
797
  return Boolean(composition.calculateMetadata);
@@ -1126,7 +1143,7 @@ var useVideo = () => {
1126
1143
  };
1127
1144
 
1128
1145
  // src/timeline-position-state.ts
1129
- var TimelineContext = createContext8({
1146
+ var TimelineContext = createContext9({
1130
1147
  frame: {},
1131
1148
  playing: false,
1132
1149
  playbackRate: 1,
@@ -1139,7 +1156,7 @@ var TimelineContext = createContext8({
1139
1156
  },
1140
1157
  audioAndVideoTags: { current: [] }
1141
1158
  });
1142
- var SetTimelineContext = createContext8({
1159
+ var SetTimelineContext = createContext9({
1143
1160
  setFrame: () => {
1144
1161
  throw new Error("default");
1145
1162
  },
@@ -1192,11 +1209,11 @@ var usePlayingState = () => {
1192
1209
  import {useContext as useContext9} from "react";
1193
1210
 
1194
1211
  // src/CanUseRemotionHooks.tsx
1195
- import {createContext as createContext9} from "react";
1212
+ import {createContext as createContext10} from "react";
1196
1213
  import {
1197
1214
  jsx as jsx7
1198
1215
  } from "react/jsx-runtime";
1199
- var CanUseRemotionHooks = createContext9(false);
1216
+ var CanUseRemotionHooks = createContext10(false);
1200
1217
  var CanUseRemotionHooksProvider = ({ children }) => {
1201
1218
  return jsx7(CanUseRemotionHooks.Provider, {
1202
1219
  value: true,
@@ -1521,7 +1538,7 @@ import {useContext as useContext13, useEffect as useEffect6, useState as useStat
1521
1538
 
1522
1539
  // src/RenderAssetManager.tsx
1523
1540
  import {
1524
- createContext as createContext10,
1541
+ createContext as createContext11,
1525
1542
  useCallback as useCallback4,
1526
1543
  useLayoutEffect as useLayoutEffect2,
1527
1544
  useMemo as useMemo11,
@@ -1560,7 +1577,7 @@ var validateRenderAsset = (artifact) => {
1560
1577
  import {
1561
1578
  jsx as jsx10
1562
1579
  } from "react/jsx-runtime";
1563
- var RenderAssetManager = createContext10({
1580
+ var RenderAssetManager = createContext11({
1564
1581
  registerRenderAsset: () => {
1565
1582
  return;
1566
1583
  },
@@ -1719,11 +1736,11 @@ var isErrorLike = (err) => {
1719
1736
  };
1720
1737
 
1721
1738
  // src/loop/index.tsx
1722
- import React8, {createContext as createContext11, useMemo as useMemo12} from "react";
1739
+ import React8, {createContext as createContext12, useMemo as useMemo12} from "react";
1723
1740
  import {
1724
1741
  jsx as jsx11
1725
1742
  } from "react/jsx-runtime";
1726
- var LoopContext = createContext11(null);
1743
+ var LoopContext = createContext12(null);
1727
1744
  var useLoop = () => {
1728
1745
  return React8.useContext(LoopContext);
1729
1746
  };
@@ -1782,11 +1799,11 @@ Loop.useLoop = useLoop;
1782
1799
  import {useContext as useContext14} from "react";
1783
1800
 
1784
1801
  // src/prefetch-state.tsx
1785
- import {createContext as createContext12, useEffect as useEffect7, useState as useState8} from "react";
1802
+ import {createContext as createContext13, useEffect as useEffect7, useState as useState8} from "react";
1786
1803
  import {
1787
1804
  jsx as jsx12
1788
1805
  } from "react/jsx-runtime";
1789
- var PreloadContext = createContext12({});
1806
+ var PreloadContext = createContext13({});
1790
1807
  var preloads = {};
1791
1808
  var updaters = [];
1792
1809
  var setPreloads = (updater) => {
@@ -2002,7 +2019,7 @@ var validateStartFromProps = (startFrom, endAt) => {
2002
2019
  };
2003
2020
 
2004
2021
  // src/video/duration-state.tsx
2005
- import {createContext as createContext13, useMemo as useMemo13, useReducer} from "react";
2022
+ import {createContext as createContext14, useMemo as useMemo13, useReducer} from "react";
2006
2023
  import {
2007
2024
  jsx as jsx13
2008
2025
  } from "react/jsx-runtime";
@@ -2022,7 +2039,7 @@ var durationReducer = (state, action) => {
2022
2039
  return state;
2023
2040
  }
2024
2041
  };
2025
- var DurationsContext = createContext13({
2042
+ var DurationsContext = createContext14({
2026
2043
  durations: {},
2027
2044
  setDurations: () => {
2028
2045
  throw new Error("context missing");
@@ -2406,7 +2423,8 @@ var useBufferState = () => {
2406
2423
  var useBufferUntilFirstFrame = ({
2407
2424
  mediaRef,
2408
2425
  mediaType,
2409
- onVariableFpsVideoDetected
2426
+ onVariableFpsVideoDetected,
2427
+ pauseWhenBuffering
2410
2428
  }) => {
2411
2429
  const bufferingRef = useRef3(false);
2412
2430
  const { delayPlayback } = useBufferState();
@@ -2414,6 +2432,9 @@ var useBufferUntilFirstFrame = ({
2414
2432
  if (mediaType !== "video") {
2415
2433
  return;
2416
2434
  }
2435
+ if (!pauseWhenBuffering) {
2436
+ return;
2437
+ }
2417
2438
  const current = mediaRef.current;
2418
2439
  if (!current) {
2419
2440
  return;
@@ -2447,7 +2468,13 @@ var useBufferUntilFirstFrame = ({
2447
2468
  });
2448
2469
  current.addEventListener("ended", onEndedOrPause, { once: true });
2449
2470
  current.addEventListener("pause", onEndedOrPause, { once: true });
2450
- }, [delayPlayback, mediaRef, mediaType, onVariableFpsVideoDetected]);
2471
+ }, [
2472
+ delayPlayback,
2473
+ mediaRef,
2474
+ mediaType,
2475
+ onVariableFpsVideoDetected,
2476
+ pauseWhenBuffering
2477
+ ]);
2451
2478
  return useMemo17(() => {
2452
2479
  return {
2453
2480
  isBuffering: () => bufferingRef.current,
@@ -2532,7 +2559,12 @@ var useMediaBuffering = ({
2532
2559
 
2533
2560
  // src/use-request-video-callback-time.ts
2534
2561
  import {useEffect as useEffect11, useRef as useRef4} from "react";
2535
- var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2562
+ var useRequestVideoCallbackTime = ({
2563
+ mediaRef,
2564
+ mediaType,
2565
+ lastSeek,
2566
+ onVariableFpsVideoDetected
2567
+ }) => {
2536
2568
  const currentTime = useRef4(null);
2537
2569
  useEffect11(() => {
2538
2570
  const { current } = mediaRef;
@@ -2558,6 +2590,13 @@ var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2558
2590
  return;
2559
2591
  }
2560
2592
  const cb = videoTag.requestVideoFrameCallback((_, info) => {
2593
+ if (currentTime.current !== null) {
2594
+ const difference = Math.abs(currentTime.current - info.mediaTime);
2595
+ const differenceToLastSeek = Math.abs(lastSeek.current === null ? Infinity : info.mediaTime - lastSeek.current);
2596
+ if (difference > 0.5 && differenceToLastSeek > 0.5 && info.mediaTime > currentTime.current) {
2597
+ onVariableFpsVideoDetected();
2598
+ }
2599
+ }
2561
2600
  currentTime.current = info.mediaTime;
2562
2601
  request();
2563
2602
  });
@@ -2572,7 +2611,7 @@ var useRequestVideoCallbackTime = (mediaRef, mediaType) => {
2572
2611
  return () => {
2573
2612
  cancel();
2574
2613
  };
2575
- }, [mediaRef, mediaType]);
2614
+ }, [lastSeek, mediaRef, mediaType, onVariableFpsVideoDetected]);
2576
2615
  return currentTime;
2577
2616
  };
2578
2617
 
@@ -2842,10 +2881,26 @@ var useMediaPlayback = ({
2842
2881
  const { fps } = useVideoConfig();
2843
2882
  const mediaStartsAt = useMediaStartsAt();
2844
2883
  const lastSeekDueToShift = useRef6(null);
2884
+ const lastSeek = useRef6(null);
2845
2885
  if (!buffering3) {
2846
2886
  throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
2847
2887
  }
2848
- const currentTime = useRequestVideoCallbackTime(mediaRef, mediaType);
2888
+ const isVariableFpsVideoMap = useRef6({});
2889
+ const onVariableFpsVideoDetected = useCallback7(() => {
2890
+ if (!src) {
2891
+ return;
2892
+ }
2893
+ if (debugSeeking) {
2894
+ console.log(`Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
2895
+ }
2896
+ isVariableFpsVideoMap.current[src] = true;
2897
+ }, [debugSeeking, src]);
2898
+ const currentTime = useRequestVideoCallbackTime({
2899
+ mediaRef,
2900
+ mediaType,
2901
+ lastSeek,
2902
+ onVariableFpsVideoDetected
2903
+ });
2849
2904
  const desiredUnclampedTime = getMediaTime({
2850
2905
  frame,
2851
2906
  playbackRate: localPlaybackRate,
@@ -2857,20 +2912,11 @@ var useMediaPlayback = ({
2857
2912
  shouldBuffer: pauseWhenBuffering,
2858
2913
  isPremounting
2859
2914
  });
2860
- const isVariableFpsVideoMap = useRef6({});
2861
- const onVariableFpsVideoDetected = useCallback7(() => {
2862
- if (!src) {
2863
- return;
2864
- }
2865
- if (debugSeeking) {
2866
- console.log(`Detected ${src} as a variable FPS video. Disabling buffering while seeking.`);
2867
- }
2868
- isVariableFpsVideoMap.current[src] = true;
2869
- }, [debugSeeking, src]);
2870
2915
  const { bufferUntilFirstFrame, isBuffering } = useBufferUntilFirstFrame({
2871
2916
  mediaRef,
2872
2917
  mediaType,
2873
- onVariableFpsVideoDetected
2918
+ onVariableFpsVideoDetected,
2919
+ pauseWhenBuffering
2874
2920
  });
2875
2921
  const playbackRate = localPlaybackRate * globalPlaybackRate;
2876
2922
  const acceptableTimeShiftButLessThanDuration = (() => {
@@ -2932,10 +2978,12 @@ var useMediaPlayback = ({
2932
2978
  shouldBeTime,
2933
2979
  isTime: mediaTagTime,
2934
2980
  rvcTime,
2935
- timeShift
2981
+ timeShift,
2982
+ isVariableFpsVideo
2936
2983
  });
2937
2984
  }
2938
2985
  seek(mediaRef, shouldBeTime);
2986
+ lastSeek.current = shouldBeTime;
2939
2987
  lastSeekDueToShift.current = shouldBeTime;
2940
2988
  if (playing && !isVariableFpsVideo) {
2941
2989
  bufferUntilFirstFrame(shouldBeTime);
@@ -2955,12 +3003,14 @@ var useMediaPlayback = ({
2955
3003
  if (!playing || isSomethingElseBuffering) {
2956
3004
  if (makesSenseToSeek) {
2957
3005
  seek(mediaRef, shouldBeTime);
3006
+ lastSeek.current = shouldBeTime;
2958
3007
  }
2959
3008
  return;
2960
3009
  }
2961
3010
  if (mediaRef.current.paused && !mediaRef.current.ended || absoluteFrame === 0) {
2962
3011
  if (makesSenseToSeek) {
2963
3012
  seek(mediaRef, shouldBeTime);
3013
+ lastSeek.current = shouldBeTime;
2964
3014
  }
2965
3015
  playAndHandleNotAllowedError(mediaRef, mediaType, onAutoPlayError);
2966
3016
  if (!isVariableFpsVideo) {
@@ -3045,12 +3095,12 @@ var useSyncVolumeWithMediaTag = ({
3045
3095
  };
3046
3096
 
3047
3097
  // src/volume-position-state.ts
3048
- import {createContext as createContext14, useContext as useContext19, useMemo as useMemo18} from "react";
3049
- var MediaVolumeContext = createContext14({
3098
+ import {createContext as createContext15, useContext as useContext19, useMemo as useMemo18} from "react";
3099
+ var MediaVolumeContext = createContext15({
3050
3100
  mediaMuted: false,
3051
3101
  mediaVolume: 1
3052
3102
  });
3053
- var SetMediaVolumeContext = createContext14({
3103
+ var SetMediaVolumeContext = createContext15({
3054
3104
  setMediaMuted: () => {
3055
3105
  throw new Error("default");
3056
3106
  },
@@ -3075,7 +3125,7 @@ var useMediaMutedState = () => {
3075
3125
 
3076
3126
  // src/audio/shared-audio-tags.tsx
3077
3127
  import React12, {
3078
- createContext as createContext15,
3128
+ createContext as createContext16,
3079
3129
  createRef as createRef2,
3080
3130
  useCallback as useCallback8,
3081
3131
  useContext as useContext20,
@@ -3114,7 +3164,7 @@ var didPropChange = (key, newProp, prevProp) => {
3114
3164
  }
3115
3165
  return true;
3116
3166
  };
3117
- var SharedAudioContext = createContext15(null);
3167
+ var SharedAudioContext = createContext16(null);
3118
3168
  var SharedAudioContextProvider = ({ children, numberOfAudioTags, component }) => {
3119
3169
  const audios = useRef7([]);
3120
3170
  const [initialNumberOfAudioTags] = useState13(numberOfAudioTags);
@@ -3733,7 +3783,7 @@ import {Suspense, useContext as useContext25, useEffect as useEffect19, useMemo
3733
3783
  import {createPortal} from "react-dom";
3734
3784
 
3735
3785
  // src/Folder.tsx
3736
- import {createContext as createContext16, useContext as useContext24, useEffect as useEffect18, useMemo as useMemo22} from "react";
3786
+ import {createContext as createContext17, useContext as useContext24, useEffect as useEffect18, useMemo as useMemo22} from "react";
3737
3787
 
3738
3788
  // src/validation/validate-folder-name.ts
3739
3789
  var getRegex = () => /^([a-zA-Z0-9-\u4E00-\u9FFF])+$/g;
@@ -3755,7 +3805,7 @@ var invalidFolderNameErrorMessage = `Folder name must match ${String(getRegex())
3755
3805
  import {
3756
3806
  jsx as jsx19
3757
3807
  } from "react/jsx-runtime";
3758
- var FolderContext = createContext16({
3808
+ var FolderContext = createContext17({
3759
3809
  folderName: null,
3760
3810
  parentName: null
3761
3811
  });
@@ -4747,9 +4797,9 @@ var setupEnvVariables = () => {
4747
4797
  };
4748
4798
 
4749
4799
  // src/use-current-scale.ts
4750
- import React22, {createContext as createContext17} from "react";
4800
+ import React22, {createContext as createContext18} from "react";
4751
4801
  var CurrentScaleContext = React22.createContext(null);
4752
- var PreviewSizeContext = createContext17({
4802
+ var PreviewSizeContext = createContext18({
4753
4803
  setSize: () => {
4754
4804
  return;
4755
4805
  },
@@ -5373,11 +5423,11 @@ var flattenChildren = (children) => {
5373
5423
  };
5374
5424
 
5375
5425
  // src/series/is-inside-series.tsx
5376
- import React25, {createContext as createContext18} from "react";
5426
+ import React25, {createContext as createContext19} from "react";
5377
5427
  import {
5378
5428
  jsx as jsx27
5379
5429
  } from "react/jsx-runtime";
5380
- var IsInsideSeriesContext = createContext18(false);
5430
+ var IsInsideSeriesContext = createContext19(false);
5381
5431
  var IsInsideSeriesContainer = ({ children }) => {
5382
5432
  return jsx27(IsInsideSeriesContext.Provider, {
5383
5433
  value: true,
@@ -5871,6 +5921,12 @@ var OffthreadVideoForRendering = ({
5871
5921
  handle: newHandle
5872
5922
  });
5873
5923
  } catch (err) {
5924
+ if (err.message.includes("aborted")) {
5925
+ return;
5926
+ }
5927
+ if (controller.signal.aborted) {
5928
+ return;
5929
+ }
5874
5930
  if (onError) {
5875
5931
  onError(err);
5876
5932
  } else {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "4.0.187";
2
+ var VERSION = "4.0.189";
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.187",
6
+ "version": "4.0.189",
7
7
  "description": "Make videos programmatically",
8
8
  "main": "dist/cjs/index.js",
9
9
  "types": "dist/cjs/index.d.ts",