remotion 4.0.85 → 4.0.87

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.
@@ -14,10 +14,10 @@ type AddBlock = (block: Block) => {
14
14
  unblock: () => void;
15
15
  };
16
16
  type BufferManager = {
17
- blocks: Block[];
18
17
  addBlock: AddBlock;
19
18
  listenForBuffering: ListenForBuffering;
20
19
  listenForResume: ListenForResume;
20
+ buffering: React.MutableRefObject<boolean>;
21
21
  };
22
22
  export declare const BufferingContextReact: React.Context<BufferManager | null>;
23
23
  export declare const BufferingProvider: React.FC<{
@@ -26,47 +26,50 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.BufferingProvider = exports.BufferingContextReact = void 0;
27
27
  const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  const react_1 = __importStar(require("react"));
29
- const createBufferManager = () => {
30
- let blocks = [];
31
- let onBufferingCallback = [];
32
- let onResumeCallback = [];
33
- const addBlock = (block) => {
34
- blocks.push(block);
35
- onBufferingCallback.forEach((callback) => callback());
29
+ const useBufferManager = () => {
30
+ const [blocks, setBlocks] = (0, react_1.useState)([]);
31
+ const [onBufferingCallbacks, setOnBufferingCallbacks] = (0, react_1.useState)([]);
32
+ const [onResumeCallbacks, setOnResumeCallbacks] = (0, react_1.useState)([]);
33
+ const buffering = (0, react_1.useRef)(false);
34
+ const addBlock = (0, react_1.useCallback)((block) => {
35
+ setBlocks((b) => [...b, block]);
36
36
  return {
37
37
  unblock: () => {
38
- blocks = blocks.filter((b) => b !== block);
38
+ setBlocks((b) => b.filter((bx) => bx !== block));
39
39
  },
40
40
  };
41
- };
42
- const listenForBuffering = (callback) => {
43
- onBufferingCallback.push(callback);
41
+ }, []);
42
+ const listenForBuffering = (0, react_1.useCallback)((callback) => {
43
+ setOnBufferingCallbacks((c) => [...c, callback]);
44
44
  return {
45
45
  remove: () => {
46
- onBufferingCallback = onBufferingCallback.filter((c) => c !== callback);
46
+ setOnBufferingCallbacks((c) => c.filter((cb) => cb !== callback));
47
47
  },
48
48
  };
49
- };
50
- const listenForResume = (callback) => {
51
- onResumeCallback.push(callback);
49
+ }, []);
50
+ const listenForResume = (0, react_1.useCallback)((callback) => {
51
+ setOnResumeCallbacks((c) => [...c, callback]);
52
52
  return {
53
53
  remove: () => {
54
- onResumeCallback = onResumeCallback.filter((c) => c !== callback);
54
+ setOnResumeCallbacks((c) => c.filter((cb) => cb !== callback));
55
55
  },
56
56
  };
57
- };
58
- return {
59
- blocks,
60
- addBlock,
61
- listenForBuffering,
62
- listenForResume,
63
- };
57
+ }, []);
58
+ (0, react_1.useEffect)(() => {
59
+ if (blocks.length > 0) {
60
+ onBufferingCallbacks.forEach((c) => c());
61
+ }
62
+ else {
63
+ onResumeCallbacks.forEach((c) => c());
64
+ }
65
+ }, [blocks, onBufferingCallbacks, onResumeCallbacks]);
66
+ return (0, react_1.useMemo)(() => {
67
+ return { addBlock, listenForBuffering, listenForResume, buffering };
68
+ }, [addBlock, buffering, listenForBuffering, listenForResume]);
64
69
  };
65
70
  exports.BufferingContextReact = react_1.default.createContext(null);
66
71
  const BufferingProvider = ({ children }) => {
67
- const [bufferManager] = (0, react_1.useState)(() => {
68
- return createBufferManager();
69
- });
72
+ const bufferManager = useBufferManager();
70
73
  return ((0, jsx_runtime_1.jsx)(exports.BufferingContextReact.Provider, { value: bufferManager, children: children }));
71
74
  };
72
75
  exports.BufferingProvider = BufferingProvider;
@@ -0,0 +1 @@
1
+ export declare const getTimelineClipName: (children: React.ReactNode) => string;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTimelineClipName = void 0;
4
+ const react_1 = require("react");
5
+ const HIDDEN_NAMES = ['__WEBPACK_DEFAULT_EXPORT__'];
6
+ const getTimelineClipName = (children) => {
7
+ var _a;
8
+ const tree = (_a = react_1.Children.map(children, (ch) => {
9
+ if (!(0, react_1.isValidElement)(ch)) {
10
+ return null;
11
+ }
12
+ // Must be name, not ID
13
+ const name = typeof ch.type !== 'string' && ch.type.name;
14
+ if (name && !HIDDEN_NAMES.includes(name)) {
15
+ return name;
16
+ }
17
+ if (ch.props.children) {
18
+ const chName = (0, exports.getTimelineClipName)(ch.props.children);
19
+ return chName;
20
+ }
21
+ return null;
22
+ })) === null || _a === void 0 ? void 0 : _a.filter(Boolean);
23
+ return (tree === null || tree === void 0 ? void 0 : tree.length) ? tree[0] : '';
24
+ };
25
+ exports.getTimelineClipName = getTimelineClipName;
@@ -8,13 +8,13 @@ const useBuffer = () => {
8
8
  if (!buffer) {
9
9
  throw new TypeError('Can only use useBuffer() inside a Remotion composition');
10
10
  }
11
- return {
11
+ return (0, react_1.useMemo)(() => ({
12
12
  delayPlayback: () => {
13
13
  const { unblock } = buffer.addBlock({
14
14
  id: String(Math.random()),
15
15
  });
16
16
  return { unblock };
17
17
  },
18
- };
18
+ }), [buffer]);
19
19
  };
20
20
  exports.useBuffer = useBuffer;
@@ -57,12 +57,10 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
57
57
  mediaRef.current.playbackRate = playbackRateToSet;
58
58
  }
59
59
  const desiredUnclampedTime = (0, get_current_time_js_1.getMediaTime)({
60
- fps,
61
60
  frame,
62
- src,
63
61
  playbackRate: localPlaybackRate,
64
62
  startFrom: -mediaStartsAt,
65
- mediaType,
63
+ fps,
66
64
  });
67
65
  const { duration } = mediaRef.current;
68
66
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration)
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.85";
1
+ export declare const VERSION = "4.0.87";
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Automatically generated on publish
5
- exports.VERSION = '4.0.85';
5
+ exports.VERSION = '4.0.87';
@@ -15,8 +15,8 @@ const timeline_position_state_js_1 = require("../timeline-position-state.js");
15
15
  const use_current_frame_js_1 = require("../use-current-frame.js");
