@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.
- package/dist/audio/audio-for-preview.d.ts +2 -0
- package/dist/audio/audio-preview-iterator.d.ts +8 -3
- package/dist/audio/props.d.ts +2 -0
- package/dist/audio-extraction/audio-iterator.d.ts +5 -4
- package/dist/audio-extraction/audio-manager.d.ts +23 -7
- package/dist/audio-extraction/extract-audio.d.ts +2 -4
- package/dist/audio-iterator-manager.d.ts +2 -2
- package/dist/caches.d.ts +34 -17
- package/dist/convert-audiodata/apply-volume.d.ts +1 -1
- package/dist/convert-audiodata/resample-audiodata.d.ts +2 -2
- package/dist/debug-overlay/preview-overlay.d.ts +83 -5
- package/dist/esm/index.mjs +524 -476
- package/dist/extract-frame-and-audio.d.ts +1 -2
- package/dist/get-sink.d.ts +1 -2
- package/dist/index.d.ts +2 -1
- package/dist/media-player.d.ts +1 -1
- package/dist/on-error.d.ts +12 -0
- package/dist/show-in-timeline.d.ts +2 -2
- package/dist/use-media-in-timeline.d.ts +2 -2
- package/dist/video/props.d.ts +5 -0
- package/dist/video/video-for-preview.d.ts +2 -0
- package/dist/video/video-for-rendering.d.ts +2 -0
- package/dist/video/video-preview-iterator.d.ts +7 -2
- package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +1 -2
- package/dist/video-extraction/extract-frame.d.ts +2 -4
- package/dist/video-extraction/get-frames-since-keyframe.d.ts +2 -12
- package/dist/video-extraction/keyframe-bank.d.ts +14 -12
- package/dist/video-extraction/keyframe-manager.d.ts +7 -9
- package/dist/video-iterator-manager.d.ts +4 -5
- package/package.json +8 -7
- package/dist/audio/allow-wait.js +0 -15
- package/dist/audio/audio-for-preview.js +0 -304
- package/dist/audio/audio-for-rendering.js +0 -194
- package/dist/audio/audio-preview-iterator.js +0 -176
- package/dist/audio/audio.js +0 -20
- package/dist/audio/props.js +0 -1
- package/dist/audio-extraction/audio-cache.js +0 -66
- package/dist/audio-extraction/audio-iterator.js +0 -132
- package/dist/audio-extraction/audio-manager.js +0 -113
- package/dist/audio-extraction/extract-audio.js +0 -132
- package/dist/audio-iterator-manager.js +0 -228
- package/dist/browser-can-use-webgl2.js +0 -13
- package/dist/caches.js +0 -61
- package/dist/calculate-playbacktime.js +0 -4
- package/dist/convert-audiodata/apply-volume.js +0 -17
- package/dist/convert-audiodata/combine-audiodata.js +0 -23
- package/dist/convert-audiodata/convert-audiodata.js +0 -73
- package/dist/convert-audiodata/resample-audiodata.js +0 -94
- package/dist/debug-overlay/preview-overlay.js +0 -44
- package/dist/extract-frame-and-audio.js +0 -101
- package/dist/get-sink.js +0 -15
- package/dist/get-time-in-seconds.js +0 -40
- package/dist/helpers/round-to-4-digits.js +0 -4
- package/dist/index.js +0 -12
- package/dist/is-type-of-error.js +0 -20
- package/dist/looped-frame.js +0 -10
- package/dist/media-player.js +0 -445
- package/dist/nonce-manager.js +0 -13
- package/dist/prewarm-iterator-for-looping.js +0 -56
- package/dist/render-timestamp-range.js +0 -9
- package/dist/show-in-timeline.js +0 -31
- package/dist/use-media-in-timeline.js +0 -103
- package/dist/video/props.js +0 -1
- package/dist/video/video-for-preview.js +0 -329
- package/dist/video/video-for-rendering.js +0 -263
- package/dist/video/video-preview-iterator.js +0 -122
- package/dist/video/video.js +0 -35
- package/dist/video-extraction/add-broadcast-channel-listener.js +0 -125
- package/dist/video-extraction/extract-frame-via-broadcast-channel.js +0 -113
- package/dist/video-extraction/extract-frame.js +0 -85
- package/dist/video-extraction/get-allocation-size.js +0 -6
- package/dist/video-extraction/get-frames-since-keyframe.js +0 -108
- package/dist/video-extraction/keyframe-bank.js +0 -159
- package/dist/video-extraction/keyframe-manager.js +0 -206
- package/dist/video-extraction/remember-actual-matroska-timestamps.js +0 -19
- package/dist/video-extraction/rotate-frame.js +0 -34
- package/dist/video-iterator-manager.js +0 -109
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Internals } from 'remotion';
|
|
2
|
-
export const getTimeInSeconds = ({ loop, mediaDurationInSeconds, unloopedTimeInSeconds, src, trimAfter, trimBefore, fps, playbackRate, ifNoMediaDuration, }) => {
|
|
3
|
-
if (mediaDurationInSeconds === null && loop && ifNoMediaDuration === 'fail') {
|
|
4
|
-
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
5
|
-
}
|
|
6
|
-
const loopDuration = loop
|
|
7
|
-
? Internals.calculateMediaDuration({
|
|
8
|
-
trimAfter,
|
|
9
|
-
mediaDurationInFrames: mediaDurationInSeconds
|
|
10
|
-
? mediaDurationInSeconds * fps
|
|
11
|
-
: Infinity,
|
|
12
|
-
// Playback rate was already specified before
|
|
13
|
-
playbackRate: 1,
|
|
14
|
-
trimBefore,
|
|
15
|
-
}) / fps
|
|
16
|
-
: Infinity;
|
|
17
|
-
const timeInSeconds = (unloopedTimeInSeconds * playbackRate) % loopDuration;
|
|
18
|
-
if ((trimAfter ?? null) !== null && !loop) {
|
|
19
|
-
const time = (trimAfter - (trimBefore ?? 0)) / fps;
|
|
20
|
-
if (timeInSeconds >= time) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return timeInSeconds + (trimBefore ?? 0) / fps;
|
|
25
|
-
};
|
|
26
|
-
export const calculateEndTime = ({ mediaDurationInSeconds, ifNoMediaDuration, src, trimAfter, trimBefore, fps, }) => {
|
|
27
|
-
if (mediaDurationInSeconds === null && ifNoMediaDuration === 'fail') {
|
|
28
|
-
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
29
|
-
}
|
|
30
|
-
const mediaDuration = Internals.calculateMediaDuration({
|
|
31
|
-
trimAfter,
|
|
32
|
-
mediaDurationInFrames: mediaDurationInSeconds
|
|
33
|
-
? mediaDurationInSeconds * fps
|
|
34
|
-
: Infinity,
|
|
35
|
-
// Playback rate was already specified before
|
|
36
|
-
playbackRate: 1,
|
|
37
|
-
trimBefore,
|
|
38
|
-
}) / fps;
|
|
39
|
-
return mediaDuration + (trimBefore ?? 0) / fps;
|
|
40
|
-
};
|
package/dist/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Audio } from './audio/audio';
|
|
2
|
-
import { Video } from './video/video';
|
|
3
|
-
/**
|
|
4
|
-
* @deprecated Now just `Audio`
|
|
5
|
-
*/
|
|
6
|
-
export const experimental_Audio = Audio;
|
|
7
|
-
/**
|
|
8
|
-
* @deprecated Now just `Video`
|
|
9
|
-
*/
|
|
10
|
-
export const experimental_Video = Video;
|
|
11
|
-
export { AudioForPreview } from './audio/audio-for-preview';
|
|
12
|
-
export { Audio, Video };
|
package/dist/is-type-of-error.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility to check if error is network error
|
|
3
|
-
* @param error
|
|
4
|
-
* @returns
|
|
5
|
-
*/
|
|
6
|
-
export function isNetworkError(error) {
|
|
7
|
-
if (
|
|
8
|
-
// Chrome
|
|
9
|
-
error.message.includes('Failed to fetch') ||
|
|
10
|
-
// Safari
|
|
11
|
-
error.message.includes('Load failed') ||
|
|
12
|
-
// Firefox
|
|
13
|
-
error.message.includes('NetworkError when attempting to fetch resource')) {
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
export function isUnsupportedConfigurationError(error) {
|
|
19
|
-
return error.message.includes('Unsupported configuration');
|
|
20
|
-
}
|
package/dist/looped-frame.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const frameForVolumeProp = ({ behavior, loop, assetDurationInSeconds, fps, frame, startsAt, }) => {
|
|
2
|
-
if (!loop) {
|
|
3
|
-
return frame + startsAt;
|
|
4
|
-
}
|
|
5
|
-
if (behavior === 'extend') {
|
|
6
|
-
return frame + startsAt;
|
|
7
|
-
}
|
|
8
|
-
const assetDurationInFrames = Math.floor(assetDurationInSeconds * fps) - startsAt;
|
|
9
|
-
return (frame % assetDurationInFrames) + startsAt;
|
|
10
|
-
};
|
package/dist/media-player.js
DELETED
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { ALL_FORMATS, Input, UrlSource } from 'mediabunny';
|
|
2
|
-
import { Internals } from 'remotion';
|
|
3
|
-
import { audioIteratorManager, } from './audio-iterator-manager';
|
|
4
|
-
import { calculatePlaybackTime } from './calculate-playbacktime';
|
|
5
|
-
import { drawPreviewOverlay } from './debug-overlay/preview-overlay';
|
|
6
|
-
import { calculateEndTime, getTimeInSeconds } from './get-time-in-seconds';
|
|
7
|
-
import { isNetworkError } from './is-type-of-error';
|
|
8
|
-
import { makeNonceManager } from './nonce-manager';
|
|
9
|
-
import { videoIteratorManager } from './video-iterator-manager';
|
|
10
|
-
export class MediaPlayer {
|
|
11
|
-
constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, onVideoFrameCallback, playing, }) {
|
|
12
|
-
this.audioIteratorManager = null;
|
|
13
|
-
this.videoIteratorManager = null;
|
|
14
|
-
// this is the time difference between Web Audio timeline
|
|
15
|
-
// and media file timeline
|
|
16
|
-
this.audioSyncAnchor = 0;
|
|
17
|
-
this.playing = false;
|
|
18
|
-
this.loop = false;
|
|
19
|
-
this.debugOverlay = false;
|
|
20
|
-
this.onVideoFrameCallback = null;
|
|
21
|
-
this.initializationPromise = null;
|
|
22
|
-
this.seekPromiseChain = Promise.resolve();
|
|
23
|
-
this.delayPlaybackHandleIfNotPremounting = () => {
|
|
24
|
-
if (this.isPremounting || this.isPostmounting) {
|
|
25
|
-
return {
|
|
26
|
-
unblock: () => { },
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
return this.bufferState.delayPlayback();
|
|
30
|
-
};
|
|
31
|
-
this.scheduleAudioNode = (node, mediaTimestamp) => {
|
|
32
|
-
const currentTime = this.getAudioPlaybackTime();
|
|
33
|
-
const delayWithoutPlaybackRate = mediaTimestamp - currentTime;
|
|
34
|
-
const delay = delayWithoutPlaybackRate / (this.playbackRate * this.globalPlaybackRate);
|
|
35
|
-
if (!this.sharedAudioContext) {
|
|
36
|
-
throw new Error('Shared audio context not found');
|
|
37
|
-
}
|
|
38
|
-
if (delay >= 0) {
|
|
39
|
-
node.start(this.sharedAudioContext.currentTime + delay);
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
node.start(this.sharedAudioContext.currentTime, -delay);
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
this.drawDebugOverlay = () => {
|
|
46
|
-
if (!this.debugOverlay)
|
|
47
|
-
return;
|
|
48
|
-
if (this.context && this.canvas) {
|
|
49
|
-
drawPreviewOverlay({
|
|
50
|
-
context: this.context,
|
|
51
|
-
audioTime: this.sharedAudioContext?.currentTime ?? null,
|
|
52
|
-
audioContextState: this.sharedAudioContext?.state ?? null,
|
|
53
|
-
audioSyncAnchor: this.audioSyncAnchor,
|
|
54
|
-
audioIteratorManager: this.audioIteratorManager,
|
|
55
|
-
playing: this.playing,
|
|
56
|
-
videoIteratorManager: this.videoIteratorManager,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
this.canvas = canvas ?? null;
|
|
61
|
-
this.src = src;
|
|
62
|
-
this.logLevel = logLevel ?? window.remotion_logLevel;
|
|
63
|
-
this.sharedAudioContext = sharedAudioContext;
|
|
64
|
-
this.playbackRate = playbackRate;
|
|
65
|
-
this.globalPlaybackRate = globalPlaybackRate;
|
|
66
|
-
this.loop = loop;
|
|
67
|
-
this.trimBefore = trimBefore;
|
|
68
|
-
this.trimAfter = trimAfter;
|
|
69
|
-
this.audioStreamIndex = audioStreamIndex ?? 0;
|
|
70
|
-
this.fps = fps;
|
|
71
|
-
this.debugOverlay = debugOverlay;
|
|
72
|
-
this.bufferState = bufferState;
|
|
73
|
-
this.isPremounting = isPremounting;
|
|
74
|
-
this.isPostmounting = isPostmounting;
|
|
75
|
-
this.nonceManager = makeNonceManager();
|
|
76
|
-
this.onVideoFrameCallback = onVideoFrameCallback;
|
|
77
|
-
this.playing = playing;
|
|
78
|
-
this.input = new Input({
|
|
79
|
-
source: new UrlSource(this.src),
|
|
80
|
-
formats: ALL_FORMATS,
|
|
81
|
-
});
|
|
82
|
-
if (canvas) {
|
|
83
|
-
const context = canvas.getContext('2d', {
|
|
84
|
-
alpha: true,
|
|
85
|
-
desynchronized: true,
|
|
86
|
-
});
|
|
87
|
-
if (!context) {
|
|
88
|
-
throw new Error('Could not get 2D context from canvas');
|
|
89
|
-
}
|
|
90
|
-
this.context = context;
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
this.context = null;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
isDisposalError() {
|
|
97
|
-
return this.input.disposed === true;
|
|
98
|
-
}
|
|
99
|
-
initialize(startTimeUnresolved) {
|
|
100
|
-
const promise = this._initialize(startTimeUnresolved);
|
|
101
|
-
this.initializationPromise = promise;
|
|
102
|
-
this.seekPromiseChain = promise;
|
|
103
|
-
return promise;
|
|
104
|
-
}
|
|
105
|
-
getStartTime() {
|
|
106
|
-
return (this.trimBefore ?? 0) / this.fps;
|
|
107
|
-
}
|
|
108
|
-
getEndTime() {
|
|
109
|
-
return calculateEndTime({
|
|
110
|
-
mediaDurationInSeconds: this.totalDuration,
|
|
111
|
-
ifNoMediaDuration: 'fail',
|
|
112
|
-
src: this.src,
|
|
113
|
-
trimAfter: this.trimAfter,
|
|
114
|
-
trimBefore: this.trimBefore,
|
|
115
|
-
fps: this.fps,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
async _initialize(startTimeUnresolved) {
|
|
119
|
-
const delayHandle = this.delayPlaybackHandleIfNotPremounting();
|
|
120
|
-
try {
|
|
121
|
-
if (this.input.disposed) {
|
|
122
|
-
return { type: 'disposed' };
|
|
123
|
-
}
|
|
124
|
-
try {
|
|
125
|
-
await this.input.getFormat();
|
|
126
|
-
}
|
|
127
|
-
catch (error) {
|
|
128
|
-
if (this.isDisposalError()) {
|
|
129
|
-
return { type: 'disposed' };
|
|
130
|
-
}
|
|
131
|
-
const err = error;
|
|
132
|
-
if (isNetworkError(err)) {
|
|
133
|
-
throw error;
|
|
134
|
-
}
|
|
135
|
-
Internals.Log.error({ logLevel: this.logLevel, tag: '@remotion/media' }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
|
|
136
|
-
return { type: 'unknown-container-format' };
|
|
137
|
-
}
|
|
138
|
-
const [durationInSeconds, videoTrack, audioTracks] = await Promise.all([
|
|
139
|
-
this.input.computeDuration(),
|
|
140
|
-
this.input.getPrimaryVideoTrack(),
|
|
141
|
-
this.input.getAudioTracks(),
|
|
142
|
-
]);
|
|
143
|
-
if (this.input.disposed) {
|
|
144
|
-
return { type: 'disposed' };
|
|
145
|
-
}
|
|
146
|
-
this.totalDuration = durationInSeconds;
|
|
147
|
-
const audioTrack = audioTracks[this.audioStreamIndex] ?? null;
|
|
148
|
-
if (!videoTrack && !audioTrack) {
|
|
149
|
-
return { type: 'no-tracks' };
|
|
150
|
-
}
|
|
151
|
-
if (videoTrack) {
|
|
152
|
-
const canDecode = await videoTrack.canDecode();
|
|
153
|
-
if (!canDecode) {
|
|
154
|
-
return { type: 'cannot-decode' };
|
|
155
|
-
}
|
|
156
|
-
if (this.input.disposed) {
|
|
157
|
-
return { type: 'disposed' };
|
|
158
|
-
}
|
|
159
|
-
this.videoIteratorManager = videoIteratorManager({
|
|
160
|
-
videoTrack,
|
|
161
|
-
delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
|
|
162
|
-
context: this.context,
|
|
163
|
-
canvas: this.canvas,
|
|
164
|
-
getOnVideoFrameCallback: () => this.onVideoFrameCallback,
|
|
165
|
-
logLevel: this.logLevel,
|
|
166
|
-
drawDebugOverlay: this.drawDebugOverlay,
|
|
167
|
-
getEndTime: () => this.getEndTime(),
|
|
168
|
-
getStartTime: () => this.getStartTime(),
|
|
169
|
-
getIsLooping: () => this.loop,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
const startTime = getTimeInSeconds({
|
|
173
|
-
unloopedTimeInSeconds: startTimeUnresolved,
|
|
174
|
-
playbackRate: this.playbackRate,
|
|
175
|
-
loop: this.loop,
|
|
176
|
-
trimBefore: this.trimBefore,
|
|
177
|
-
trimAfter: this.trimAfter,
|
|
178
|
-
mediaDurationInSeconds: this.totalDuration,
|
|
179
|
-
fps: this.fps,
|
|
180
|
-
ifNoMediaDuration: 'infinity',
|
|
181
|
-
src: this.src,
|
|
182
|
-
});
|
|
183
|
-
if (startTime === null) {
|
|
184
|
-
throw new Error(`should have asserted that the time is not null`);
|
|
185
|
-
}
|
|
186
|
-
this.setPlaybackTime(startTime, this.playbackRate * this.globalPlaybackRate);
|
|
187
|
-
if (audioTrack && this.sharedAudioContext) {
|
|
188
|
-
this.audioIteratorManager = audioIteratorManager({
|
|
189
|
-
audioTrack,
|
|
190
|
-
delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
|
|
191
|
-
sharedAudioContext: this.sharedAudioContext,
|
|
192
|
-
getIsLooping: () => this.loop,
|
|
193
|
-
getEndTime: () => this.getEndTime(),
|
|
194
|
-
getStartTime: () => this.getStartTime(),
|
|
195
|
-
updatePlaybackTime: (time) => this.setPlaybackTime(time, this.playbackRate * this.globalPlaybackRate),
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
const nonce = this.nonceManager.createAsyncOperation();
|
|
199
|
-
try {
|
|
200
|
-
await Promise.all([
|
|
201
|
-
this.audioIteratorManager
|
|
202
|
-
? this.audioIteratorManager.startAudioIterator({
|
|
203
|
-
nonce,
|
|
204
|
-
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
205
|
-
startFromSecond: startTime,
|
|
206
|
-
getIsPlaying: () => this.playing,
|
|
207
|
-
scheduleAudioNode: this.scheduleAudioNode,
|
|
208
|
-
})
|
|
209
|
-
: Promise.resolve(),
|
|
210
|
-
this.videoIteratorManager
|
|
211
|
-
? this.videoIteratorManager.startVideoIterator(startTime, nonce)
|
|
212
|
-
: Promise.resolve(),
|
|
213
|
-
]);
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
if (this.isDisposalError()) {
|
|
217
|
-
return { type: 'disposed' };
|
|
218
|
-
}
|
|
219
|
-
Internals.Log.error({ logLevel: this.logLevel, tag: '@remotion/media' }, '[MediaPlayer] Failed to start audio and video iterators', error);
|
|
220
|
-
}
|
|
221
|
-
return { type: 'success', durationInSeconds };
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
const err = error;
|
|
225
|
-
if (isNetworkError(err)) {
|
|
226
|
-
Internals.Log.error({ logLevel: this.logLevel, tag: '@remotion/media' }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
|
|
227
|
-
return { type: 'network-error' };
|
|
228
|
-
}
|
|
229
|
-
Internals.Log.error({ logLevel: this.logLevel, tag: '@remotion/media' }, '[MediaPlayer] Failed to initialize', error);
|
|
230
|
-
throw error;
|
|
231
|
-
}
|
|
232
|
-
finally {
|
|
233
|
-
delayHandle.unblock();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
async seekTo(time) {
|
|
237
|
-
const newTime = getTimeInSeconds({
|
|
238
|
-
unloopedTimeInSeconds: time,
|
|
239
|
-
playbackRate: this.playbackRate,
|
|
240
|
-
loop: this.loop,
|
|
241
|
-
trimBefore: this.trimBefore,
|
|
242
|
-
trimAfter: this.trimAfter,
|
|
243
|
-
mediaDurationInSeconds: this.totalDuration ?? null,
|
|
244
|
-
fps: this.fps,
|
|
245
|
-
ifNoMediaDuration: 'infinity',
|
|
246
|
-
src: this.src,
|
|
247
|
-
});
|
|
248
|
-
if (newTime === null) {
|
|
249
|
-
throw new Error(`should have asserted that the time is not null`);
|
|
250
|
-
}
|
|
251
|
-
const nonce = this.nonceManager.createAsyncOperation();
|
|
252
|
-
await this.seekPromiseChain;
|
|
253
|
-
this.seekPromiseChain = this.seekToDoNotCallDirectly(newTime, nonce);
|
|
254
|
-
await this.seekPromiseChain;
|
|
255
|
-
}
|
|
256
|
-
async seekToDoNotCallDirectly(newTime, nonce) {
|
|
257
|
-
if (nonce.isStale()) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
const shouldSeekAudio = this.audioIteratorManager &&
|
|
261
|
-
this.sharedAudioContext &&
|
|
262
|
-
this.getAudioPlaybackTime() !== newTime;
|
|
263
|
-
await Promise.all([
|
|
264
|
-
this.videoIteratorManager?.seek({
|
|
265
|
-
newTime,
|
|
266
|
-
nonce,
|
|
267
|
-
}),
|
|
268
|
-
shouldSeekAudio
|
|
269
|
-
? this.audioIteratorManager?.seek({
|
|
270
|
-
newTime,
|
|
271
|
-
nonce,
|
|
272
|
-
fps: this.fps,
|
|
273
|
-
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
274
|
-
getIsPlaying: () => this.playing,
|
|
275
|
-
scheduleAudioNode: this.scheduleAudioNode,
|
|
276
|
-
bufferState: this.bufferState,
|
|
277
|
-
})
|
|
278
|
-
: null,
|
|
279
|
-
]);
|
|
280
|
-
}
|
|
281
|
-
async play(time) {
|
|
282
|
-
if (this.playing) {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const newTime = getTimeInSeconds({
|
|
286
|
-
unloopedTimeInSeconds: time,
|
|
287
|
-
playbackRate: this.playbackRate,
|
|
288
|
-
loop: this.loop,
|
|
289
|
-
trimBefore: this.trimBefore,
|
|
290
|
-
trimAfter: this.trimAfter,
|
|
291
|
-
mediaDurationInSeconds: this.totalDuration ?? null,
|
|
292
|
-
fps: this.fps,
|
|
293
|
-
ifNoMediaDuration: 'infinity',
|
|
294
|
-
src: this.src,
|
|
295
|
-
});
|
|
296
|
-
if (newTime === null) {
|
|
297
|
-
throw new Error(`should have asserted that the time is not null`);
|
|
298
|
-
}
|
|
299
|
-
this.setPlaybackTime(newTime, this.playbackRate * this.globalPlaybackRate);
|
|
300
|
-
this.playing = true;
|
|
301
|
-
if (this.audioIteratorManager) {
|
|
302
|
-
this.audioIteratorManager.resumeScheduledAudioChunks({
|
|
303
|
-
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
304
|
-
scheduleAudioNode: this.scheduleAudioNode,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
if (this.sharedAudioContext &&
|
|
308
|
-
this.sharedAudioContext.state === 'suspended') {
|
|
309
|
-
await this.sharedAudioContext.resume();
|
|
310
|
-
}
|
|
311
|
-
this.drawDebugOverlay();
|
|
312
|
-
}
|
|
313
|
-
pause() {
|
|
314
|
-
if (!this.playing) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
this.playing = false;
|
|
318
|
-
this.audioIteratorManager?.pausePlayback();
|
|
319
|
-
this.drawDebugOverlay();
|
|
320
|
-
}
|
|
321
|
-
setMuted(muted) {
|
|
322
|
-
this.audioIteratorManager?.setMuted(muted);
|
|
323
|
-
}
|
|
324
|
-
setVolume(volume) {
|
|
325
|
-
if (!this.audioIteratorManager) {
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
this.audioIteratorManager.setVolume(volume);
|
|
329
|
-
}
|
|
330
|
-
updateAfterTrimChange(unloopedTimeInSeconds) {
|
|
331
|
-
if (!this.audioIteratorManager && !this.videoIteratorManager) {
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const newMediaTime = getTimeInSeconds({
|
|
335
|
-
unloopedTimeInSeconds,
|
|
336
|
-
playbackRate: this.playbackRate,
|
|
337
|
-
loop: this.loop,
|
|
338
|
-
trimBefore: this.trimBefore,
|
|
339
|
-
trimAfter: this.trimAfter,
|
|
340
|
-
mediaDurationInSeconds: this.totalDuration ?? null,
|
|
341
|
-
fps: this.fps,
|
|
342
|
-
ifNoMediaDuration: 'infinity',
|
|
343
|
-
src: this.src,
|
|
344
|
-
});
|
|
345
|
-
if (newMediaTime !== null) {
|
|
346
|
-
this.setPlaybackTime(newMediaTime, this.playbackRate * this.globalPlaybackRate);
|
|
347
|
-
}
|
|
348
|
-
// audio iterator will be re-created on next play/seek
|
|
349
|
-
// video iterator doesn't need to be re-created
|
|
350
|
-
this.audioIteratorManager?.destroyIterator();
|
|
351
|
-
}
|
|
352
|
-
setTrimBefore(trimBefore, unloopedTimeInSeconds) {
|
|
353
|
-
if (this.trimBefore !== trimBefore) {
|
|
354
|
-
this.trimBefore = trimBefore;
|
|
355
|
-
this.updateAfterTrimChange(unloopedTimeInSeconds);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
setTrimAfter(trimAfter, unloopedTimeInSeconds) {
|
|
359
|
-
if (this.trimAfter !== trimAfter) {
|
|
360
|
-
this.trimAfter = trimAfter;
|
|
361
|
-
this.updateAfterTrimChange(unloopedTimeInSeconds);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
setDebugOverlay(debugOverlay) {
|
|
365
|
-
this.debugOverlay = debugOverlay;
|
|
366
|
-
}
|
|
367
|
-
updateAudioTimeAfterPlaybackRateChange() {
|
|
368
|
-
if (!this.audioIteratorManager) {
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
if (!this.sharedAudioContext) {
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
this.setPlaybackTime(this.getAudioPlaybackTime(), this.playbackRate * this.globalPlaybackRate);
|
|
375
|
-
const iterator = this.audioIteratorManager.getAudioBufferIterator();
|
|
376
|
-
if (!iterator) {
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
iterator.moveQueuedChunksToPauseQueue();
|
|
380
|
-
if (this.playing) {
|
|
381
|
-
this.audioIteratorManager.resumeScheduledAudioChunks({
|
|
382
|
-
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
383
|
-
scheduleAudioNode: this.scheduleAudioNode,
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
setPlaybackRate(rate) {
|
|
388
|
-
this.playbackRate = rate;
|
|
389
|
-
this.updateAudioTimeAfterPlaybackRateChange();
|
|
390
|
-
}
|
|
391
|
-
setGlobalPlaybackRate(rate) {
|
|
392
|
-
this.globalPlaybackRate = rate;
|
|
393
|
-
this.updateAudioTimeAfterPlaybackRateChange();
|
|
394
|
-
}
|
|
395
|
-
setFps(fps) {
|
|
396
|
-
this.fps = fps;
|
|
397
|
-
}
|
|
398
|
-
setIsPremounting(isPremounting) {
|
|
399
|
-
this.isPremounting = isPremounting;
|
|
400
|
-
}
|
|
401
|
-
setIsPostmounting(isPostmounting) {
|
|
402
|
-
this.isPostmounting = isPostmounting;
|
|
403
|
-
}
|
|
404
|
-
setLoop(loop) {
|
|
405
|
-
this.loop = loop;
|
|
406
|
-
}
|
|
407
|
-
async dispose() {
|
|
408
|
-
if (this.initializationPromise) {
|
|
409
|
-
try {
|
|
410
|
-
// wait for the init to finished
|
|
411
|
-
// otherwise we might get errors like:
|
|
412
|
-
// Error: Response stream reader stopped unexpectedly before all requested data was read. from UrlSource
|
|
413
|
-
await this.initializationPromise;
|
|
414
|
-
}
|
|
415
|
-
catch {
|
|
416
|
-
// Ignore initialization errors during disposal
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
// Mark all async operations as stale
|
|
420
|
-
this.nonceManager.createAsyncOperation();
|
|
421
|
-
this.videoIteratorManager?.destroy();
|
|
422
|
-
this.audioIteratorManager?.destroyIterator();
|
|
423
|
-
this.input.dispose();
|
|
424
|
-
}
|
|
425
|
-
getAudioPlaybackTime() {
|
|
426
|
-
if (!this.sharedAudioContext) {
|
|
427
|
-
throw new Error('Shared audio context not found');
|
|
428
|
-
}
|
|
429
|
-
return calculatePlaybackTime({
|
|
430
|
-
audioSyncAnchor: this.audioSyncAnchor,
|
|
431
|
-
currentTime: this.sharedAudioContext.currentTime,
|
|
432
|
-
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
setPlaybackTime(time, playbackRate) {
|
|
436
|
-
if (!this.sharedAudioContext) {
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
this.audioSyncAnchor =
|
|
440
|
-
this.sharedAudioContext.currentTime - time / playbackRate;
|
|
441
|
-
}
|
|
442
|
-
setVideoFrameCallback(callback) {
|
|
443
|
-
this.onVideoFrameCallback = callback;
|
|
444
|
-
}
|
|
445
|
-
}
|
package/dist/nonce-manager.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const renderTimestampRange = (timestamps) => {
|
|
2
|
-
if (timestamps.length === 0) {
|
|
3
|
-
return '(none)';
|
|
4
|
-
}
|
|
5
|
-
if (timestamps.length === 1) {
|
|
6
|
-
return timestamps[0].toFixed(3);
|
|
7
|
-
}
|
|
8
|
-
return `${timestamps[0].toFixed(3)}...${timestamps[timestamps.length - 1].toFixed(3)}`;
|
|
9
|
-
};
|
package/dist/show-in-timeline.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { Internals, useVideoConfig } from 'remotion';
|
|
3
|
-
export const useLoopDisplay = ({ loop, mediaDurationInSeconds, playbackRate, trimAfter, trimBefore, }) => {
|
|
4
|
-
const { durationInFrames: compDuration, fps } = useVideoConfig();
|
|
5
|
-
const loopDisplay = useMemo(() => {
|
|
6
|
-
if (!loop || !mediaDurationInSeconds) {
|
|
7
|
-
return undefined;
|
|
8
|
-
}
|
|
9
|
-
const durationInFrames = Internals.calculateMediaDuration({
|
|
10
|
-
mediaDurationInFrames: mediaDurationInSeconds * fps,
|
|
11
|
-
playbackRate,
|
|
12
|
-
trimAfter,
|
|
13
|
-
trimBefore,
|
|
14
|
-
});
|
|
15
|
-
const maxTimes = compDuration / durationInFrames;
|
|
16
|
-
return {
|
|
17
|
-
numberOfTimes: maxTimes,
|
|
18
|
-
startOffset: 0,
|
|
19
|
-
durationInFrames,
|
|
20
|
-
};
|
|
21
|
-
}, [
|
|
22
|
-
compDuration,
|
|
23
|
-
fps,
|
|
24
|
-
loop,
|
|
25
|
-
mediaDurationInSeconds,
|
|
26
|
-
playbackRate,
|
|
27
|
-
trimAfter,
|
|
28
|
-
trimBefore,
|
|
29
|
-
]);
|
|
30
|
-
return loopDisplay;
|
|
31
|
-
};
|