@remotion/media 4.0.402 → 4.0.404

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 (77) hide show
  1. package/dist/audio/audio-for-preview.d.ts +2 -0
  2. package/dist/audio/audio-preview-iterator.d.ts +8 -3
  3. package/dist/audio/props.d.ts +2 -0
  4. package/dist/audio-extraction/audio-iterator.d.ts +5 -4
  5. package/dist/audio-extraction/audio-manager.d.ts +23 -7
  6. package/dist/audio-extraction/extract-audio.d.ts +2 -4
  7. package/dist/audio-iterator-manager.d.ts +2 -2
  8. package/dist/caches.d.ts +34 -17
  9. package/dist/convert-audiodata/apply-volume.d.ts +1 -1
  10. package/dist/convert-audiodata/resample-audiodata.d.ts +2 -2
  11. package/dist/debug-overlay/preview-overlay.d.ts +83 -5
  12. package/dist/esm/index.mjs +524 -476
  13. package/dist/extract-frame-and-audio.d.ts +1 -2
  14. package/dist/get-sink.d.ts +1 -2
  15. package/dist/index.d.ts +2 -1
  16. package/dist/media-player.d.ts +1 -1
  17. package/dist/on-error.d.ts +12 -0
  18. package/dist/show-in-timeline.d.ts +2 -2
  19. package/dist/use-media-in-timeline.d.ts +2 -2
  20. package/dist/video/props.d.ts +5 -0
  21. package/dist/video/video-for-preview.d.ts +2 -0
  22. package/dist/video/video-for-rendering.d.ts +2 -0
  23. package/dist/video/video-preview-iterator.d.ts +7 -2
  24. package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +1 -2
  25. package/dist/video-extraction/extract-frame.d.ts +2 -4
  26. package/dist/video-extraction/get-frames-since-keyframe.d.ts +2 -12
  27. package/dist/video-extraction/keyframe-bank.d.ts +14 -12
  28. package/dist/video-extraction/keyframe-manager.d.ts +7 -9
  29. package/dist/video-iterator-manager.d.ts +4 -5
  30. package/package.json +8 -7
  31. package/dist/audio/allow-wait.js +0 -15
  32. package/dist/audio/audio-for-preview.js +0 -304
  33. package/dist/audio/audio-for-rendering.js +0 -194
  34. package/dist/audio/audio-preview-iterator.js +0 -176
  35. package/dist/audio/audio.js +0 -20
  36. package/dist/audio/props.js +0 -1
  37. package/dist/audio-extraction/audio-cache.js +0 -66
  38. package/dist/audio-extraction/audio-iterator.js +0 -132
  39. package/dist/audio-extraction/audio-manager.js +0 -113
  40. package/dist/audio-extraction/extract-audio.js +0 -132
  41. package/dist/audio-iterator-manager.js +0 -228
  42. package/dist/browser-can-use-webgl2.js +0 -13
  43. package/dist/caches.js +0 -61
  44. package/dist/calculate-playbacktime.js +0 -4
  45. package/dist/convert-audiodata/apply-volume.js +0 -17
  46. package/dist/convert-audiodata/combine-audiodata.js +0 -23
  47. package/dist/convert-audiodata/convert-audiodata.js +0 -73
  48. package/dist/convert-audiodata/resample-audiodata.js +0 -94
  49. package/dist/debug-overlay/preview-overlay.js +0 -44
  50. package/dist/extract-frame-and-audio.js +0 -101
  51. package/dist/get-sink.js +0 -15
  52. package/dist/get-time-in-seconds.js +0 -40
  53. package/dist/helpers/round-to-4-digits.js +0 -4
  54. package/dist/index.js +0 -12
  55. package/dist/is-type-of-error.js +0 -20
  56. package/dist/looped-frame.js +0 -10
  57. package/dist/media-player.js +0 -445
  58. package/dist/nonce-manager.js +0 -13
  59. package/dist/prewarm-iterator-for-looping.js +0 -56
  60. package/dist/render-timestamp-range.js +0 -9
  61. package/dist/show-in-timeline.js +0 -31
  62. package/dist/use-media-in-timeline.js +0 -103
  63. package/dist/video/props.js +0 -1
  64. package/dist/video/video-for-preview.js +0 -329
  65. package/dist/video/video-for-rendering.js +0 -263
  66. package/dist/video/video-preview-iterator.js +0 -122
  67. package/dist/video/video.js +0 -35
  68. package/dist/video-extraction/add-broadcast-channel-listener.js +0 -125
  69. package/dist/video-extraction/extract-frame-via-broadcast-channel.js +0 -113
  70. package/dist/video-extraction/extract-frame.js +0 -85
  71. package/dist/video-extraction/get-allocation-size.js +0 -6
  72. package/dist/video-extraction/get-frames-since-keyframe.js +0 -108
  73. package/dist/video-extraction/keyframe-bank.js +0 -159
  74. package/dist/video-extraction/keyframe-manager.js +0 -206
  75. package/dist/video-extraction/remember-actual-matroska-timestamps.js +0 -19
  76. package/dist/video-extraction/rotate-frame.js +0 -34
  77. package/dist/video-iterator-manager.js +0 -109