16
16
  const use_unsafe_video_config_js_1 = require("../use-unsafe-video-config.js");
17
17
  const volume_prop_js_1 = require("../volume-prop.js");
18
- const warn_about_non_seekable_media_js_1 = require("../warn-about-non-seekable-media.js");
19
18
  const get_current_time_js_1 = require("./get-current-time.js");
19
+ const seek_until_right_js_1 = require("./seek-until-right.js");
20
20
  const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, toneFrequency, name, acceptableTimeShiftInSeconds, ...props }, ref) => {
21
21
  const absoluteFrame = (0, timeline_position_state_js_1.useTimelinePosition)();
22
22
  const frame = (0, use_current_frame_js_1.useCurrentFrame)();
@@ -96,16 +96,12 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
96
96
  if (!current) {
97
97
  return;
98
98
  }
99
- const currentTime = (() => {
100
- return (0, get_current_time_js_1.getMediaTime)({
101
- fps: videoConfig.fps,
102
- frame,
103
- src: props.src,
104
- playbackRate: playbackRate || 1,
105
- startFrom: -mediaStartsAt,
106
- mediaType: 'video',
107
- });
108
- })();
99
+ const currentTime = (0, get_current_time_js_1.getMediaTime)({
100
+ frame,
101
+ playbackRate: playbackRate || 1,
102
+ startFrom: -mediaStartsAt,
103
+ fps: videoConfig.fps,
104
+ });
109
105
  const handle = (0, delay_render_js_1.delayRender)(`Rendering <Video /> with src="${props.src}"`);
110
106
  if (process.env.NODE_ENV === 'test') {
111
107
  (0, delay_render_js_1.continueRender)(handle);
@@ -124,25 +120,13 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
124
120
  current.removeEventListener('loadeddata', loadedDataHandler);
125
121
  };
126
122
  }
