@remotion/media 4.0.390 → 4.0.392

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.
Files changed (76) hide show
  1. package/dist/audio/audio-for-preview.js +2 -0
  2. package/dist/audio/audio-preview-iterator.d.ts +3 -2
  3. package/dist/audio/audio-preview-iterator.js +2 -2
  4. package/dist/audio-for-rendering.d.ts +3 -0
  5. package/dist/audio-for-rendering.js +94 -0
  6. package/dist/audio-iterator-manager.d.ts +5 -1
  7. package/dist/audio-iterator-manager.js +21 -5
  8. package/dist/audio.d.ts +3 -0
  9. package/dist/audio.js +60 -0
  10. package/dist/audiodata-to-array.d.ts +0 -0
  11. package/dist/audiodata-to-array.js +1 -0
  12. package/dist/convert-audiodata/data-types.d.ts +1 -0
  13. package/dist/convert-audiodata/data-types.js +22 -0
  14. package/dist/convert-audiodata/is-planar-format.d.ts +1 -0
  15. package/dist/convert-audiodata/is-planar-format.js +3 -0
  16. package/dist/convert-audiodata/log-audiodata.d.ts +1 -0
  17. package/dist/convert-audiodata/log-audiodata.js +8 -0
  18. package/dist/convert-audiodata/trim-audiodata.d.ts +0 -0
  19. package/dist/convert-audiodata/trim-audiodata.js +1 -0
  20. package/dist/deserialized-audiodata.d.ts +15 -0
  21. package/dist/deserialized-audiodata.js +26 -0
  22. package/dist/esm/index.mjs +185 -27
  23. package/dist/extract-audio.d.ts +7 -0
  24. package/dist/extract-audio.js +98 -0
  25. package/dist/extract-frame-via-broadcast-channel.d.ts +15 -0
  26. package/dist/extract-frame-via-broadcast-channel.js +104 -0
  27. package/dist/extract-frame.d.ts +27 -0
  28. package/dist/extract-frame.js +21 -0
  29. package/dist/extrct-audio.d.ts +7 -0
  30. package/dist/extrct-audio.js +94 -0
  31. package/dist/get-frames-since-keyframe.d.ts +22 -0
  32. package/dist/get-frames-since-keyframe.js +41 -0
  33. package/dist/get-time-in-seconds.d.ts +8 -0
  34. package/dist/get-time-in-seconds.js +15 -0
  35. package/dist/is-network-error.d.ts +6 -0
  36. package/dist/is-network-error.js +17 -0
  37. package/dist/keyframe-bank.d.ts +25 -0
  38. package/dist/keyframe-bank.js +120 -0
  39. package/dist/keyframe-manager.d.ts +23 -0
  40. package/dist/keyframe-manager.js +170 -0
  41. package/dist/log.d.ts +10 -0
  42. package/dist/log.js +33 -0
  43. package/dist/media-player.d.ts +4 -1
  44. package/dist/media-player.js +56 -17
  45. package/dist/new-video-for-rendering.d.ts +3 -0
  46. package/dist/new-video-for-rendering.js +108 -0
  47. package/dist/new-video.d.ts +3 -0
  48. package/dist/new-video.js +37 -0
  49. package/dist/prewarm-iterator-for-looping.d.ts +17 -0
  50. package/dist/prewarm-iterator-for-looping.js +56 -0
  51. package/dist/props.d.ts +29 -0
  52. package/dist/props.js +1 -0
  53. package/dist/remember-actual-matroska-timestamps.d.ts +4 -0
  54. package/dist/remember-actual-matroska-timestamps.js +19 -0
  55. package/dist/serialize-videoframe.d.ts +0 -0
  56. package/dist/serialize-videoframe.js +1 -0
  57. package/dist/video/media-player.d.ts +62 -0
  58. package/dist/video/media-player.js +361 -0
  59. package/dist/video/new-video-for-preview.d.ts +10 -0
  60. package/dist/video/new-video-for-preview.js +108 -0
  61. package/dist/video/timeout-utils.d.ts +2 -0
  62. package/dist/video/timeout-utils.js +18 -0
  63. package/dist/video/video-for-preview.js +2 -0
  64. package/dist/video/video-preview-iterator.d.ts +3 -2
  65. package/dist/video/video-preview-iterator.js +2 -2
  66. package/dist/video-extraction/media-player.d.ts +64 -0
  67. package/dist/video-extraction/media-player.js +501 -0
  68. package/dist/video-extraction/new-video-for-preview.d.ts +10 -0
  69. package/dist/video-extraction/new-video-for-preview.js +114 -0
  70. package/dist/video-for-rendering.d.ts +3 -0
  71. package/dist/video-for-rendering.js +108 -0
  72. package/dist/video-iterator-manager.d.ts +4 -1
  73. package/dist/video-iterator-manager.js +27 -4
  74. package/dist/video.d.ts +3 -0
  75. package/dist/video.js +37 -0
  76. package/package.json +3 -3