@@ -1,263 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useContext, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
- import { Internals, Loop, random, useCurrentFrame, useDelayRender, useRemotionEnvironment, useVideoConfig, } from 'remotion';
4
- import { useMaxMediaCacheSize } from '../caches';
5
- import { applyVolume } from '../convert-audiodata/apply-volume';
6
- import { TARGET_SAMPLE_RATE } from '../convert-audiodata/resample-audiodata';
7
- import { frameForVolumeProp } from '../looped-frame';
8
- import { extractFrameViaBroadcastChannel } from '../video-extraction/extract-frame-via-broadcast-channel';
9
- export const VideoForRendering = ({ volume: volumeProp, playbackRate, src, muted, loopVolumeCurveBehavior, delayRenderRetries, delayRenderTimeoutInMilliseconds, onVideoFrame, logLevel, loop, style, className, fallbackOffthreadVideoProps, audioStreamIndex, name, disallowFallbackToOffthreadVideo, stack, toneFrequency, trimAfterValue, trimBeforeValue, headless, }) => {
10
- if (!src) {
11
- throw new TypeError('No `src` was passed to <Video>.');
12
- }
13
- const frame = useCurrentFrame();
14
- const absoluteFrame = Internals.useTimelinePosition();
15
- const { fps } = useVideoConfig();
16
- const { registerRenderAsset, unregisterRenderAsset } = useContext(Internals.RenderAssetManager);
17
- const startsAt = Internals.useMediaStartsAt();
18
- const sequenceContext = useContext(Internals.SequenceContext);
19
- // Generate a string that's as unique as possible for this asset
20
- // but at the same time the same on all threads
21
- const id = useMemo(() => `media-video-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
22
- src,
23
- sequenceContext?.cumulatedFrom,
24
- sequenceContext?.relativeFrom,
25
- sequenceContext?.durationInFrames,
26
- ]);
27
- const environment = useRemotionEnvironment();
28
- const { delayRender, continueRender, cancelRender } = useDelayRender();
29
- const canvasRef = useRef(null);
30
- const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState(false);
31
- const audioEnabled = Internals.useAudioEnabled();
32
- const videoEnabled = Internals.useVideoEnabled();
33
- const maxCacheSize = useMaxMediaCacheSize(logLevel);
34
- const [error, setError] = useState(null);
35
- if (error) {
36
- throw error;
37
- }
38
- useLayoutEffect(() => {
39
- if (!canvasRef.current && !headless) {
40
- return;
41
- }
42
- if (replaceWithOffthreadVideo) {
43
- return;
44
- }
45
- if (!canvasRef.current?.getContext && !headless) {
46
- return setError(new Error('Canvas does not have .getContext() method available. This could be because <Video> was mounted inside an <svg> tag.'));
47
- }
48
- const timestamp = frame / fps;
49
- const durationInSeconds = 1 / fps;
50
- const newHandle = delayRender(`Extracting frame at time ${timestamp}`, {
51
- retries: delayRenderRetries ?? undefined,
52
- timeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined,
53
- });
54
- const shouldRenderAudio = (() => {
55
- if (!audioEnabled) {
56
- return false;
57
- }
58
- if (muted) {
59
- return false;
60
- }
61
- return true;
62
- })();
63
- extractFrameViaBroadcastChannel({
64
- src,
65
- timeInSeconds: timestamp,
66
- durationInSeconds,
67
- playbackRate,
68
- logLevel,
69
- includeAudio: shouldRenderAudio,
70
- includeVideo: videoEnabled,
71
- isClientSideRendering: environment.isClientSideRendering,
72
- loop,
73
- audioStreamIndex,
74
- trimAfter: trimAfterValue,
75
- trimBefore: trimBeforeValue,
76
- fps,
77
- maxCacheSize,
78
- })
79
- .then((result) => {
80
- if (result.type === 'unknown-container-format') {
81
- if (environment.isClientSideRendering) {
82
- cancelRender(new Error(`Cannot render video "${src}": Unknown container format. See supported formats: https://www.remotion.dev/docs/mediabunny/formats`));
83
- return;
84
- }
85
- if (disallowFallbackToOffthreadVideo) {
86
- cancelRender(new Error(`Unknown container format ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
87
- }
88
- if (window.remotion_isMainTab) {
89
- Internals.Log.info({ logLevel, tag: '@remotion/media' }, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
90
- }
91
- setReplaceWithOffthreadVideo({ durationInSeconds: null });
92
- return;
93
- }
94
- if (result.type === 'cannot-decode') {
95
- if (environment.isClientSideRendering) {
96
- cancelRender(new Error(`Cannot render video "${src}": The video could not be decoded by the browser.`));
97
- return;
98
- }
99
- if (disallowFallbackToOffthreadVideo) {
100
- cancelRender(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
101
- }
102
- if (window.remotion_isMainTab) {
103
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `Cannot decode ${src}, falling back to <OffthreadVideo>`);
104
- }
105
- setReplaceWithOffthreadVideo({
106
- durationInSeconds: result.durationInSeconds,
107
- });
108
- return;
109
- }
110
- if (result.type === 'cannot-decode-alpha') {
111
- if (environment.isClientSideRendering) {
112
- cancelRender(new Error(`Cannot render video "${src}": The alpha channel could not be decoded by the browser.`));
113
- return;
114
- }
115
- if (disallowFallbackToOffthreadVideo) {
116
- cancelRender(new Error(`Cannot decode alpha component for ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
117
- }
118
- if (window.remotion_isMainTab) {
119
- Internals.Log.info({ logLevel, tag: '@remotion/media' }, `Cannot decode alpha component for ${src}, falling back to <OffthreadVideo>`);
120
- }
121
- setReplaceWithOffthreadVideo({
122
- durationInSeconds: result.durationInSeconds,
123
- });
124
- return;
125
- }
126
- if (result.type === 'network-error') {
127
- if (environment.isClientSideRendering) {
128
- cancelRender(new Error(`Cannot render video "${src}": Network error while fetching the video (possibly CORS).`));
129
- return;
130
- }
131
- if (disallowFallbackToOffthreadVideo) {
132
- cancelRender(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
133
- }
134
- if (window.remotion_isMainTab) {
135
- Internals.Log.warn({ logLevel, tag: '@remotion/media' }, `Network error fetching ${src} (no CORS?), falling back to <OffthreadVideo>`);
136
- }
137
- setReplaceWithOffthreadVideo({ durationInSeconds: null });
138
- return;
139
- }
140
- const { frame: imageBitmap, audio, durationInSeconds: assetDurationInSeconds, } = result;
141
- if (imageBitmap) {
142
- onVideoFrame?.(imageBitmap);
143
- const context = canvasRef.current?.getContext('2d', {
144
- alpha: true,
145
- });
146
- // Could be in headless mode
147
- if (context) {
148
- context.canvas.width = imageBitmap.width;
149
- context.canvas.height = imageBitmap.height;
150
- context.canvas.style.aspectRatio = `${context.canvas.width} / ${context.canvas.height}`;
151
- context.drawImage(imageBitmap, 0, 0);
152
- }
153
- imageBitmap.close();
154
- }
155
- else if (videoEnabled) {
156
- // A video that only starts at time 0.033sec
157
- // we shall not crash here but clear the canvas
158
- const context = canvasRef.current?.getContext('2d', {
159
- alpha: true,
160
- });
161
- if (context) {
162
- context.clearRect(0, 0, context.canvas.width, context.canvas.height);
163
- }
164
- }
165
- const volumePropsFrame = frameForVolumeProp({
166
- behavior: loopVolumeCurveBehavior,
167
- loop,
168
- assetDurationInSeconds: assetDurationInSeconds ?? 0,
169
- fps,
170
- frame,
171
- startsAt,
172
- });
173
- const volume = Internals.evaluateVolume({
174
- volume: volumeProp,
175
- frame: volumePropsFrame,
176
- mediaVolume: 1,
177
- });
178
- Internals.warnAboutTooHighVolume(volume);
179
- if (audio && volume > 0) {
180
- applyVolume(audio.data, volume);
181
- registerRenderAsset({
182
- type: 'inline-audio',
183
- id,
184
- audio: environment.isClientSideRendering
185
- ? audio.data
186
- : Array.from(audio.data),
187
- frame: absoluteFrame,
188
- timestamp: audio.timestamp,
189
- duration: (audio.numberOfFrames / TARGET_SAMPLE_RATE) * 1000000,
190
- toneFrequency,
191
- });
192
- }
193
- continueRender(newHandle);
194
- })
195
- .catch((err) => {
196
- cancelRender(err);
197
- });
198
- return () => {
199
- continueRender(newHandle);
200
- unregisterRenderAsset(id);
201
- };
202
- }, [
203
- absoluteFrame,
204
- continueRender,
205
- delayRender,
206
- delayRenderRetries,
207
- delayRenderTimeoutInMilliseconds,
208
- environment.isClientSideRendering,
209
- fps,
210
- frame,
211
- id,
212
- logLevel,
213
- loop,
214
- loopVolumeCurveBehavior,
215
- muted,
216
- onVideoFrame,
217
- playbackRate,
218
- registerRenderAsset,
219
- src,
220
- startsAt,
221
- unregisterRenderAsset,
222
- volumeProp,
223
- replaceWithOffthreadVideo,
224
- audioStreamIndex,
225
- disallowFallbackToOffthreadVideo,
226
- toneFrequency,
227
- trimAfterValue,
228
- trimBeforeValue,
229
- audioEnabled,
230
- videoEnabled,
231
- maxCacheSize,
232
- cancelRender,
233
- headless,
234
- ]);
235
- const classNameValue = useMemo(() => {
236
- return [Internals.OBJECTFIT_CONTAIN_CLASS_NAME, className]
237
- .filter(Internals.truthy)
238
- .join(' ');
239
- }, [className]);
240
- if (replaceWithOffthreadVideo) {
241
- const fallback = (_jsx(Internals.InnerOffthreadVideo, { src: src, playbackRate: playbackRate ?? 1, muted: muted ?? false, acceptableTimeShiftInSeconds: fallbackOffthreadVideoProps?.acceptableTimeShiftInSeconds, loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? 'repeat', delayRenderRetries: delayRenderRetries ?? undefined, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined, style: style, allowAmplificationDuringRender: true, transparent: fallbackOffthreadVideoProps?.transparent ?? true, toneMapped: fallbackOffthreadVideoProps?.toneMapped ?? true, audioStreamIndex: audioStreamIndex ?? 0, name: name, className: className, onVideoFrame: onVideoFrame, volume: volumeProp, id: id, onError: fallbackOffthreadVideoProps?.onError, toneFrequency: toneFrequency,
242
- // these shouldn't matter during rendering / should not appear at all
243
- showInTimeline: false, crossOrigin: undefined, onAutoPlayError: () => undefined, pauseWhenBuffering: false, trimAfter: trimAfterValue, trimBefore: trimBeforeValue, useWebAudioApi: false, startFrom: undefined, endAt: undefined, stack: stack, _remotionInternalNativeLoopPassed: false }));
244
- if (loop) {
245
- if (!replaceWithOffthreadVideo.durationInSeconds) {
246
- const err = new Error(`Cannot render video ${src}: @remotion/media was unable to render, and fell back to <OffthreadVideo>. Also, "loop" was set, but <OffthreadVideo> does not support looping and @remotion/media could also not determine the duration of the video.`);
247
- cancelRender(err);
248
- throw err;
249
- }
250
- return (_jsx(Loop, { layout: "none", durationInFrames: Internals.calculateMediaDuration({
251
- trimAfter: trimAfterValue,
252
- mediaDurationInFrames: replaceWithOffthreadVideo.durationInSeconds * fps,
253
- playbackRate,
254
- trimBefore: trimBeforeValue,
255
- }), children: fallback }));
256
- }
257
- return fallback;
258
- }
259
- if (headless) {
260
- return null;
261
- }
262
- return _jsx("canvas", { ref: canvasRef, style: style, className: classNameValue });
263
- };
@@ -1,122 +0,0 @@
1
- import { roundTo4Digits } from '../helpers/round-to-4-digits';
2
- export const createVideoIterator = (timeToSeek, cache) => {
3
- let destroyed = false;
4
- const iterator = cache.makeIteratorOrUsePrewarmed(timeToSeek);
5
- let lastReturnedFrame = null;
6
- let iteratorEnded = false;
7
- const getNextOrNullIfNotAvailable = async () => {
8
- const next = iterator.next();
9
- const result = await Promise.race([
10
- next,
11
- new Promise((resolve) => {
12
- Promise.resolve().then(() => resolve());
13
- }),
14
- ]);
15
- if (!result) {
16
- return {
17
- type: 'need-to-wait-for-it',
18
- waitPromise: async () => {
19
- const res = await next;
20
- if (res.value) {
21
- lastReturnedFrame = res.value;
22
- }
23
- else {
24
- iteratorEnded = true;
25
- }
26
- return res.value;
27
- },
28
- };
29
- }
30
- if (result.value) {
31
- lastReturnedFrame = result.value;
32
- }
33
- else {
34
- iteratorEnded = true;
35
- }
36
- return {
37
- type: 'got-frame-or-end',
38
- frame: result.value ?? null,
39
- };
40
- };
41
- const destroy = () => {
42
- destroyed = true;
43
- lastReturnedFrame = null;
44
- iterator.return().catch(() => undefined);
45
- };
46
- const tryToSatisfySeek = async (time) => {
47
- if (lastReturnedFrame) {
48
- const frameTimestamp = roundTo4Digits(lastReturnedFrame.timestamp);
49
- if (roundTo4Digits(time) < frameTimestamp) {
50
- return {
51
- type: 'not-satisfied',
52
- reason: `iterator is too far, most recently returned ${frameTimestamp}`,
53
- };
54
- }
55
- const frameEndTimestamp = roundTo4Digits(lastReturnedFrame.timestamp + lastReturnedFrame.duration);
56
- const timestamp = roundTo4Digits(time);
57
- if (frameTimestamp <= timestamp && frameEndTimestamp > timestamp) {
58
- return {
59
- type: 'satisfied',
60
- frame: lastReturnedFrame,
61
- };
62
- }
63
- }
64
- if (iteratorEnded) {
65
- if (lastReturnedFrame) {
66
- return {
67
- type: 'satisfied',
68
- frame: lastReturnedFrame,
69
- };
70
- }
71
- return {
72
- type: 'not-satisfied',
73
- reason: 'iterator ended',
74
- };
75
- }
76
- while (true) {
77
- const frame = await getNextOrNullIfNotAvailable();
78
- if (frame.type === 'need-to-wait-for-it') {
79
- return {
80
- type: 'not-satisfied',
81
- reason: 'iterator did not have frame ready',
82
- };
83
- }
84
- if (frame.type === 'got-frame-or-end') {
85
- if (frame.frame === null) {
86
- iteratorEnded = true;
87
- if (lastReturnedFrame) {
88
- return {
89
- type: 'satisfied',
90
- frame: lastReturnedFrame,
91
- };
92
- }
93
- return {
94
- type: 'not-satisfied',
95
- reason: 'iterator ended and did not have frame ready',
96
- };
97
- }
98
- const frameTimestamp = roundTo4Digits(frame.frame.timestamp);
99
- const frameEndTimestamp = roundTo4Digits(frame.frame.timestamp + frame.frame.duration);
100
- const timestamp = roundTo4Digits(time);
101
- if (frameTimestamp <= timestamp && frameEndTimestamp > timestamp) {
102
- return {
103
- type: 'satisfied',
104
- frame: frame.frame,
105
- };
106
- }
107
- continue;
108
- }
109
- throw new Error('Unreachable');
110
- }
111
- };
112
- return {
113
- destroy,
114
- getNext: () => {
115
- return iterator.next();
116
- },
117
- isDestroyed: () => {
118
- return destroyed;
119
- },
120
- tryToSatisfySeek,
121
- };
122
- };
@@ -1,35 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Internals, useRemotionEnvironment } from 'remotion';
3
- import { VideoForPreview } from './video-for-preview';
4
- import { VideoForRendering } from './video-for-rendering';
5
- const { validateMediaTrimProps, resolveTrimProps, validateMediaProps } = Internals;
6
- const InnerVideo = ({ src, audioStreamIndex, className, delayRenderRetries, delayRenderTimeoutInMilliseconds, disallowFallbackToOffthreadVideo, fallbackOffthreadVideoProps, logLevel, loop, loopVolumeCurveBehavior, muted, name, onVideoFrame, playbackRate, style, trimAfter, trimBefore, volume, stack, toneFrequency, showInTimeline, debugOverlay, headless, }) => {
7
- const environment = useRemotionEnvironment();
8
- if (typeof src !== 'string') {
9
- throw new TypeError(`The \`<Video>\` tag requires a string for \`src\`, but got ${JSON.stringify(src)} instead.`);
10
- }
11
- validateMediaTrimProps({
12
- startFrom: undefined,
13
- endAt: undefined,
14
- trimBefore,
15
- trimAfter,
16
- });
17
- const { trimBeforeValue, trimAfterValue } = resolveTrimProps({
18
- startFrom: undefined,
19
- endAt: undefined,
20
- trimBefore,
21
- trimAfter,
22
- });
23
- validateMediaProps({ playbackRate, volume }, 'Video');
24
- if (environment.isRendering) {
25
- return (_jsx(VideoForRendering, { audioStreamIndex: audioStreamIndex ?? 0, className: className, delayRenderRetries: delayRenderRetries ?? null, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? null, disallowFallbackToOffthreadVideo: disallowFallbackToOffthreadVideo ?? false, name: name, fallbackOffthreadVideoProps: fallbackOffthreadVideoProps, logLevel: logLevel, loop: loop, loopVolumeCurveBehavior: loopVolumeCurveBehavior, muted: muted, onVideoFrame: onVideoFrame, playbackRate: playbackRate, src: src, stack: stack, style: style, volume: volume, toneFrequency: toneFrequency, trimAfterValue: trimAfterValue, trimBeforeValue: trimBeforeValue, headless: headless }));
26
- }
27
- return (_jsx(VideoForPreview, { audioStreamIndex: audioStreamIndex ?? 0, className: className, name: name, logLevel: logLevel, loop: loop, loopVolumeCurveBehavior: loopVolumeCurveBehavior, muted: muted, onVideoFrame: onVideoFrame, playbackRate: playbackRate, src: src, style: style, volume: volume, showInTimeline: showInTimeline, trimAfter: trimAfterValue, trimBefore: trimBeforeValue, stack: stack ?? null, disallowFallbackToOffthreadVideo: disallowFallbackToOffthreadVideo, fallbackOffthreadVideoProps: fallbackOffthreadVideoProps, debugOverlay: debugOverlay ?? false, headless: headless ?? false }));
28
- };
29
- export const Video = ({ src, audioStreamIndex, className, delayRenderRetries, delayRenderTimeoutInMilliseconds, disallowFallbackToOffthreadVideo, fallbackOffthreadVideoProps, logLevel, loop, loopVolumeCurveBehavior, muted, name, onVideoFrame, playbackRate, showInTimeline, style, trimAfter, trimBefore, volume, stack, toneFrequency, debugOverlay, headless, }) => {
30
- return (_jsx(InnerVideo, { audioStreamIndex: audioStreamIndex ?? 0, className: className, delayRenderRetries: delayRenderRetries ?? null, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? null, disallowFallbackToOffthreadVideo: disallowFallbackToOffthreadVideo ?? false, fallbackOffthreadVideoProps: fallbackOffthreadVideoProps ?? {}, logLevel: logLevel ??
31
- (typeof window !== 'undefined'
32
- ? (window.remotion_logLevel ?? 'info')
33
- : 'info'), loop: loop ?? false, loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? 'repeat', muted: muted ?? false, name: name, onVideoFrame: onVideoFrame, playbackRate: playbackRate ?? 1, showInTimeline: showInTimeline ?? true, src: src, style: style ?? {}, trimAfter: trimAfter, trimBefore: trimBefore, volume: volume ?? 1, toneFrequency: toneFrequency ?? 1, stack: stack, debugOverlay: debugOverlay ?? false, headless: headless ?? false }));
34
- };
35
- Internals.addSequenceStackTraces(Video);
@@ -1,125 +0,0 @@
1
- import { extractFrameAndAudio } from '../extract-frame-and-audio';
2
- // Send to other channels a message to let them know that the
3
- // tab was loaded and is ready to receive requests.
4
- // Emit "readiness" messages for approximately 10 seconds.
5
- const emitReadiness = (channel) => {
6
- channel.postMessage({
7
- type: 'main-tab-ready',
8
- });
9
- let times = 0;
10
- const interval = setInterval(() => {
11
- channel.postMessage({
12
- type: 'main-tab-ready',
13
- });
14
- times++;
15
- if (times > 30) {
16
- clearInterval(interval);
17
- }
18
- }, 300);
19
- };
20
- export const addBroadcastChannelListener = () => {
21
- // Doesn't exist in studio
22
- if (!(typeof window !== 'undefined' &&
23
- window.remotion_broadcastChannel &&
24
- window.remotion_isMainTab)) {
25
- return;
26
- }
27
- window.remotion_broadcastChannel.addEventListener('message', async (event) => {
28
- const data = event.data;
29
- if (data.type === 'request') {
30
- try {
31
- const result = await extractFrameAndAudio({
32
- src: data.src,
33
- timeInSeconds: data.timeInSeconds,
34
- logLevel: data.logLevel,
35
- durationInSeconds: data.durationInSeconds,
36
- playbackRate: data.playbackRate,
37
- includeAudio: data.includeAudio,
38
- includeVideo: data.includeVideo,
39
- loop: data.loop,
40
- audioStreamIndex: data.audioStreamIndex,
41
- trimAfter: data.trimAfter,
42
- trimBefore: data.trimBefore,
43
- fps: data.fps,
44
- maxCacheSize: data.maxCacheSize,
45
- });
46
- if (result.type === 'cannot-decode') {
47
- const cannotDecodeResponse = {
48
- type: 'response-cannot-decode',
49
- id: data.id,
50
- durationInSeconds: result.durationInSeconds,
51
- };
52
- window.remotion_broadcastChannel.postMessage(cannotDecodeResponse);
53
- return;
54
- }
55
- if (result.type === 'cannot-decode-alpha') {
56
- const cannotDecodeAlphaResponse = {
57
- type: 'response-cannot-decode-alpha',
58
- id: data.id,
59
- durationInSeconds: result.durationInSeconds,
60
- };
61
- window.remotion_broadcastChannel.postMessage(cannotDecodeAlphaResponse);
62
- return;
63
- }
64
- if (result.type === 'network-error') {
65
- const networkErrorResponse = {
66
- type: 'response-network-error',
67
- id: data.id,
68
- };
69
- window.remotion_broadcastChannel.postMessage(networkErrorResponse);
70
- return;
71
- }
72
- if (result.type === 'unknown-container-format') {
73
- const unknownContainerFormatResponse = {
74
- type: 'response-unknown-container-format',
75
- id: data.id,
76
- };
77
- window.remotion_broadcastChannel.postMessage(unknownContainerFormatResponse);
78
- return;
79
- }
80
- const { frame, audio, durationInSeconds } = result;
81
- const imageBitmap = frame ? await createImageBitmap(frame) : null;
82
- if (frame) {
83
- frame.close();
84
- }
85
- const response = {
86
- type: 'response-success',
87
- id: data.id,
88
- frame: imageBitmap,
89
- audio,
90
- durationInSeconds: durationInSeconds ?? null,
91
- };
92
- window.remotion_broadcastChannel.postMessage(response);
93
- }
94
- catch (error) {
95
- const response = {
96
- type: 'response-error',
97
- id: data.id,
98
- errorStack: error.stack ?? 'No stack trace',
99
- };
100
- window.remotion_broadcastChannel.postMessage(response);
101
- }
102
- }
103
- else {
104
- throw new Error('Invalid message: ' + JSON.stringify(data));
105
- }
106
- });
107
- emitReadiness(window.remotion_broadcastChannel);
108
- };
109
- let mainTabIsReadyProm = null;
110
- export const waitForMainTabToBeReady = (channel) => {
111
- if (mainTabIsReadyProm) {
112
- return mainTabIsReadyProm;
113
- }
114
- mainTabIsReadyProm = new Promise((resolve) => {
115
- const onMessage = (event) => {
116
- const data = event.data;
117
- if (data.type === 'main-tab-ready') {
118
- resolve();
119
- channel.removeEventListener('message', onMessage);
120
- }
121
- };
122
- channel.addEventListener('message', onMessage);
123
- });
124
- return mainTabIsReadyProm;
125
- };
@@ -1,113 +0,0 @@
1
- import { extractFrameAndAudio } from '../extract-frame-and-audio';
2
- import { addBroadcastChannelListener, waitForMainTabToBeReady, } from './add-broadcast-channel-listener';
3
- addBroadcastChannelListener();
4
- export const extractFrameViaBroadcastChannel = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, isClientSideRendering, loop, audioStreamIndex, trimAfter, trimBefore, fps, maxCacheSize, }) => {
5
- if (isClientSideRendering || window.remotion_isMainTab) {
6
- return extractFrameAndAudio({
7
- logLevel,
8
- src,
9
- timeInSeconds,
10
- durationInSeconds,
11
- playbackRate,
12
- includeAudio,
13
- includeVideo,
14
- loop,
15
- audioStreamIndex,
16
- trimAfter,
17
- trimBefore,
18
- fps,
19
- maxCacheSize,
20
- });
21
- }
22
- await waitForMainTabToBeReady(window.remotion_broadcastChannel);
23
- const requestId = crypto.randomUUID();
24
- const resolvePromise = new Promise((resolve, reject) => {
25
- const onMessage = (event) => {
26
- const data = event.data;
27
- if (!data) {
28
- return;
29
- }
30
- if (data.type === 'main-tab-ready') {
31
- return;
32
- }
33
- if (data.id !== requestId) {
34
- return;
35
- }
36
- if (data.type === 'response-success') {
37
- resolve({
38
- type: 'success',
39
- frame: data.frame ? data.frame : null,
40
- audio: data.audio ? data.audio : null,
41
- durationInSeconds: data.durationInSeconds
42
- ? data.durationInSeconds
43
- : null,
44
- });
45
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
46
- return;
47
- }
48
- if (data.type === 'response-error') {
49
- reject(data.errorStack);
50
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
51
- return;
52
- }
53
- if (data.type === 'response-cannot-decode') {
54
- resolve({
55
- type: 'cannot-decode',
56
- durationInSeconds: data.durationInSeconds,
57
- });
58
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
59
- return;
60
- }
61
- if (data.type === 'response-network-error') {
62
- resolve({ type: 'network-error' });
63
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
64
- return;
65
- }
66
- if (data.type === 'response-unknown-container-format') {
67
- resolve({ type: 'unknown-container-format' });
68
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
69
- return;
70
- }
71
- if (data.type === 'response-cannot-decode-alpha') {
72
- resolve({
73
- type: 'cannot-decode-alpha',
74
- durationInSeconds: data.durationInSeconds,
75
- });
76
- window.remotion_broadcastChannel.removeEventListener('message', onMessage);
77
- return;
78
- }
79
- throw new Error(`Invalid message: ${JSON.stringify(data)}`);
80
- };
81
- window.remotion_broadcastChannel.addEventListener('message', onMessage);
82
- });
83
- const request = {
84
- type: 'request',
85
- src,
86
- timeInSeconds,
87
- id: requestId,
88
- logLevel,
89
- durationInSeconds,
90
- playbackRate,
91
- includeAudio,
92
- includeVideo,
93
- loop,
94
- audioStreamIndex,
95
- trimAfter,
96
- trimBefore,
97
- fps,
98
- maxCacheSize,
99
- };
100
- window.remotion_broadcastChannel.postMessage(request);
101
- let timeoutId;
102
- return Promise.race([
103
- resolvePromise.then((res) => {
104
- clearTimeout(timeoutId);
105
- return res;
106
- }),
107
- new Promise((_, reject) => {
108
- timeoutId = setTimeout(() => {
109
- reject(new Error(`Timeout while extracting frame at time ${timeInSeconds}sec from ${src}`));
110
- }, Math.max(3000, window.remotion_puppeteerTimeout - 5000));
111
- }),
112
- ]);
113
- };