127
- current.currentTime = currentTime;
128
- const seekedHandler = () => {
129
- (0, warn_about_non_seekable_media_js_1.warnAboutNonSeekableMedia)(current, 'exception');
130
- if (window.navigator.platform.startsWith('Mac')) {
131
- // Improve me: This is ensures frame perfectness but slows down render.
132
- // Please see this issue for context: https://github.com/remotion-dev/remotion/issues/200
133
- // Only affects macOS since it uses VideoToolbox decoding.
134
- setTimeout(() => {
135
- (0, delay_render_js_1.continueRender)(handle);
136
- }, 100);
137
- }
138
- else {
139
- (0, delay_render_js_1.continueRender)(handle);
140
- }
141
- };
142
- current.addEventListener('seeked', seekedHandler, { once: true });
143
123
  const endedHandler = () => {
144
124
  (0, delay_render_js_1.continueRender)(handle);
145
125
  };
126
+ const seek = (0, seek_until_right_js_1.seekToTimeMultipleUntilRight)(current, currentTime, videoConfig.fps);
127
+ seek.prom.then(() => {
128
+ (0, delay_render_js_1.continueRender)(handle);
129
+ });
146
130
  current.addEventListener('ended', endedHandler, { once: true });
147
131
  const errorHandler = () => {
148
132
  var _a;
@@ -162,9 +146,9 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
162
146
  current.addEventListener('error', errorHandler, { once: true });
163
147
  // If video skips to another frame or unmounts, we clear the created handle
164
148
  return () => {
149
+ seek.cancel();
165
150
  current.removeEventListener('ended', endedHandler);
166
151
  current.removeEventListener('error', errorHandler);
167
- current.removeEventListener('seeked', seekedHandler);
168
152
  (0, delay_render_js_1.continueRender)(handle);
169
153
  };
170
154
  }, [
@@ -3,11 +3,9 @@ export declare const getExpectedMediaFrameUncorrected: ({ frame, playbackRate, s
3
3
  playbackRate: number;
4
4
  startFrom: number;
5
5
  }) => number;
6
- export declare const getMediaTime: ({ fps, frame, src, playbackRate, startFrom, mediaType, }: {
6
+ export declare const getMediaTime: ({ fps, frame, playbackRate, startFrom, }: {
7
7
  fps: number;
8
8
  frame: number;
9
- src: string;
10
9
  playbackRate: number;
11
10
  startFrom: number;
12
- mediaType: 'video' | 'audio';
13
11
  }) => number;
@@ -7,26 +7,13 @@ const getExpectedMediaFrameUncorrected = ({ frame, playbackRate, startFrom, }) =
7
7
  return (0, interpolate_js_1.interpolate)(frame, [-1, startFrom, startFrom + 1], [-1, startFrom, startFrom + playbackRate]);
8
8
  };
9
9
  exports.getExpectedMediaFrameUncorrected = getExpectedMediaFrameUncorrected;
10
- const getMediaTime = ({ fps, frame, src, playbackRate, startFrom, mediaType, }) => {
10
+ const getMediaTime = ({ fps, frame, playbackRate, startFrom, }) => {
11
11
  const expectedFrame = (0, exports.getExpectedMediaFrameUncorrected)({
12
12
  frame,
13
13
  playbackRate,
14
14
  startFrom,
15
15
  });
16
- const isChrome = typeof window !== 'undefined' &&
17
- window.navigator.userAgent.match(/Chrome\/([0-9]+)/);
18
- if (isChrome &&
19
- Number(isChrome[1]) < 112 &&
20
- mediaType === 'video' &&
21
- src.endsWith('.mp4')) {
22
- // In Chrome, for MP4s, if 30fps, the first frame is still displayed at 0.033333
23
- // even though after that it increases by 0.033333333 each.
24
- // So frame = 0 in Remotion is like frame = 1 for the browser
25
- return (expectedFrame + 1) / fps;
26
- }
27
- // For WebM videos, we need to add a little bit of shift to get the right frame.
28
16
  const msPerFrame = 1000 / fps;
29
- const msShift = msPerFrame / 2;
30
- return (expectedFrame * msPerFrame + msShift) / 1000;
17
+ return (expectedFrame * msPerFrame) / 1000;
31
18
  };
32
19
  exports.getMediaTime = getMediaTime;
@@ -0,0 +1,8 @@
1
+ export declare const seekToTime: (element: HTMLVideoElement, desiredTime: number) => {
2
+ wait: Promise<number>;
3
+ cancel: () => void;
4
+ };
5
+ export declare const seekToTimeMultipleUntilRight: (element: HTMLVideoElement, desiredTime: number, fps: number) => {
6
+ prom: Promise<void>;
7
+ cancel: () => void;
8
+ };
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.seekToTimeMultipleUntilRight = exports.seekToTime = void 0;
4
+ const seekToTime = (element, desiredTime) => {
5
+ element.currentTime = desiredTime;
6
+ let cancel;
7
+ let cancelSeeked = null;
8
+ const prom = new Promise((resolve) => {
9
+ cancel = element.requestVideoFrameCallback((now, metadata) => {
10
+ const displayIn = metadata.expectedDisplayTime - now;
11
+ if (displayIn <= 0) {
12
+ resolve(metadata.mediaTime);
13
+ return;
14
+ }
15
+ setTimeout(() => {
16
+ resolve(metadata.mediaTime);
17
+ }, displayIn + 150);
18
+ });
19
+ });
20
+ const waitForSeekedEvent = new Promise((resolve) => {
21
+ const onDone = () => {
22
+ resolve();
23
+ };
24
+ element.addEventListener('seeked', onDone, {
25
+ once: true,
26
+ });
27
+ cancelSeeked = () => {
28
+ element.removeEventListener('seeked', onDone);
29
+ };
30
+ });
31
+ return {
32
+ wait: Promise.all([prom, waitForSeekedEvent]).then(([time]) => time),
33
+ cancel: () => {
34
+ cancelSeeked === null || cancelSeeked === void 0 ? void 0 : cancelSeeked();
35
+ element.cancelVideoFrameCallback(cancel);
36
+ },
37
+ };
38
+ };
39
+ exports.seekToTime = seekToTime;
40
+ const seekToTimeMultipleUntilRight = (element, desiredTime, fps) => {
41
+ const threshold = 1 / fps / 2;
42
+ let currentCancel = () => undefined;
43
+ const prom = new Promise((resolve, reject) => {
44
+ const firstSeek = (0, exports.seekToTime)(element, desiredTime + threshold);
45
+ firstSeek.wait.then((seekedTo) => {
46
+ const difference = Math.abs(desiredTime - seekedTo);
47
+ if (difference < threshold) {
48
+ return resolve();
49
+ }
50
+ const sign = desiredTime > seekedTo ? 1 : -1;
51
+ const newSeek = (0, exports.seekToTime)(element, seekedTo + threshold * sign);
52
+ currentCancel = newSeek.cancel;
53
+ newSeek.wait
54
+ .then((newTime) => {
55
+ const newDifference = Math.abs(desiredTime - newTime);
56
+ if (newDifference < threshold) {
57
+ return resolve();
58
+ }
59
+ const thirdSeek = (0, exports.seekToTime)(element, desiredTime);
60
+ currentCancel = thirdSeek.cancel;
61
+ thirdSeek.wait.then(() => {
62
+ resolve();
63
+ });
64
+ })
65
+ .catch((err) => {
66
+ reject(err);
67
+ });
68
+ });
69
+ currentCancel = firstSeek.cancel;
70
+ });
71
+ return {
72
+ prom,
73
+ cancel: () => {
74
+ currentCancel();
75
+ },
76
+ };
77
+ };
78
+ exports.seekToTimeMultipleUntilRight = seekToTimeMultipleUntilRight;
@@ -132,7 +132,7 @@ function truthy(value) {
132
132
  }
133
133
 
134
134
  // Automatically generated on publish
135
- const VERSION = '4.0.85';
135
+ const VERSION = '4.0.87';
136
136
 
137
137
  const checkMultipleRemotionVersions = () => {
138
138
  if (typeof globalThis === 'undefined') {
@@ -1843,27 +1843,14 @@ function interpolate(input, inputRange, outputRange, options) {
1843
1843
  const getExpectedMediaFrameUncorrected = ({ frame, playbackRate, startFrom, }) => {
1844
1844
  return interpolate(frame, [-1, startFrom, startFrom + 1], [-1, startFrom, startFrom + playbackRate]);
1845
1845
  };
1846
- const getMediaTime = ({ fps, frame, src, playbackRate, startFrom, mediaType, }) => {
1846
+ const getMediaTime = ({ fps, frame, playbackRate, startFrom, }) => {
1847
1847
  const expectedFrame = getExpectedMediaFrameUncorrected({
1848
1848
  frame,
1849
1849
  playbackRate,
1850
1850
  startFrom,
1851
1851
  });
1852
- const isChrome = typeof window !== 'undefined' &&
1853
- window.navigator.userAgent.match(/Chrome\/([0-9]+)/);
1854
- if (isChrome &&
1855
- Number(isChrome[1]) < 112 &&
1856
- mediaType === 'video' &&
1857
- src.endsWith('.mp4')) {
1858
- // In Chrome, for MP4s, if 30fps, the first frame is still displayed at 0.033333
1859
- // even though after that it increases by 0.033333333 each.
1860
- // So frame = 0 in Remotion is like frame = 1 for the browser
1861
- return (expectedFrame + 1) / fps;
1862
- }
1863
- // For WebM videos, we need to add a little bit of shift to get the right frame.
1864
1852
  const msPerFrame = 1000 / fps;
1865
- const msShift = msPerFrame / 2;
1866
- return (expectedFrame * msPerFrame + msShift) / 1000;
1853
+ return (expectedFrame * msPerFrame) / 1000;
1867
1854
  };
1868
1855
 
1869
1856
  const toSeconds = (time, fps) => {
@@ -2009,12 +1996,10 @@ const useMediaPlayback = ({ mediaRef, src, mediaType, playbackRate: localPlaybac
2009
1996
  mediaRef.current.playbackRate = playbackRateToSet;
2010
1997
  }
2011
1998
  const desiredUnclampedTime = getMediaTime({
2012
- fps,
2013
1999
  frame,
2014
- src,
2015
2000
  playbackRate: localPlaybackRate,
2016
2001
  startFrom: -mediaStartsAt,
2017
- mediaType,
2002
+ fps,
2018
2003
  });
2019
2004
  const { duration } = mediaRef.current;
2020
2005
  const shouldBeTime = !Number.isNaN(duration) && Number.isFinite(duration)
@@ -4785,6 +4770,80 @@ const OffthreadVideo = (props) => {
4785
4770
  return (jsx(VideoForDevelopment, { _remotionInternalStack: stack !== null && stack !== void 0 ? stack : null, _remotionInternalNativeLoopPassed: false, onDuration: onDuration, onlyWarnForMediaSeekingError: true, ...withoutTransparent }));
4786
4771
  };
4787
4772
 
4773
+ const seekToTime = (element, desiredTime) => {
4774
+ element.currentTime = desiredTime;
4775
+ let cancel;
4776
+ let cancelSeeked = null;
4777
+ const prom = new Promise((resolve) => {
4778
+ cancel = element.requestVideoFrameCallback((now, metadata) => {
4779
+ const displayIn = metadata.expectedDisplayTime - now;
4780
+ if (displayIn <= 0) {
4781
+ resolve(metadata.mediaTime);
4782
+ return;
4783
+ }
4784
+ setTimeout(() => {
4785
+ resolve(metadata.mediaTime);
4786
+ }, displayIn + 150);
4787
+ });
4788
+ });
4789
+ const waitForSeekedEvent = new Promise((resolve) => {
4790
+ const onDone = () => {
4791
+ resolve();
4792
+ };
4793
+ element.addEventListener('seeked', onDone, {
4794
+ once: true,
4795
+ });
4796
+ cancelSeeked = () => {
4797
+ element.removeEventListener('seeked', onDone);
4798
+ };
4799
+ });
4800
+ return {
4801
+ wait: Promise.all([prom, waitForSeekedEvent]).then(([time]) => time),
4802
+ cancel: () => {
4803
+ cancelSeeked === null || cancelSeeked === void 0 ? void 0 : cancelSeeked();
4804
+ element.cancelVideoFrameCallback(cancel);
4805
+ },
4806
+ };
4807
+ };
4808
+ const seekToTimeMultipleUntilRight = (element, desiredTime, fps) => {
4809
+ const threshold = 1 / fps / 2;
4810
+ let currentCancel = () => undefined;
4811
+ const prom = new Promise((resolve, reject) => {
4812
+ const firstSeek = seekToTime(element, desiredTime + threshold);
4813
+ firstSeek.wait.then((seekedTo) => {
4814
+ const difference = Math.abs(desiredTime - seekedTo);
4815
+ if (difference < threshold) {
4816
+ return resolve();
4817
+ }
4818
+ const sign = desiredTime > seekedTo ? 1 : -1;
4819
+ const newSeek = seekToTime(element, seekedTo + threshold * sign);
4820
+ currentCancel = newSeek.cancel;
4821
+ newSeek.wait
4822
+ .then((newTime) => {
4823
+ const newDifference = Math.abs(desiredTime - newTime);
4824
+ if (newDifference < threshold) {
4825
+ return resolve();
4826
+ }
4827
+ const thirdSeek = seekToTime(element, desiredTime);
4828
+ currentCancel = thirdSeek.cancel;
4829
+ thirdSeek.wait.then(() => {
4830
+ resolve();
4831
+ });
4832
+ })
4833
+ .catch((err) => {
4834
+ reject(err);
4835
+ });
4836
+ });
4837
+ currentCancel = firstSeek.cancel;
4838
+ });
4839
+ return {
4840
+ prom,
4841
+ cancel: () => {
4842
+ currentCancel();
4843
+ },
4844
+ };
4845
+ };
4846
+
4788
4847
  const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAmplificationDuringRender, playbackRate, onDuration, toneFrequency, name, acceptableTimeShiftInSeconds, ...props }, ref) => {
4789
4848
  const absoluteFrame = useTimelinePosition();
4790
4849
  const frame = useCurrentFrame();
@@ -4864,16 +4923,12 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
4864
4923
  if (!current) {
4865
4924
  return;
4866
4925
  }
4867
- const currentTime = (() => {
4868
- return getMediaTime({
4869
- fps: videoConfig.fps,
4870
- frame,
4871
- src: props.src,
4872
- playbackRate: playbackRate || 1,
4873
- startFrom: -mediaStartsAt,
4874
- mediaType: 'video',
4875
- });
4876
- })();
4926
+ const currentTime = getMediaTime({
4927
+ frame,
4928
+ playbackRate: playbackRate || 1,
4929
+ startFrom: -mediaStartsAt,
4930
+ fps: videoConfig.fps,
4931
+ });
4877
4932
  const handle = delayRender(`Rendering <Video /> with src="${props.src}"`);
4878
4933
  if (process.env.NODE_ENV === 'test') {
4879
4934
  continueRender(handle);
@@ -4892,25 +4947,13 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
4892
4947
  current.removeEventListener('loadeddata', loadedDataHandler);
4893
4948
  };
4894
4949
  }
4895
- current.currentTime = currentTime;
4896
- const seekedHandler = () => {
4897
- warnAboutNonSeekableMedia(current, 'exception');
4898
- if (window.navigator.platform.startsWith('Mac')) {
4899
- // Improve me: This is ensures frame perfectness but slows down render.
4900
- // Please see this issue for context: https://github.com/remotion-dev/remotion/issues/200
4901
- // Only affects macOS since it uses VideoToolbox decoding.
4902
- setTimeout(() => {
4903
- continueRender(handle);
4904
- }, 100);
4905
- }
4906
- else {
4907
- continueRender(handle);
4908
- }
4909
- };
4910
- current.addEventListener('seeked', seekedHandler, { once: true });
4911
4950
  const endedHandler = () => {
4912
4951
  continueRender(handle);
4913
4952
  };
4953
+ const seek = seekToTimeMultipleUntilRight(current, currentTime, videoConfig.fps);
4954
+ seek.prom.then(() => {
4955
+ continueRender(handle);
4956
+ });
4914
4957
  current.addEventListener('ended', endedHandler, { once: true });
4915
4958
  const errorHandler = () => {
4916
4959
  var _a;
@@ -4930,9 +4973,9 @@ const VideoForRenderingForwardFunction = ({ onError, volume: volumeProp, allowAm
4930
4973
  current.addEventListener('error', errorHandler, { once: true });
4931
4974
  // If video skips to another frame or unmounts, we clear the created handle
4932
4975
  return () => {
4976
+ seek.cancel();
4933
4977
  current.removeEventListener('ended', endedHandler);
4934
4978
  current.removeEventListener('error', errorHandler);
4935
- current.removeEventListener('seeked', seekedHandler);
4936
4979
  continueRender(handle);
4937
4980
  };
4938
4981
  }, [
@@ -1,4 +1,4 @@
1
1
  // Automatically generated on publish
2
- const VERSION = '4.0.85';
2
+ const VERSION = '4.0.87';
3
3
 
4
4
  export { VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remotion",
3
- "version": "4.0.85",
3
+ "version": "4.0.87",
4
4
  "description": "Render videos in React",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",