@@ -3,12 +3,12 @@ import { Internals } from 'remotion';
3
3
  import { audioIteratorManager, } from './audio-iterator-manager';
4
4
  import { calculatePlaybackTime } from './calculate-playbacktime';
5
5
  import { drawPreviewOverlay } from './debug-overlay/preview-overlay';
6
- import { getTimeInSeconds } from './get-time-in-seconds';
6
+ import { calculateEndTime, getTimeInSeconds } from './get-time-in-seconds';
7
7
  import { isNetworkError } from './is-type-of-error';
8
8
  import { makeNonceManager } from './nonce-manager';
9
9
  import { videoIteratorManager } from './video-iterator-manager';
10
10
  export class MediaPlayer {
11
- constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, }) {
11
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, playing, }) {
12
12
  this.audioIteratorManager = null;
13
13
  this.videoIteratorManager = null;
14
14
  // this is the time difference between Web Audio timeline
@@ -71,6 +71,7 @@ export class MediaPlayer {
71
71
  this.isPostmounting = isPostmounting;
72
72
  this.nonceManager = makeNonceManager();
73
73
  this.onVideoFrameCallback = onVideoFrameCallback;
74
+ this.playing = playing;
74
75
  this.input = new Input({
75
76
  source: new UrlSource(this.src),
76
77
  formats: ALL_FORMATS,
@@ -95,9 +96,24 @@ export class MediaPlayer {
95
96
  initialize(startTimeUnresolved) {
96
97
  const promise = this._initialize(startTimeUnresolved);
97
98
  this.initializationPromise = promise;
99
+ this.seekPromiseChain = promise;
98
100
  return promise;
99
101
  }
102
+ getStartTime() {
103
+ return (this.trimBefore ?? 0) / this.fps;
104
+ }
105
+ getEndTime() {
106
+ return calculateEndTime({
107
+ mediaDurationInSeconds: this.totalDuration,
108
+ ifNoMediaDuration: 'fail',
109
+ src: this.src,
110
+ trimAfter: this.trimAfter,
111
+ trimBefore: this.trimBefore,
112
+ fps: this.fps,
113
+ });
114
+ }
100
115
  async _initialize(startTimeUnresolved) {
116
+ const delayHandle = this.delayPlaybackHandleIfNotPremounting();
101
117
  try {
102
118
  if (this.input.disposed) {
103
119
  return { type: 'disposed' };
@@ -145,6 +161,9 @@ export class MediaPlayer {
145
161
  getOnVideoFrameCallback: () => this.onVideoFrameCallback,
146
162
  logLevel: this.logLevel,
147
163
  drawDebugOverlay: this.drawDebugOverlay,
164
+ getEndTime: () => this.getEndTime(),
165
+ getStartTime: () => this.getStartTime(),
166
+ getIsLooping: () => this.loop,
148
167
  });
149
168
  }
150
169
  const startTime = getTimeInSeconds({
@@ -167,21 +186,28 @@ export class MediaPlayer {
167
186
  audioTrack,
168
187
  delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
169
188
  sharedAudioContext: this.sharedAudioContext,
189
+ getIsLooping: () => this.loop,
190
+ getEndTime: () => this.getEndTime(),
191
+ getStartTime: () => this.getStartTime(),
192
+ updatePlaybackTime: (time) => this.setPlaybackTime(time, this.playbackRate * this.globalPlaybackRate),
170
193
  });
171
194
  }
172
195
  const nonce = this.nonceManager.createAsyncOperation();
173
196
  try {
174
- // intentionally not awaited
175
- if (this.audioIteratorManager) {
176
- this.audioIteratorManager.startAudioIterator({
177
- nonce,
178
- playbackRate: this.playbackRate * this.globalPlaybackRate,
179
- startFromSecond: startTime,
180
- getIsPlaying: () => this.playing,
181
- scheduleAudioNode: this.scheduleAudioNode,
182
- });
183
- }
184
- await this.videoIteratorManager?.startVideoIterator(startTime, nonce);
197
+ await Promise.all([
198
+ this.audioIteratorManager
199
+ ? this.audioIteratorManager.startAudioIterator({
200
+ nonce,
201
+ playbackRate: this.playbackRate * this.globalPlaybackRate,
202
+ startFromSecond: startTime,
203
+ getIsPlaying: () => this.playing,
204
+ scheduleAudioNode: this.scheduleAudioNode,
205
+ })
206
+ : Promise.resolve(),
207
+ this.videoIteratorManager
208
+ ? this.videoIteratorManager.startVideoIterator(startTime, nonce)
209
+ : Promise.resolve(),
210
+ ]);
185
211
  }
186
212
  catch (error) {
187
213
  if (this.isDisposalError()) {
@@ -200,6 +226,9 @@ export class MediaPlayer {
200
226
  Internals.Log.error({ logLevel: this.logLevel, tag: '@remotion/media' }, '[MediaPlayer] Failed to initialize', error);
201
227
  throw error;
202
228
  }
229
+ finally {
230
+ delayHandle.unblock();
231
+ }
203
232
  }
204
233
  async seekTo(time) {
205
234
  const newTime = getTimeInSeconds({
@@ -246,6 +275,9 @@ export class MediaPlayer {
246
275
  ]);
247
276
  }
248
277
  async play(time) {
278
+ if (this.playing) {
279
+ return;
280
+ }
249
281
  const newTime = getTimeInSeconds({
250
282
  unloopedTimeInSeconds: time,
251
283
  playbackRate: this.playbackRate,
@@ -274,6 +306,9 @@ export class MediaPlayer {
274
306
  this.drawDebugOverlay();
275
307
  }
276
308
  pause() {
309
+ if (!this.playing) {
310
+ return;
311
+ }
277
312
  this.playing = false;
278
313
  this.audioIteratorManager?.pausePlayback();
279
314
  this.drawDebugOverlay();
@@ -310,12 +345,16 @@ export class MediaPlayer {
310
345
  this.audioIteratorManager?.destroyIterator();
311
346
  }
312
347
  setTrimBefore(trimBefore, unloopedTimeInSeconds) {
313
- this.trimBefore = trimBefore;
314
- this.updateAfterTrimChange(unloopedTimeInSeconds);
348
+ if (this.trimBefore !== trimBefore) {
349
+ this.trimBefore = trimBefore;
350
+ this.updateAfterTrimChange(unloopedTimeInSeconds);
351
+ }
315
352
  }
316
353
  setTrimAfter(trimAfter, unloopedTimeInSeconds) {
317
- this.trimAfter = trimAfter;
318
- this.updateAfterTrimChange(unloopedTimeInSeconds);
354
+ if (this.trimAfter !== trimAfter) {
355
+ this.trimAfter = trimAfter;
356
+ this.updateAfterTrimChange(unloopedTimeInSeconds);
357
+ }
319
358
  }
320
359
  setDebugOverlay(debugOverlay) {
321
360
  this.debugOverlay = debugOverlay;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { VideoProps } from './props';
3
+ export declare const VideoForRendering: React.FC<VideoProps>;
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
+ import { cancelRender, Internals, useCurrentFrame, useDelayRender, useRemotionEnvironment, } from 'remotion';
4
+ import { extractFrameViaBroadcastChannel } from './extract-frame-via-broadcast-channel';
5
+ export const VideoForRendering = ({ volume: volumeProp, playbackRate, src, muted, loopVolumeCurveBehavior, delayRenderRetries, delayRenderTimeoutInMilliseconds,
6
+ // call when a frame of the video, i.e. frame drawn on canvas
7
+ onVideoFrame, logLevel = window.remotion_logLevel, }) => {
8
+ const absoluteFrame = Internals.useTimelinePosition();
9
+ const videoConfig = Internals.useUnsafeVideoConfig();
10
+ const canvasRef = useRef(null);
11
+ const { registerRenderAsset, unregisterRenderAsset } = useContext(Internals.RenderAssetManager);
12
+ const frame = useCurrentFrame();
13
+ const volumePropsFrame = Internals.useFrameForVolumeProp(loopVolumeCurveBehavior ?? 'repeat');
14
+ const environment = useRemotionEnvironment();
15
+ const [id] = useState(() => `${Math.random()}`.replace('0.', ''));
16
+ if (!videoConfig) {
17
+ throw new Error('No video config found');
18
+ }
19
+ if (!src) {
20
+ throw new TypeError('No `src` was passed to <Video>.');
21
+ }
22
+ const volume = Internals.evaluateVolume({
23
+ volume: volumeProp,
24
+ frame: volumePropsFrame,
25
+ mediaVolume: 1,
26
+ });
27
+ Internals.warnAboutTooHighVolume(volume);
28
+ const shouldRenderAudio = useMemo(() => {
29
+ if (!window.remotion_audioEnabled) {
30
+ return false;
31
+ }
32
+ if (muted) {
33
+ return false;
34
+ }
35
+ if (volume <= 0) {
36
+ return false;
37
+ }
38
+ return true;
39
+ }, [muted, volume]);
40
+ const { fps } = videoConfig;
41
+ const { delayRender, continueRender } = useDelayRender();
42
+ useLayoutEffect(() => {
43
+ if (!canvasRef.current) {
44
+ return;
45
+ }
46
+ const actualFps = playbackRate ? fps / playbackRate : fps;
47
+ const timestamp = frame / actualFps;
48
+ const durationInSeconds = 1 / actualFps;
49
+ const newHandle = delayRender(`Extracting frame number ${frame}`, {
50
+ retries: delayRenderRetries ?? undefined,
51
+ timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined,
52
+ });
53
+ extractFrameViaBroadcastChannel({
54
+ src,
55
+ timeInSeconds: timestamp,
56
+ durationInSeconds,
57
+ logLevel: logLevel ?? 'info',
58
+ shouldRenderAudio,
59
+ isClientSideRendering: environment.isClientSideRendering,
60
+ })
61
+ .then(({ frame: imageBitmap, audio }) => {
62
+ if (!imageBitmap) {
63
+ cancelRender(new Error('No video frame found'));
64
+ }
65
+ onVideoFrame?.(imageBitmap);
66
+ canvasRef.current?.getContext('2d')?.drawImage(imageBitmap, 0, 0);
67
+ imageBitmap.close();
68
+ if (audio) {
69
+ registerRenderAsset({
70
+ type: 'inline-audio',
71
+ id,
72
+ audio: Array.from(audio.data),
73
+ sampleRate: audio.sampleRate,
74
+ numberOfChannels: audio.numberOfChannels,
75
+ frame: absoluteFrame,
76
+ timestamp: audio.timestamp,
77
+ duration: (audio.numberOfFrames / audio.sampleRate) * 1000000,
78
+ });
79
+ }
80
+ continueRender(newHandle);
81
+ })
82
+ .catch((error) => {
83
+ cancelRender(error);
84
+ });
85
+ return () => {
86
+ continueRender(newHandle);
87
+ unregisterRenderAsset(id);
88
+ };
89
+ }, [
90
+ absoluteFrame,
91
+ continueRender,
92
+ delayRender,
93
+ delayRenderRetries,
94
+ delayRenderTimeoutInMilliseconds,
95
+ environment.isClientSideRendering,
96
+ fps,
97
+ frame,
98
+ id,
99
+ logLevel,
100
+ onVideoFrame,
101
+ playbackRate,
102
+ registerRenderAsset,
103
+ shouldRenderAudio,
104
+ src,
105
+ unregisterRenderAsset,
106
+ ]);
107
+ return (_jsx("canvas", { ref: canvasRef, width: videoConfig.width, height: videoConfig.height }));
108
+ };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { VideoProps } from './props';
3
+ export declare const Video: React.FC<VideoProps>;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback } from 'react';
3
+ import { Internals, Sequence, useRemotionEnvironment } from 'remotion';
4
+ import { VideoForRendering } from './new-video-for-rendering';
5
+ const { validateMediaTrimProps, resolveTrimProps, validateMediaProps, VideoForPreview, } = Internals;
6
+ export const Video = (props) => {
7
+ // Should only destruct `startFrom` and `endAt` from props,
8
+ // rest gets drilled down
9
+ const { trimBefore, trimAfter, name, pauseWhenBuffering, stack, showInTimeline, ...otherProps } = props;
10
+ const environment = useRemotionEnvironment();
11
+ const onDuration = useCallback(() => undefined, []);
12
+ if (typeof props.src !== 'string') {
13
+ throw new TypeError(`The \`<Video>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
14
+ }
15
+ validateMediaTrimProps({
16
+ startFrom: undefined,
17
+ endAt: undefined,
18
+ trimBefore,
19
+ trimAfter,
20
+ });
21
+ const { trimBeforeValue, trimAfterValue } = resolveTrimProps({
22
+ startFrom: undefined,
23
+ endAt: undefined,
24
+ trimBefore,
25
+ trimAfter,
26
+ });
27
+ if (typeof trimBeforeValue !== 'undefined' ||
28
+ typeof trimAfterValue !== 'undefined') {
29
+ return (_jsx(Sequence, { layout: "none", from: 0 - (trimBeforeValue ?? 0), showInTimeline: false, durationInFrames: trimAfterValue, name: name, children: _jsx(Video, { pauseWhenBuffering: pauseWhenBuffering ?? false, ...otherProps }) }));
30
+ }
31
+ validateMediaProps(props, 'Video');
32
+ if (environment.isRendering) {
33
+ return _jsx(VideoForRendering, { ...otherProps });
34
+ }
35
+ const { onAutoPlayError, onVideoFrame, crossOrigin, delayRenderRetries, delayRenderTimeoutInMilliseconds, ...propsForPreview } = otherProps;
36
+ return (_jsx(VideoForPreview, { _remotionInternalStack: stack ?? null, _remotionInternalNativeLoopPassed: false, onDuration: onDuration, onlyWarnForMediaSeekingError: true, pauseWhenBuffering: pauseWhenBuffering ?? false, showInTimeline: showInTimeline ?? true, onAutoPlayError: onAutoPlayError ?? undefined, onVideoFrame: onVideoFrame ?? null, crossOrigin: crossOrigin, ...propsForPreview }));
37
+ };
@@ -0,0 +1,17 @@
1
+ import type { AudioBufferSink, CanvasSink, WrappedAudioBuffer, WrappedCanvas } from 'mediabunny';
2
+ export declare const makePrewarmedVideoIteratorCache: (videoSink: CanvasSink) => {
3
+ prewarmIteratorForLooping: ({ timeToSeek }: {
4
+ timeToSeek: number;
5
+ }) => void;
6
+ makeIteratorOrUsePrewarmed: (timeToSeek: number) => AsyncGenerator<WrappedCanvas, void, unknown>;
7
+ destroy: () => void;
8
+ };
9
+ export type PrewarmedVideoIteratorCache = ReturnType<typeof makePrewarmedVideoIteratorCache>;
10
+ export declare const makePrewarmedAudioIteratorCache: (audioSink: AudioBufferSink) => {
11
+ prewarmIteratorForLooping: ({ timeToSeek }: {
12
+ timeToSeek: number;
13
+ }) => void;
14
+ makeIteratorOrUsePrewarmed: (timeToSeek: number) => AsyncGenerator<WrappedAudioBuffer, void, unknown>;
15
+ destroy: () => void;
16
+ };
17
+ export type PrewarmedAudioIteratorCache = ReturnType<typeof makePrewarmedAudioIteratorCache>;
@@ -0,0 +1,56 @@
1
+ export const makePrewarmedVideoIteratorCache = (videoSink) => {
2
+ const prewarmedVideoIterators = new Map();
3
+ const prewarmIteratorForLooping = ({ timeToSeek }) => {
4
+ if (!prewarmedVideoIterators.has(timeToSeek)) {
5
+ prewarmedVideoIterators.set(timeToSeek, videoSink.canvases(timeToSeek));
6
+ }
7
+ };
8
+ const makeIteratorOrUsePrewarmed = (timeToSeek) => {
9
+ const prewarmedIterator = prewarmedVideoIterators.get(timeToSeek);
10
+ if (prewarmedIterator) {
11
+ prewarmedVideoIterators.delete(timeToSeek);
12
+ return prewarmedIterator;
13
+ }
14
+ const iterator = videoSink.canvases(timeToSeek);
15
+ return iterator;
16
+ };
17
+ const destroy = () => {
18
+ for (const iterator of prewarmedVideoIterators.values()) {
19
+ iterator.return();
20
+ }
21
+ prewarmedVideoIterators.clear();
22
+ };
23
+ return {
24
+ prewarmIteratorForLooping,
25
+ makeIteratorOrUsePrewarmed,
26
+ destroy,
27
+ };
28
+ };
29
+ export const makePrewarmedAudioIteratorCache = (audioSink) => {
30
+ const prewarmedAudioIterators = new Map();
31
+ const prewarmIteratorForLooping = ({ timeToSeek }) => {
32
+ if (!prewarmedAudioIterators.has(timeToSeek)) {
33
+ prewarmedAudioIterators.set(timeToSeek, audioSink.buffers(timeToSeek));
34
+ }
35
+ };
36
+ const makeIteratorOrUsePrewarmed = (timeToSeek) => {
37
+ const prewarmedIterator = prewarmedAudioIterators.get(timeToSeek);
38
+ if (prewarmedIterator) {
39
+ prewarmedAudioIterators.delete(timeToSeek);
40
+ return prewarmedIterator;
41
+ }
42
+ const iterator = audioSink.buffers(timeToSeek);
43
+ return iterator;
44
+ };
45
+ const destroy = () => {
46
+ for (const iterator of prewarmedAudioIterators.values()) {
47
+ iterator.return();
48
+ }
49
+ prewarmedAudioIterators.clear();
50
+ };
51
+ return {
52
+ prewarmIteratorForLooping,
53
+ makeIteratorOrUsePrewarmed,
54
+ destroy,
55
+ };
56
+ };
@@ -0,0 +1,29 @@
1
+ import type { LoopVolumeCurveBehavior, VolumeProp } from 'remotion';
2
+ import type { LogLevel } from './log';
3
+ export type AudioProps = {
4
+ src: string;
5
+ trimBefore?: number;
6
+ trimAfter?: number;
7
+ volume?: VolumeProp;
8
+ loopVolumeCurveBehavior?: LoopVolumeCurveBehavior;
9
+ name?: string;
10
+ pauseWhenBuffering?: boolean;
11
+ showInTimeline?: boolean;
12
+ onAutoPlayError?: null | (() => void);
13
+ playbackRate?: number;
14
+ muted?: boolean;
15
+ delayRenderRetries?: number;
16
+ delayRenderTimeoutInMilliseconds?: number;
17
+ crossOrigin?: '' | 'anonymous' | 'use-credentials';
18
+ style?: React.CSSProperties;
19
+ onError?: (err: Error) => void;
20
+ useWebAudioApi?: boolean;
21
+ acceptableTimeShiftInSeconds?: number;
22
+ /**
23
+ * @deprecated For internal use only
24
+ */
25
+ stack?: string;
26
+ logLevel?: LogLevel;
27
+ loop?: boolean;
28
+ _remotionInternalNativeLoopPassed?: boolean;
29
+ };
package/dist/props.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export declare const rememberActualMatroskaTimestamps: (isMatroska: boolean) => {
2
+ observeTimestamp: (startTime: number) => void;
3
+ getRealTimestamp: (observedTimestamp: number) => number | null;
4
+ };
@@ -0,0 +1,19 @@
1
+ export const rememberActualMatroskaTimestamps = (isMatroska) => {
2
+ const observations = [];
3
+ const observeTimestamp = (startTime) => {
4
+ if (!isMatroska) {
5
+ return;
6
+ }
7
+ observations.push(startTime);
8
+ };
9
+ const getRealTimestamp = (observedTimestamp) => {
10
+ if (!isMatroska) {
11
+ return observedTimestamp;
12
+ }
13
+ return (observations.find((observation) => Math.abs(observedTimestamp - observation) < 0.001) ?? null);
14
+ };
15
+ return {
16
+ observeTimestamp,
17
+ getRealTimestamp,
18
+ };
19
+ };
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,62 @@
1
+ import type { LogLevel } from 'remotion';
2
+ export declare const SEEK_THRESHOLD = 0.05;
3
+ export declare class MediaPlayer {
4
+ private canvas;
5
+ private context;
6
+ private src;
7
+ private logLevel;
8
+ private canvasSink;
9
+ private videoFrameIterator;
10
+ private nextFrame;
11
+ private audioSink;
12
+ private audioBufferIterator;
13
+ private queuedAudioNodes;
14
+ private gainNode;
15
+ private sharedAudioContext;
16
+ private audioSyncAnchor;
17
+ private playing;
18
+ private animationFrameId;
19
+ private videoAsyncId;
20
+ private initialized;
21
+ private totalDuration;
22
+ private isBuffering;
23
+ private onBufferingChangeCallback?;
24
+ private audioBufferHealth;
25
+ private audioIteratorStarted;
26
+ private readonly HEALTHY_BUFER_THRESHOLD_SECONDS;
27
+ constructor({ canvas, src, logLevel, sharedAudioContext, }: {
28
+ canvas: HTMLCanvasElement;
29
+ src: string;
30
+ logLevel: LogLevel;
31
+ sharedAudioContext: AudioContext;
32
+ });
33
+ private input;
34
+ private isReady;
35
+ private hasAudio;
36
+ private isCurrentlyBuffering;
37
+ initialize(startTime?: number): Promise<void>;
38
+ private cleanupAudioQueue;
39
+ private cleanAudioIteratorAndNodes;
40
+ seekTo(time: number): Promise<void>;
41
+ play(): Promise<void>;
42
+ pause(): void;
43
+ dispose(): void;
44
+ private getPlaybackTime;
45
+ private scheduleAudioChunk;
46
+ onBufferingChange(callback: (isBuffering: boolean) => void): void;
47
+ private canRenderVideo;
48
+ private startRenderLoop;
49
+ private stopRenderLoop;
50
+ private render;
51
+ private shouldRenderFrame;
52
+ private drawCurrentFrame;
53
+ private startAudioIterator;
54
+ private startVideoIterator;
55
+ private updateNextFrame;
56
+ private bufferingStartedAtMs;
57
+ private minBufferingTimeoutMs;
58
+ private setBufferingState;
59
+ private maybeResumeFromBuffering;
60
+ private maybeForceResumeFromBuffering;
61
+ private runAudioIterator;
62
+ }