@remotion/media 4.0.431 → 4.0.433
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 +5 -2
- package/dist/audio/audio-preview-iterator.d.ts +16 -9
- package/dist/audio/audio.d.ts +1 -1
- package/dist/audio/props.d.ts +1 -0
- package/dist/audio-iterator-manager.d.ts +24 -13
- package/dist/debug-overlay/preview-overlay.d.ts +24 -14
- package/dist/esm/index.mjs +827 -597
- package/dist/index.d.ts +32 -2
- package/dist/make-iterator-with-priming.d.ts +6 -0
- package/dist/media-player.d.ts +12 -7
- package/dist/prewarm-iterator-for-looping.d.ts +3 -2
- package/dist/set-global-time-anchor.d.ts +11 -0
- package/dist/shared-audio-context-for-media-player.d.ts +8 -0
- package/dist/use-common-effects.d.ts +32 -0
- package/dist/video/props.d.ts +1 -0
- package/dist/video/video-for-preview.d.ts +5 -2
- package/dist/video/video.d.ts +31 -2
- package/package.json +4 -4
- package/dist/audio/allow-wait.d.ts +0 -6
- 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 -42
- 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-network-error.d.ts +0 -6
- package/dist/is-network-error.js +0 -17
- package/dist/is-type-of-error.js +0 -20
- package/dist/looped-frame.js +0 -10
- package/dist/media-player.js +0 -431
- 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 -331
- 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
package/dist/esm/index.mjs
CHANGED
|
@@ -37,19 +37,12 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
// src/audio/audio.tsx
|
|
40
|
-
import { Internals as
|
|
40
|
+
import { Internals as Internals19, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
|
|
41
41
|
|
|
42
42
|
// src/audio/audio-for-preview.tsx
|
|
43
|
+
import { useContext as useContext3, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
43
44
|
import {
|
|
44
|
-
|
|
45
|
-
useEffect as useEffect2,
|
|
46
|
-
useLayoutEffect,
|
|
47
|
-
useMemo as useMemo2,
|
|
48
|
-
useRef,
|
|
49
|
-
useState as useState2
|
|
50
|
-
} from "react";
|
|
51
|
-
import {
|
|
52
|
-
Internals as Internals6,
|
|
45
|
+
Internals as Internals10,
|
|
53
46
|
Audio as RemotionAudio,
|
|
54
47
|
useBufferState,
|
|
55
48
|
useCurrentFrame as useCurrentFrame2,
|
|
@@ -109,27 +102,65 @@ var calculateEndTime = ({
|
|
|
109
102
|
|
|
110
103
|
// src/media-player.ts
|
|
111
104
|
import { ALL_FORMATS, Input, UrlSource } from "mediabunny";
|
|
112
|
-
import { Internals as
|
|
105
|
+
import { Internals as Internals6 } from "remotion";
|
|
113
106
|
|
|
114
107
|
// src/audio-iterator-manager.ts
|
|
115
108
|
import { AudioBufferSink, InputDisposedError } from "mediabunny";
|
|
109
|
+
import { Internals as Internals4 } from "remotion";
|
|
110
|
+
|
|
111
|
+
// src/audio/audio-preview-iterator.ts
|
|
112
|
+
import { Internals as Internals3 } from "remotion";
|
|
116
113
|
|
|
117
114
|
// src/helpers/round-to-4-digits.ts
|
|
118
115
|
var roundTo4Digits = (timestamp) => {
|
|
119
116
|
return Math.round(timestamp * 1000) / 1000;
|
|
120
117
|
};
|
|
121
118
|
|
|
119
|
+
// src/set-global-time-anchor.ts
|
|
120
|
+
import { Internals as Internals2 } from "remotion";
|
|
121
|
+
var ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
|
|
122
|
+
var setGlobalTimeAnchor = ({
|
|
123
|
+
audioContext,
|
|
124
|
+
audioSyncAnchor,
|
|
125
|
+
absoluteTimeInSeconds,
|
|
126
|
+
globalPlaybackRate,
|
|
127
|
+
debugAudioScheduling,
|
|
128
|
+
logLevel
|
|
129
|
+
}) => {
|
|
130
|
+
const newAnchor = audioContext.currentTime - absoluteTimeInSeconds / globalPlaybackRate;
|
|
131
|
+
const shift = (newAnchor - audioSyncAnchor.value) * globalPlaybackRate;
|
|
132
|
+
if (Math.abs(shift) < ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (debugAudioScheduling) {
|
|
136
|
+
Internals2.Log.info({ logLevel, tag: "audio-scheduling" }, "Anchor changed from %s to %s with shift %s", audioSyncAnchor.value, newAnchor, shift);
|
|
137
|
+
}
|
|
138
|
+
audioSyncAnchor.value = newAnchor;
|
|
139
|
+
};
|
|
140
|
+
|
|
122
141
|
// src/audio/audio-preview-iterator.ts
|
|
123
|
-
var makeAudioIterator = (startFromSecond, cache) => {
|
|
142
|
+
var makeAudioIterator = (startFromSecond, maximumTimestamp, cache, debugAudioScheduling) => {
|
|
124
143
|
let destroyed = false;
|
|
125
|
-
const iterator = cache.makeIteratorOrUsePrewarmed(startFromSecond);
|
|
144
|
+
const iterator = cache.makeIteratorOrUsePrewarmed(startFromSecond, maximumTimestamp);
|
|
126
145
|
const queuedAudioNodes = [];
|
|
127
146
|
const audioChunksForAfterResuming = [];
|
|
128
147
|
let mostRecentTimestamp = -Infinity;
|
|
129
148
|
let pendingNext = null;
|
|
130
|
-
const cleanupAudioQueue = () => {
|
|
149
|
+
const cleanupAudioQueue = (audioContext) => {
|
|
131
150
|
for (const node of queuedAudioNodes) {
|
|
132
|
-
|
|
151
|
+
try {
|
|
152
|
+
const currentlyHearing = audioContext.getOutputTimestamp().contextTime;
|
|
153
|
+
const nodeEndTime = node.scheduledTime + node.buffer.duration / node.playbackRate;
|
|
154
|
+
const isAlreadyPlaying = node.scheduledTime - ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT < audioContext.currentTime;
|
|
155
|
+
const shouldKeep = isAlreadyPlaying;
|
|
156
|
+
if (shouldKeep) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (debugAudioScheduling) {
|
|
160
|
+
Internals3.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, `Stopping node ${node.timestamp.toFixed(3)}, currently hearing = ${currentlyHearing.toFixed(3)} currentTime = ${audioContext.currentTime.toFixed(3)} nodeEndTime = ${nodeEndTime.toFixed(3)} scheduledTime = ${node.scheduledTime.toFixed(3)}`);
|
|
161
|
+
}
|
|
162
|
+
node.node.stop();
|
|
163
|
+
} catch {}
|
|
133
164
|
}
|
|
134
165
|
queuedAudioNodes.length = 0;
|
|
135
166
|
};
|
|
@@ -238,26 +269,34 @@ var makeAudioIterator = (startFromSecond, cache) => {
|
|
|
238
269
|
const removeAndReturnAllQueuedAudioNodes = () => {
|
|
239
270
|
const nodes = queuedAudioNodes.slice();
|
|
240
271
|
for (const node of nodes) {
|
|
241
|
-
|
|
272
|
+
try {
|
|
273
|
+
node.node.stop();
|
|
274
|
+
} catch {}
|
|
242
275
|
}
|
|
243
276
|
queuedAudioNodes.length = 0;
|
|
244
277
|
return nodes;
|
|
245
278
|
};
|
|
246
|
-
const addChunkForAfterResuming = (buffer, timestamp
|
|
247
|
-
audioChunksForAfterResuming.push({
|
|
279
|
+
const addChunkForAfterResuming = (buffer, timestamp) => {
|
|
280
|
+
audioChunksForAfterResuming.push({
|
|
281
|
+
buffer,
|
|
282
|
+
timestamp
|
|
283
|
+
});
|
|
248
284
|
};
|
|
249
285
|
const moveQueuedChunksToPauseQueue = () => {
|
|
250
286
|
const toQueue = removeAndReturnAllQueuedAudioNodes();
|
|
251
287
|
for (const chunk of toQueue) {
|
|
252
|
-
addChunkForAfterResuming(chunk.buffer, chunk.timestamp
|
|
288
|
+
addChunkForAfterResuming(chunk.buffer, chunk.timestamp);
|
|
289
|
+
}
|
|
290
|
+
if (debugAudioScheduling && toQueue.length > 0) {
|
|
291
|
+
Internals3.Log.trace({ logLevel: "trace", tag: "audio-scheduling" }, `Moved ${toQueue.length} ${toQueue.length === 1 ? "chunk" : "chunks"} to pause queue (${toQueue[0].timestamp.toFixed(3)}-${toQueue[toQueue.length - 1].timestamp + toQueue[toQueue.length - 1].buffer.duration.toFixed(3)})`);
|
|
253
292
|
}
|
|
254
293
|
};
|
|
255
294
|
const getNumberOfChunksAfterResuming = () => {
|
|
256
295
|
return audioChunksForAfterResuming.length;
|
|
257
296
|
};
|
|
258
297
|
return {
|
|
259
|
-
destroy: () => {
|
|
260
|
-
cleanupAudioQueue();
|
|
298
|
+
destroy: (audioContext) => {
|
|
299
|
+
cleanupAudioQueue(audioContext);
|
|
261
300
|
destroyed = true;
|
|
262
301
|
iterator.return().catch(() => {
|
|
263
302
|
return;
|
|
@@ -274,8 +313,20 @@ var makeAudioIterator = (startFromSecond, cache) => {
|
|
|
274
313
|
isDestroyed: () => {
|
|
275
314
|
return destroyed;
|
|
276
315
|
},
|
|
277
|
-
addQueuedAudioNode: (
|
|
278
|
-
|
|
316
|
+
addQueuedAudioNode: ({
|
|
317
|
+
node,
|
|
318
|
+
timestamp,
|
|
319
|
+
buffer,
|
|
320
|
+
scheduledTime,
|
|
321
|
+
playbackRate
|
|
322
|
+
}) => {
|
|
323
|
+
queuedAudioNodes.push({
|
|
324
|
+
node,
|
|
325
|
+
timestamp,
|
|
326
|
+
buffer,
|
|
327
|
+
scheduledTime,
|
|
328
|
+
playbackRate
|
|
329
|
+
});
|
|
279
330
|
},
|
|
280
331
|
removeQueuedAudioNode: (node) => {
|
|
281
332
|
const index = queuedAudioNodes.findIndex((n) => n.node === node);
|
|
@@ -321,6 +372,122 @@ var isAlreadyQueued = (time, queuedPeriod) => {
|
|
|
321
372
|
return time >= queuedPeriod.from && time < queuedPeriod.until;
|
|
322
373
|
};
|
|
323
374
|
|
|
375
|
+
// src/make-iterator-with-priming.ts
|
|
376
|
+
var AUDIO_PRIMING_SECONDS = 0.5;
|
|
377
|
+
var PREDECODE_AHEAD_SECONDS = 8;
|
|
378
|
+
function makePredecodingIterator(inner) {
|
|
379
|
+
const buffer = [];
|
|
380
|
+
let consumerEndTime = 0;
|
|
381
|
+
let innerDone = false;
|
|
382
|
+
let returned = false;
|
|
383
|
+
let fetching = false;
|
|
384
|
+
let waiter = null;
|
|
385
|
+
const prefetch = () => {
|
|
386
|
+
if (fetching || returned || innerDone) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const lastBuffered = buffer.length > 0 ? buffer[buffer.length - 1] : null;
|
|
390
|
+
const bufferedEndTime = lastBuffered ? lastBuffered.timestamp + lastBuffered.duration : consumerEndTime;
|
|
391
|
+
if (bufferedEndTime >= consumerEndTime + PREDECODE_AHEAD_SECONDS) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
fetching = true;
|
|
395
|
+
inner.next().then((result) => {
|
|
396
|
+
fetching = false;
|
|
397
|
+
if (returned) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (result.done) {
|
|
401
|
+
innerDone = true;
|
|
402
|
+
if (waiter) {
|
|
403
|
+
const w = waiter;
|
|
404
|
+
waiter = null;
|
|
405
|
+
w({ value: undefined, done: true });
|
|
406
|
+
}
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (waiter) {
|
|
410
|
+
const w = waiter;
|
|
411
|
+
waiter = null;
|
|
412
|
+
const buf = result.value;
|
|
413
|
+
consumerEndTime = buf.timestamp + buf.duration;
|
|
414
|
+
w({ value: buf, done: false });
|
|
415
|
+
prefetch();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
buffer.push(result.value);
|
|
419
|
+
prefetch();
|
|
420
|
+
}, () => {
|
|
421
|
+
fetching = false;
|
|
422
|
+
innerDone = true;
|
|
423
|
+
if (waiter) {
|
|
424
|
+
const w = waiter;
|
|
425
|
+
waiter = null;
|
|
426
|
+
w({ value: undefined, done: true });
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
prefetch();
|
|
431
|
+
const _return = () => {
|
|
432
|
+
returned = true;
|
|
433
|
+
buffer.length = 0;
|
|
434
|
+
if (waiter) {
|
|
435
|
+
const w = waiter;
|
|
436
|
+
waiter = null;
|
|
437
|
+
w({ value: undefined, done: true });
|
|
438
|
+
}
|
|
439
|
+
inner.return(undefined);
|
|
440
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
441
|
+
};
|
|
442
|
+
const iterator = {
|
|
443
|
+
next() {
|
|
444
|
+
if (buffer.length > 0) {
|
|
445
|
+
const buf = buffer.shift();
|
|
446
|
+
consumerEndTime = buf.timestamp + buf.duration;
|
|
447
|
+
prefetch();
|
|
448
|
+
return Promise.resolve({ value: buf, done: false });
|
|
449
|
+
}
|
|
450
|
+
if (innerDone) {
|
|
451
|
+
return Promise.resolve({
|
|
452
|
+
value: undefined,
|
|
453
|
+
done: true
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
return new Promise((resolve) => {
|
|
457
|
+
waiter = resolve;
|
|
458
|
+
prefetch();
|
|
459
|
+
});
|
|
460
|
+
},
|
|
461
|
+
return: _return,
|
|
462
|
+
throw(e) {
|
|
463
|
+
returned = true;
|
|
464
|
+
buffer.length = 0;
|
|
465
|
+
return inner.throw(e);
|
|
466
|
+
},
|
|
467
|
+
[Symbol.asyncIterator]() {
|
|
468
|
+
return iterator;
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
return iterator;
|
|
472
|
+
}
|
|
473
|
+
async function* makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp) {
|
|
474
|
+
const primingStart = Math.max(0, timeToSeek - AUDIO_PRIMING_SECONDS);
|
|
475
|
+
const iterator = audioSink.buffers(primingStart, maximumTimestamp);
|
|
476
|
+
for await (const buffer of iterator) {
|
|
477
|
+
if (buffer.timestamp + buffer.duration <= timeToSeek) {
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
yield buffer;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
var makeIteratorWithPriming = ({
|
|
484
|
+
audioSink,
|
|
485
|
+
timeToSeek,
|
|
486
|
+
maximumTimestamp
|
|
487
|
+
}) => {
|
|
488
|
+
return makePredecodingIterator(makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp));
|
|
489
|
+
};
|
|
490
|
+
|
|
324
491
|
// src/prewarm-iterator-for-looping.ts
|
|
325
492
|
var makePrewarmedVideoIteratorCache = (videoSink) => {
|
|
326
493
|
const prewarmedVideoIterators = new Map;
|
|
@@ -350,20 +517,30 @@ var makePrewarmedVideoIteratorCache = (videoSink) => {
|
|
|
350
517
|
destroy
|
|
351
518
|
};
|
|
352
519
|
};
|
|
520
|
+
var makeKey = (timeToSeek, maximumTimestamp) => {
|
|
521
|
+
return `${timeToSeek}-${maximumTimestamp}`;
|
|
522
|
+
};
|
|
353
523
|
var makePrewarmedAudioIteratorCache = (audioSink) => {
|
|
354
524
|
const prewarmedAudioIterators = new Map;
|
|
355
|
-
const prewarmIteratorForLooping = ({
|
|
356
|
-
|
|
357
|
-
|
|
525
|
+
const prewarmIteratorForLooping = ({
|
|
526
|
+
timeToSeek,
|
|
527
|
+
maximumTimestamp
|
|
528
|
+
}) => {
|
|
529
|
+
if (!prewarmedAudioIterators.has(makeKey(timeToSeek, maximumTimestamp))) {
|
|
530
|
+
prewarmedAudioIterators.set(makeKey(timeToSeek, maximumTimestamp), makeIteratorWithPriming({ audioSink, timeToSeek, maximumTimestamp }));
|
|
358
531
|
}
|
|
359
532
|
};
|
|
360
|
-
const makeIteratorOrUsePrewarmed = (timeToSeek) => {
|
|
361
|
-
const prewarmedIterator = prewarmedAudioIterators.get(timeToSeek);
|
|
533
|
+
const makeIteratorOrUsePrewarmed = (timeToSeek, maximumTimestamp) => {
|
|
534
|
+
const prewarmedIterator = prewarmedAudioIterators.get(makeKey(timeToSeek, maximumTimestamp));
|
|
362
535
|
if (prewarmedIterator) {
|
|
363
|
-
prewarmedAudioIterators.delete(timeToSeek);
|
|
536
|
+
prewarmedAudioIterators.delete(makeKey(timeToSeek, maximumTimestamp));
|
|
364
537
|
return prewarmedIterator;
|
|
365
538
|
}
|
|
366
|
-
const iterator =
|
|
539
|
+
const iterator = makeIteratorWithPriming({
|
|
540
|
+
audioSink,
|
|
541
|
+
timeToSeek,
|
|
542
|
+
maximumTimestamp
|
|
543
|
+
});
|
|
367
544
|
return iterator;
|
|
368
545
|
};
|
|
369
546
|
const destroy = () => {
|
|
@@ -405,11 +582,14 @@ var audioIteratorManager = ({
|
|
|
405
582
|
mediaTimestamp,
|
|
406
583
|
playbackRate,
|
|
407
584
|
scheduleAudioNode,
|
|
408
|
-
|
|
585
|
+
debugAudioScheduling
|
|
409
586
|
}) => {
|
|
410
587
|
if (!audioBufferIterator) {
|
|
411
588
|
throw new Error("Audio buffer iterator not found");
|
|
412
589
|
}
|
|
590
|
+
if (sharedAudioContext.state !== "running") {
|
|
591
|
+
throw new Error("Tried to schedule node while audio context is not running");
|
|
592
|
+
}
|
|
413
593
|
if (muted) {
|
|
414
594
|
return;
|
|
415
595
|
}
|
|
@@ -417,42 +597,88 @@ var audioIteratorManager = ({
|
|
|
417
597
|
node.buffer = buffer;
|
|
418
598
|
node.playbackRate.value = playbackRate;
|
|
419
599
|
node.connect(gainNode);
|
|
420
|
-
scheduleAudioNode(node, mediaTimestamp
|
|
600
|
+
const started = scheduleAudioNode(node, mediaTimestamp);
|
|
601
|
+
if (started.type === "not-started") {
|
|
602
|
+
if (debugAudioScheduling) {
|
|
603
|
+
Internals4.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, "not started, disconnected: %s %s", mediaTimestamp.toFixed(3), buffer.duration.toFixed(3));
|
|
604
|
+
}
|
|
605
|
+
node.disconnect();
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
421
608
|
const iterator = audioBufferIterator;
|
|
422
|
-
iterator.addQueuedAudioNode(
|
|
609
|
+
iterator.addQueuedAudioNode({
|
|
610
|
+
node,
|
|
611
|
+
timestamp: mediaTimestamp,
|
|
612
|
+
buffer,
|
|
613
|
+
scheduledTime: started.scheduledTime,
|
|
614
|
+
playbackRate
|
|
615
|
+
});
|
|
423
616
|
node.onended = () => {
|
|
424
617
|
setTimeout(() => {
|
|
425
618
|
iterator.removeQueuedAudioNode(node);
|
|
426
619
|
}, 30);
|
|
427
620
|
};
|
|
428
621
|
};
|
|
622
|
+
const resumeScheduledAudioChunks = ({
|
|
623
|
+
playbackRate,
|
|
624
|
+
scheduleAudioNode,
|
|
625
|
+
debugAudioScheduling
|
|
626
|
+
}) => {
|
|
627
|
+
if (muted) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
if (!audioBufferIterator) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
for (const chunk of audioBufferIterator.getAndClearAudioChunksForAfterResuming()) {
|
|
634
|
+
scheduleAudioChunk({
|
|
635
|
+
buffer: chunk.buffer,
|
|
636
|
+
mediaTimestamp: chunk.timestamp,
|
|
637
|
+
playbackRate,
|
|
638
|
+
scheduleAudioNode,
|
|
639
|
+
debugAudioScheduling
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
};
|
|
429
643
|
const onAudioChunk = ({
|
|
430
644
|
getIsPlaying,
|
|
431
645
|
buffer,
|
|
432
646
|
playbackRate,
|
|
433
|
-
scheduleAudioNode
|
|
647
|
+
scheduleAudioNode,
|
|
648
|
+
debugAudioScheduling
|
|
434
649
|
}) => {
|
|
435
650
|
if (muted) {
|
|
436
651
|
return;
|
|
437
652
|
}
|
|
653
|
+
const startTime = getStartTime();
|
|
438
654
|
const endTime = getEndTime();
|
|
655
|
+
if (buffer.timestamp + buffer.duration <= startTime) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
439
658
|
if (buffer.timestamp >= endTime) {
|
|
440
659
|
return;
|
|
441
660
|
}
|
|
442
|
-
|
|
443
|
-
|
|
661
|
+
if (getIsPlaying() && sharedAudioContext.state === "running" && (sharedAudioContext.getOutputTimestamp().contextTime ?? 0) > 0) {
|
|
662
|
+
resumeScheduledAudioChunks({
|
|
663
|
+
playbackRate,
|
|
664
|
+
scheduleAudioNode,
|
|
665
|
+
debugAudioScheduling
|
|
666
|
+
});
|
|
444
667
|
scheduleAudioChunk({
|
|
445
668
|
buffer: buffer.buffer,
|
|
446
669
|
mediaTimestamp: buffer.timestamp,
|
|
447
670
|
playbackRate,
|
|
448
671
|
scheduleAudioNode,
|
|
449
|
-
|
|
672
|
+
debugAudioScheduling
|
|
450
673
|
});
|
|
451
674
|
} else {
|
|
452
675
|
if (!audioBufferIterator) {
|
|
453
676
|
throw new Error("Audio buffer iterator not found");
|
|
454
677
|
}
|
|
455
|
-
|
|
678
|
+
if (debugAudioScheduling) {
|
|
679
|
+
Internals4.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, "not ready, added to queue: %s %s", buffer.timestamp.toFixed(3), buffer.duration.toFixed(3));
|
|
680
|
+
}
|
|
681
|
+
audioBufferIterator.addChunkForAfterResuming(buffer.buffer, buffer.timestamp);
|
|
456
682
|
}
|
|
457
683
|
drawDebugOverlay();
|
|
458
684
|
};
|
|
@@ -461,17 +687,18 @@ var audioIteratorManager = ({
|
|
|
461
687
|
playbackRate,
|
|
462
688
|
startFromSecond,
|
|
463
689
|
getIsPlaying,
|
|
464
|
-
scheduleAudioNode
|
|
690
|
+
scheduleAudioNode,
|
|
691
|
+
debugAudioScheduling
|
|
465
692
|
}) => {
|
|
466
693
|
let __stack = [];
|
|
467
694
|
try {
|
|
468
695
|
if (muted) {
|
|
469
696
|
return;
|
|
470
697
|
}
|
|
471
|
-
audioBufferIterator?.destroy();
|
|
698
|
+
audioBufferIterator?.destroy(sharedAudioContext);
|
|
472
699
|
const delayHandle = __using(__stack, delayPlaybackHandleIfNotPremounting(), 0);
|
|
473
700
|
currentDelayHandle = delayHandle;
|
|
474
|
-
const iterator = makeAudioIterator(startFromSecond, prewarmedAudioIteratorCache);
|
|
701
|
+
const iterator = makeAudioIterator(startFromSecond, getEndTime(), prewarmedAudioIteratorCache, debugAudioScheduling);
|
|
475
702
|
audioIteratorsCreated++;
|
|
476
703
|
audioBufferIterator = iterator;
|
|
477
704
|
try {
|
|
@@ -490,7 +717,8 @@ var audioIteratorManager = ({
|
|
|
490
717
|
getIsPlaying,
|
|
491
718
|
buffer: result.value,
|
|
492
719
|
playbackRate,
|
|
493
|
-
scheduleAudioNode
|
|
720
|
+
scheduleAudioNode,
|
|
721
|
+
debugAudioScheduling
|
|
494
722
|
});
|
|
495
723
|
}
|
|
496
724
|
await iterator.bufferAsFarAsPossible((buffer) => {
|
|
@@ -499,7 +727,8 @@ var audioIteratorManager = ({
|
|
|
499
727
|
getIsPlaying,
|
|
500
728
|
buffer,
|
|
501
729
|
playbackRate,
|
|
502
|
-
scheduleAudioNode
|
|
730
|
+
scheduleAudioNode,
|
|
731
|
+
debugAudioScheduling
|
|
503
732
|
});
|
|
504
733
|
}
|
|
505
734
|
}, Math.min(startFromSecond + MAX_BUFFER_AHEAD_SECONDS, getEndTime()));
|
|
@@ -526,7 +755,8 @@ var audioIteratorManager = ({
|
|
|
526
755
|
nonce,
|
|
527
756
|
playbackRate,
|
|
528
757
|
getIsPlaying,
|
|
529
|
-
scheduleAudioNode
|
|
758
|
+
scheduleAudioNode,
|
|
759
|
+
debugAudioScheduling
|
|
530
760
|
}) => {
|
|
531
761
|
if (muted) {
|
|
532
762
|
return;
|
|
@@ -534,7 +764,8 @@ var audioIteratorManager = ({
|
|
|
534
764
|
if (getIsLooping()) {
|
|
535
765
|
if (getEndTime() - newTime < 1) {
|
|
536
766
|
prewarmedAudioIteratorCache.prewarmIteratorForLooping({
|
|
537
|
-
timeToSeek: getStartTime()
|
|
767
|
+
timeToSeek: getStartTime(),
|
|
768
|
+
maximumTimestamp: getEndTime()
|
|
538
769
|
});
|
|
539
770
|
}
|
|
540
771
|
}
|
|
@@ -544,7 +775,8 @@ var audioIteratorManager = ({
|
|
|
544
775
|
playbackRate,
|
|
545
776
|
startFromSecond: newTime,
|
|
546
777
|
getIsPlaying,
|
|
547
|
-
scheduleAudioNode
|
|
778
|
+
scheduleAudioNode,
|
|
779
|
+
debugAudioScheduling
|
|
548
780
|
});
|
|
549
781
|
return;
|
|
550
782
|
}
|
|
@@ -557,7 +789,8 @@ var audioIteratorManager = ({
|
|
|
557
789
|
getIsPlaying,
|
|
558
790
|
buffer,
|
|
559
791
|
playbackRate,
|
|
560
|
-
scheduleAudioNode
|
|
792
|
+
scheduleAudioNode,
|
|
793
|
+
debugAudioScheduling
|
|
561
794
|
});
|
|
562
795
|
}
|
|
563
796
|
});
|
|
@@ -573,7 +806,8 @@ var audioIteratorManager = ({
|
|
|
573
806
|
playbackRate,
|
|
574
807
|
startFromSecond: newTime,
|
|
575
808
|
getIsPlaying,
|
|
576
|
-
scheduleAudioNode
|
|
809
|
+
scheduleAudioNode,
|
|
810
|
+
debugAudioScheduling
|
|
577
811
|
});
|
|
578
812
|
return;
|
|
579
813
|
}
|
|
@@ -585,31 +819,12 @@ var audioIteratorManager = ({
|
|
|
585
819
|
getIsPlaying,
|
|
586
820
|
buffer,
|
|
587
821
|
playbackRate,
|
|
588
|
-
scheduleAudioNode
|
|
822
|
+
scheduleAudioNode,
|
|
823
|
+
debugAudioScheduling
|
|
589
824
|
});
|
|
590
825
|
}
|
|
591
826
|
}, Math.min(newTime + MAX_BUFFER_AHEAD_SECONDS, getEndTime()));
|
|
592
827
|
};
|
|
593
|
-
const resumeScheduledAudioChunks = ({
|
|
594
|
-
playbackRate,
|
|
595
|
-
scheduleAudioNode
|
|
596
|
-
}) => {
|
|
597
|
-
if (muted) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
if (!audioBufferIterator) {
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
for (const chunk of audioBufferIterator.getAndClearAudioChunksForAfterResuming()) {
|
|
604
|
-
scheduleAudioChunk({
|
|
605
|
-
buffer: chunk.buffer,
|
|
606
|
-
mediaTimestamp: chunk.timestamp,
|
|
607
|
-
playbackRate,
|
|
608
|
-
scheduleAudioNode,
|
|
609
|
-
maxDuration: chunk.maxDuration
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
828
|
return {
|
|
614
829
|
startAudioIterator,
|
|
615
830
|
resumeScheduledAudioChunks,
|
|
@@ -617,7 +832,7 @@ var audioIteratorManager = ({
|
|
|
617
832
|
getAudioBufferIterator: () => audioBufferIterator,
|
|
618
833
|
destroyIterator: () => {
|
|
619
834
|
prewarmedAudioIteratorCache.destroy();
|
|
620
|
-
audioBufferIterator?.destroy();
|
|
835
|
+
audioBufferIterator?.destroy(sharedAudioContext);
|
|
621
836
|
audioBufferIterator = null;
|
|
622
837
|
if (currentDelayHandle) {
|
|
623
838
|
currentDelayHandle.unblock();
|
|
@@ -638,16 +853,6 @@ var audioIteratorManager = ({
|
|
|
638
853
|
};
|
|
639
854
|
};
|
|
640
855
|
|
|
641
|
-
// src/calculate-playbacktime.ts
|
|
642
|
-
var calculatePlaybackTime = ({
|
|
643
|
-
audioSyncAnchor,
|
|
644
|
-
currentTime,
|
|
645
|
-
playbackRate
|
|
646
|
-
}) => {
|
|
647
|
-
const timeSinceAnchor = currentTime - audioSyncAnchor;
|
|
648
|
-
return timeSinceAnchor * playbackRate;
|
|
649
|
-
};
|
|
650
|
-
|
|
651
856
|
// src/debug-overlay/preview-overlay.ts
|
|
652
857
|
var drawPreviewOverlay = ({
|
|
653
858
|
context,
|
|
@@ -659,18 +864,19 @@ var drawPreviewOverlay = ({
|
|
|
659
864
|
videoIteratorManager,
|
|
660
865
|
playbackRate
|
|
661
866
|
}) => {
|
|
867
|
+
const anchorValue = audioSyncAnchor?.value ?? 0;
|
|
662
868
|
const lines = [
|
|
663
869
|
"Debug overlay",
|
|
664
870
|
`Video iterators created: ${videoIteratorManager?.getVideoIteratorsCreated()}`,
|
|
665
871
|
`Audio iterators created: ${audioIteratorManager2?.getAudioIteratorsCreated()}`,
|
|
666
872
|
`Frames rendered: ${videoIteratorManager?.getFramesRendered()}`,
|
|
667
873
|
`Audio context state: ${audioContextState}`,
|
|
668
|
-
audioTime ? `Audio time: ${((audioTime -
|
|
874
|
+
audioTime ? `Audio time: ${((audioTime - anchorValue) * playbackRate).toFixed(3)}s` : null
|
|
669
875
|
].filter(Boolean);
|
|
670
876
|
if (audioIteratorManager2) {
|
|
671
877
|
const queuedPeriod = audioIteratorManager2.getAudioBufferIterator()?.getQueuedPeriod();
|
|
672
878
|
if (queuedPeriod) {
|
|
673
|
-
const aheadText = audioTime ? ` (${(queuedPeriod.until - (audioTime -
|
|
879
|
+
const aheadText = audioTime ? ` (${(queuedPeriod.until - (audioTime - anchorValue) * playbackRate).toFixed(3)}s ahead)` : "";
|
|
674
880
|
lines.push(`Audio queued until ${queuedPeriod.until.toFixed(3)}s${aheadText}`);
|
|
675
881
|
}
|
|
676
882
|
lines.push(`Playing: ${playing}`);
|
|
@@ -720,7 +926,7 @@ var makeNonceManager = () => {
|
|
|
720
926
|
|
|
721
927
|
// src/video-iterator-manager.ts
|
|
722
928
|
import { CanvasSink } from "mediabunny";
|
|
723
|
-
import { Internals as
|
|
929
|
+
import { Internals as Internals5 } from "remotion";
|
|
724
930
|
|
|
725
931
|
// src/video/video-preview-iterator.ts
|
|
726
932
|
var createVideoIterator = async (timeToSeek, cache) => {
|
|
@@ -890,7 +1096,7 @@ var videoIteratorManager = ({
|
|
|
890
1096
|
if (callback) {
|
|
891
1097
|
callback(frame.canvas);
|
|
892
1098
|
}
|
|
893
|
-
|
|
1099
|
+
Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew frame ${frame.timestamp.toFixed(3)}s`);
|
|
894
1100
|
};
|
|
895
1101
|
const startVideoIterator = async (timeToSeek, nonce) => {
|
|
896
1102
|
let __stack = [];
|
|
@@ -975,7 +1181,7 @@ class MediaPlayer {
|
|
|
975
1181
|
sharedAudioContext;
|
|
976
1182
|
audioIteratorManager = null;
|
|
977
1183
|
videoIteratorManager = null;
|
|
978
|
-
|
|
1184
|
+
sequenceOffset;
|
|
979
1185
|
playing = false;
|
|
980
1186
|
loop = false;
|
|
981
1187
|
fps;
|
|
@@ -984,6 +1190,7 @@ class MediaPlayer {
|
|
|
984
1190
|
durationInFrames;
|
|
985
1191
|
totalDuration;
|
|
986
1192
|
debugOverlay = false;
|
|
1193
|
+
debugAudioScheduling = false;
|
|
987
1194
|
nonceManager;
|
|
988
1195
|
onVideoFrameCallback = null;
|
|
989
1196
|
initializationPromise = null;
|
|
@@ -1004,12 +1211,14 @@ class MediaPlayer {
|
|
|
1004
1211
|
audioStreamIndex,
|
|
1005
1212
|
fps,
|
|
1006
1213
|
debugOverlay,
|
|
1214
|
+
debugAudioScheduling,
|
|
1007
1215
|
bufferState,
|
|
1008
1216
|
isPremounting,
|
|
1009
1217
|
isPostmounting,
|
|
1010
1218
|
durationInFrames,
|
|
1011
1219
|
onVideoFrameCallback,
|
|
1012
|
-
playing
|
|
1220
|
+
playing,
|
|
1221
|
+
sequenceOffset
|
|
1013
1222
|
}) {
|
|
1014
1223
|
this.canvas = canvas ?? null;
|
|
1015
1224
|
this.src = src;
|
|
@@ -1023,6 +1232,7 @@ class MediaPlayer {
|
|
|
1023
1232
|
this.audioStreamIndex = audioStreamIndex ?? 0;
|
|
1024
1233
|
this.fps = fps;
|
|
1025
1234
|
this.debugOverlay = debugOverlay;
|
|
1235
|
+
this.debugAudioScheduling = debugAudioScheduling;
|
|
1026
1236
|
this.bufferState = bufferState;
|
|
1027
1237
|
this.isPremounting = isPremounting;
|
|
1028
1238
|
this.isPostmounting = isPostmounting;
|
|
@@ -1030,6 +1240,7 @@ class MediaPlayer {
|
|
|
1030
1240
|
this.nonceManager = makeNonceManager();
|
|
1031
1241
|
this.onVideoFrameCallback = onVideoFrameCallback;
|
|
1032
1242
|
this.playing = playing;
|
|
1243
|
+
this.sequenceOffset = sequenceOffset;
|
|
1033
1244
|
this.input = new Input({
|
|
1034
1245
|
source: new UrlSource(this.src),
|
|
1035
1246
|
formats: ALL_FORMATS
|
|
@@ -1093,7 +1304,7 @@ class MediaPlayer {
|
|
|
1093
1304
|
if (isNetworkError(err)) {
|
|
1094
1305
|
throw error;
|
|
1095
1306
|
}
|
|
1096
|
-
|
|
1307
|
+
Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
|
|
1097
1308
|
return { type: "unknown-container-format" };
|
|
1098
1309
|
}
|
|
1099
1310
|
const [durationInSeconds, videoTrack, audioTracks] = await Promise.all([
|
|
@@ -1134,7 +1345,6 @@ class MediaPlayer {
|
|
|
1134
1345
|
if (startTime === null) {
|
|
1135
1346
|
throw new Error(`should have asserted that the time is not null`);
|
|
1136
1347
|
}
|
|
1137
|
-
this.setAudioPlaybackTime(startTime);
|
|
1138
1348
|
if (audioTrack && this.sharedAudioContext) {
|
|
1139
1349
|
const canDecode = await audioTrack.canDecode();
|
|
1140
1350
|
if (!canDecode) {
|
|
@@ -1146,7 +1356,7 @@ class MediaPlayer {
|
|
|
1146
1356
|
this.audioIteratorManager = audioIteratorManager({
|
|
1147
1357
|
audioTrack,
|
|
1148
1358
|
delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
|
|
1149
|
-
sharedAudioContext: this.sharedAudioContext,
|
|
1359
|
+
sharedAudioContext: this.sharedAudioContext.audioContext,
|
|
1150
1360
|
getIsLooping: () => this.loop,
|
|
1151
1361
|
getEndTime: () => this.getEndTime(),
|
|
1152
1362
|
getStartTime: () => this.getStartTime(),
|
|
@@ -1162,7 +1372,8 @@ class MediaPlayer {
|
|
|
1162
1372
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1163
1373
|
startFromSecond: startTime,
|
|
1164
1374
|
getIsPlaying: () => this.playing,
|
|
1165
|
-
scheduleAudioNode: this.scheduleAudioNode
|
|
1375
|
+
scheduleAudioNode: this.scheduleAudioNode,
|
|
1376
|
+
debugAudioScheduling: this.debugAudioScheduling
|
|
1166
1377
|
}) : Promise.resolve(),
|
|
1167
1378
|
this.videoIteratorManager ? this.videoIteratorManager.startVideoIterator(startTime, nonce) : Promise.resolve()
|
|
1168
1379
|
]);
|
|
@@ -1170,16 +1381,16 @@ class MediaPlayer {
|
|
|
1170
1381
|
if (this.isDisposalError()) {
|
|
1171
1382
|
return { type: "disposed" };
|
|
1172
1383
|
}
|
|
1173
|
-
|
|
1384
|
+
Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start audio and video iterators", error);
|
|
1174
1385
|
}
|
|
1175
1386
|
return { type: "success", durationInSeconds };
|
|
1176
1387
|
} catch (error) {
|
|
1177
1388
|
const err = error;
|
|
1178
1389
|
if (isNetworkError(err)) {
|
|
1179
|
-
|
|
1390
|
+
Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
|
|
1180
1391
|
return { type: "network-error" };
|
|
1181
1392
|
}
|
|
1182
|
-
|
|
1393
|
+
Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to initialize", error);
|
|
1183
1394
|
throw error;
|
|
1184
1395
|
}
|
|
1185
1396
|
} catch (_catch) {
|
|
@@ -1205,46 +1416,44 @@ class MediaPlayer {
|
|
|
1205
1416
|
if (nonce.isStale()) {
|
|
1206
1417
|
return;
|
|
1207
1418
|
}
|
|
1208
|
-
const shouldSeekAudio = this.audioIteratorManager && this.sharedAudioContext
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
throw new Error(`should have asserted that the time is not null`);
|
|
1419
|
+
const shouldSeekAudio = this.audioIteratorManager && this.getAudioPlaybackTime(this.sharedAudioContext?.audioContext.currentTime ?? 0) !== newTime;
|
|
1420
|
+
try {
|
|
1421
|
+
await Promise.all([
|
|
1422
|
+
this.videoIteratorManager?.seek({
|
|
1423
|
+
newTime,
|
|
1424
|
+
nonce
|
|
1425
|
+
}),
|
|
1426
|
+
shouldSeekAudio ? this.audioIteratorManager?.seek({
|
|
1427
|
+
newTime,
|
|
1428
|
+
nonce,
|
|
1429
|
+
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1430
|
+
getIsPlaying: () => this.playing,
|
|
1431
|
+
scheduleAudioNode: this.scheduleAudioNode,
|
|
1432
|
+
debugAudioScheduling: this.debugAudioScheduling
|
|
1433
|
+
}) : null
|
|
1434
|
+
]);
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
if (this.isDisposalError()) {
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1439
|
+
throw error;
|
|
1230
1440
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1441
|
+
}
|
|
1442
|
+
playAudio() {
|
|
1443
|
+
if (this.audioIteratorManager && this.sharedAudioContext?.audioContext.state === "running" && (this.sharedAudioContext?.audioContext?.getOutputTimestamp().contextTime ?? 0) > 0) {
|
|
1233
1444
|
this.audioIteratorManager.resumeScheduledAudioChunks({
|
|
1234
1445
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1235
|
-
scheduleAudioNode: this.scheduleAudioNode
|
|
1446
|
+
scheduleAudioNode: this.scheduleAudioNode,
|
|
1447
|
+
debugAudioScheduling: this.debugAudioScheduling
|
|
1236
1448
|
});
|
|
1237
1449
|
}
|
|
1238
|
-
if (this.sharedAudioContext && this.sharedAudioContext.state === "suspended") {
|
|
1239
|
-
await this.sharedAudioContext.resume();
|
|
1240
|
-
}
|
|
1241
1450
|
}
|
|
1242
|
-
|
|
1451
|
+
play() {
|
|
1452
|
+
this.playAudio();
|
|
1243
1453
|
if (this.playing) {
|
|
1244
1454
|
return;
|
|
1245
1455
|
}
|
|
1246
1456
|
this.playing = true;
|
|
1247
|
-
await this.playAudio(time);
|
|
1248
1457
|
this.drawDebugOverlay();
|
|
1249
1458
|
}
|
|
1250
1459
|
delayPlaybackHandleIfNotPremounting = () => {
|
|
@@ -1299,7 +1508,6 @@ class MediaPlayer {
|
|
|
1299
1508
|
const newMediaTime = this.getTrimmedTime(unloopedTimeInSeconds);
|
|
1300
1509
|
this.audioIteratorManager?.destroyIterator();
|
|
1301
1510
|
if (newMediaTime !== null) {
|
|
1302
|
-
this.setAudioPlaybackTime(newMediaTime);
|
|
1303
1511
|
if (!this.playing && this.videoIteratorManager) {
|
|
1304
1512
|
await this.seekToWithQueue(newMediaTime);
|
|
1305
1513
|
}
|
|
@@ -1320,39 +1528,43 @@ class MediaPlayer {
|
|
|
1320
1528
|
setDebugOverlay(debugOverlay) {
|
|
1321
1529
|
this.debugOverlay = debugOverlay;
|
|
1322
1530
|
}
|
|
1323
|
-
|
|
1531
|
+
setDebugAudioScheduling(debugAudioScheduling) {
|
|
1532
|
+
this.debugAudioScheduling = debugAudioScheduling;
|
|
1533
|
+
}
|
|
1534
|
+
rescheduleAudioChunks() {
|
|
1324
1535
|
if (!this.audioIteratorManager) {
|
|
1325
1536
|
return;
|
|
1326
1537
|
}
|
|
1327
1538
|
if (!this.sharedAudioContext) {
|
|
1328
1539
|
return;
|
|
1329
1540
|
}
|
|
1330
|
-
this.setAudioPlaybackTime(mediaTimeBeforeChange);
|
|
1331
1541
|
const iterator = this.audioIteratorManager.getAudioBufferIterator();
|
|
1332
1542
|
if (!iterator) {
|
|
1333
1543
|
return;
|
|
1334
1544
|
}
|
|
1335
1545
|
iterator.moveQueuedChunksToPauseQueue();
|
|
1336
|
-
if (this.playing) {
|
|
1546
|
+
if (this.playing && this.sharedAudioContext.audioContext.state === "running" && (this.sharedAudioContext.audioContext?.getOutputTimestamp().contextTime ?? 0) > 0) {
|
|
1337
1547
|
this.audioIteratorManager.resumeScheduledAudioChunks({
|
|
1338
1548
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1339
|
-
scheduleAudioNode: this.scheduleAudioNode
|
|
1549
|
+
scheduleAudioNode: this.scheduleAudioNode,
|
|
1550
|
+
debugAudioScheduling: this.debugAudioScheduling
|
|
1340
1551
|
});
|
|
1341
1552
|
}
|
|
1342
1553
|
}
|
|
1343
1554
|
async setPlaybackRate(rate, unloopedTimeInSeconds) {
|
|
1344
1555
|
const previousRate = this.playbackRate;
|
|
1345
|
-
const mediaTime = this.sharedAudioContext ? this.getAudioPlaybackTime() : 0;
|
|
1346
|
-
this.playbackRate = rate;
|
|
1347
|
-
this.updateAudioTimeAfterPlaybackRateChange(mediaTime);
|
|
1348
1556
|
if (previousRate !== rate) {
|
|
1557
|
+
this.playbackRate = rate;
|
|
1558
|
+
this.rescheduleAudioChunks();
|
|
1349
1559
|
await this.seekTo(unloopedTimeInSeconds);
|
|
1350
1560
|
}
|
|
1351
1561
|
}
|
|
1352
1562
|
setGlobalPlaybackRate(rate) {
|
|
1353
|
-
const
|
|
1354
|
-
|
|
1355
|
-
|
|
1563
|
+
const previousRate = this.globalPlaybackRate;
|
|
1564
|
+
if (previousRate !== rate) {
|
|
1565
|
+
this.globalPlaybackRate = rate;
|
|
1566
|
+
this.rescheduleAudioChunks();
|
|
1567
|
+
}
|
|
1356
1568
|
}
|
|
1357
1569
|
setFps(fps) {
|
|
1358
1570
|
this.fps = fps;
|
|
@@ -1366,6 +1578,9 @@ class MediaPlayer {
|
|
|
1366
1578
|
setLoop(loop) {
|
|
1367
1579
|
this.loop = loop;
|
|
1368
1580
|
}
|
|
1581
|
+
setSequenceOffset(offset) {
|
|
1582
|
+
this.sequenceOffset = offset;
|
|
1583
|
+
}
|
|
1369
1584
|
setDurationInFrames(durationInFrames) {
|
|
1370
1585
|
this.durationInFrames = durationInFrames;
|
|
1371
1586
|
}
|
|
@@ -1380,41 +1595,40 @@ class MediaPlayer {
|
|
|
1380
1595
|
this.audioIteratorManager?.destroyIterator();
|
|
1381
1596
|
this.input.dispose();
|
|
1382
1597
|
}
|
|
1383
|
-
scheduleAudioNode = (node, mediaTimestamp
|
|
1384
|
-
const currentTime = this.getAudioPlaybackTime();
|
|
1385
|
-
const delayWithoutPlaybackRate = mediaTimestamp - currentTime;
|
|
1386
|
-
const delay = delayWithoutPlaybackRate / (this.playbackRate * this.globalPlaybackRate);
|
|
1598
|
+
scheduleAudioNode = (node, mediaTimestamp) => {
|
|
1387
1599
|
if (!this.sharedAudioContext) {
|
|
1388
1600
|
throw new Error("Shared audio context not found");
|
|
1389
1601
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1602
|
+
const { audioContext } = this.sharedAudioContext;
|
|
1603
|
+
const { currentTime } = audioContext;
|
|
1604
|
+
const globalTime = (currentTime - this.sharedAudioContext.audioSyncAnchor.value) * this.globalPlaybackRate;
|
|
1605
|
+
const timeInSeconds = globalTime - this.sequenceOffset;
|
|
1606
|
+
const localTime = this.getTrimmedTime(timeInSeconds);
|
|
1607
|
+
if (localTime === null) {
|
|
1608
|
+
throw new Error("hmm, should not render!");
|
|
1609
|
+
}
|
|
1610
|
+
const targetTime = (mediaTimestamp - localTime) / (this.playbackRate * this.globalPlaybackRate);
|
|
1611
|
+
return this.sharedAudioContext.scheduleAudioNode({
|
|
1612
|
+
node,
|
|
1613
|
+
mediaTimestamp,
|
|
1614
|
+
targetTime,
|
|
1615
|
+
currentTime,
|
|
1616
|
+
sequenceEndTime: this.getEndTime(),
|
|
1617
|
+
sequenceStartTime: this.getStartTime(),
|
|
1618
|
+
debugAudioScheduling: this.debugAudioScheduling
|
|
1619
|
+
});
|
|
1396
1620
|
};
|
|
1397
|
-
getAudioPlaybackTime() {
|
|
1621
|
+
getAudioPlaybackTime(currentTime) {
|
|
1398
1622
|
if (!this.sharedAudioContext) {
|
|
1399
1623
|
throw new Error("Shared audio context not found");
|
|
1400
1624
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
}
|
|
1407
|
-
setAudioPlaybackTime(time) {
|
|
1408
|
-
if (!this.sharedAudioContext) {
|
|
1409
|
-
return;
|
|
1625
|
+
const globalTime = (currentTime - this.sharedAudioContext.audioSyncAnchor.value) * this.globalPlaybackRate;
|
|
1626
|
+
const localTime = globalTime - this.sequenceOffset;
|
|
1627
|
+
const trimmedTime = this.getTrimmedTime(localTime);
|
|
1628
|
+
if (trimmedTime !== null) {
|
|
1629
|
+
return trimmedTime;
|
|
1410
1630
|
}
|
|
1411
|
-
|
|
1412
|
-
const newAnchor = this.sharedAudioContext.currentTime - time / playbackRate;
|
|
1413
|
-
const shift = Math.abs(newAnchor - this.audioSyncAnchor) * playbackRate;
|
|
1414
|
-
if (shift < 0.05) {
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
this.audioSyncAnchor = newAnchor;
|
|
1631
|
+
return localTime * this.playbackRate + (this.trimBefore ?? 0) / this.fps;
|
|
1418
1632
|
}
|
|
1419
1633
|
setVideoFrameCallback(callback) {
|
|
1420
1634
|
this.onVideoFrameCallback = callback;
|
|
@@ -1425,9 +1639,9 @@ class MediaPlayer {
|
|
|
1425
1639
|
if (this.context && this.canvas) {
|
|
1426
1640
|
drawPreviewOverlay({
|
|
1427
1641
|
context: this.context,
|
|
1428
|
-
audioTime: this.sharedAudioContext?.currentTime ?? null,
|
|
1429
|
-
audioContextState: this.sharedAudioContext?.state ?? null,
|
|
1430
|
-
audioSyncAnchor: this.audioSyncAnchor,
|
|
1642
|
+
audioTime: this.sharedAudioContext?.audioContext.currentTime ?? null,
|
|
1643
|
+
audioContextState: this.sharedAudioContext?.audioContext.state ?? null,
|
|
1644
|
+
audioSyncAnchor: this.sharedAudioContext?.audioSyncAnchor ?? null,
|
|
1431
1645
|
audioIteratorManager: this.audioIteratorManager,
|
|
1432
1646
|
playing: this.playing,
|
|
1433
1647
|
videoIteratorManager: this.videoIteratorManager,
|
|
@@ -1460,7 +1674,7 @@ var callOnErrorAndResolve = ({
|
|
|
1460
1674
|
|
|
1461
1675
|
// src/show-in-timeline.ts
|
|
1462
1676
|
import { useMemo } from "react";
|
|
1463
|
-
import { Internals as
|
|
1677
|
+
import { Internals as Internals7, useVideoConfig } from "remotion";
|
|
1464
1678
|
var useLoopDisplay = ({
|
|
1465
1679
|
loop,
|
|
1466
1680
|
mediaDurationInSeconds,
|
|
@@ -1473,7 +1687,7 @@ var useLoopDisplay = ({
|
|
|
1473
1687
|
if (!loop || !mediaDurationInSeconds) {
|
|
1474
1688
|
return;
|
|
1475
1689
|
}
|
|
1476
|
-
const durationInFrames =
|
|
1690
|
+
const durationInFrames = Internals7.calculateMediaDuration({
|
|
1477
1691
|
mediaDurationInFrames: mediaDurationInSeconds * fps,
|
|
1478
1692
|
playbackRate,
|
|
1479
1693
|
trimAfter,
|
|
@@ -1497,9 +1711,177 @@ var useLoopDisplay = ({
|
|
|
1497
1711
|
return loopDisplay;
|
|
1498
1712
|
};
|
|
1499
1713
|
|
|
1714
|
+
// src/use-common-effects.ts
|
|
1715
|
+
import { useContext, useLayoutEffect } from "react";
|
|
1716
|
+
import { Internals as Internals8 } from "remotion";
|
|
1717
|
+
var useCommonEffects = ({
|
|
1718
|
+
mediaPlayerRef,
|
|
1719
|
+
mediaPlayerReady,
|
|
1720
|
+
currentTimeRef,
|
|
1721
|
+
playing,
|
|
1722
|
+
isPlayerBuffering,
|
|
1723
|
+
frame,
|
|
1724
|
+
trimBefore,
|
|
1725
|
+
trimAfter,
|
|
1726
|
+
effectiveMuted,
|
|
1727
|
+
userPreferredVolume,
|
|
1728
|
+
playbackRate,
|
|
1729
|
+
globalPlaybackRate,
|
|
1730
|
+
fps,
|
|
1731
|
+
sequenceOffset,
|
|
1732
|
+
loop,
|
|
1733
|
+
debugAudioScheduling,
|
|
1734
|
+
durationInFrames,
|
|
1735
|
+
isPremounting,
|
|
1736
|
+
isPostmounting,
|
|
1737
|
+
currentTime,
|
|
1738
|
+
logLevel,
|
|
1739
|
+
sharedAudioContext,
|
|
1740
|
+
label
|
|
1741
|
+
}) => {
|
|
1742
|
+
const absoluteTime = Internals8.useAbsoluteTimelinePosition();
|
|
1743
|
+
const { playing: playingWhilePremounting } = useContext(Internals8.PremountContext);
|
|
1744
|
+
useLayoutEffect(() => {
|
|
1745
|
+
if (sharedAudioContext?.audioContext && sharedAudioContext.audioSyncAnchor) {
|
|
1746
|
+
setGlobalTimeAnchor({
|
|
1747
|
+
audioContext: sharedAudioContext.audioContext,
|
|
1748
|
+
audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
|
|
1749
|
+
absoluteTimeInSeconds: absoluteTime / fps,
|
|
1750
|
+
globalPlaybackRate,
|
|
1751
|
+
debugAudioScheduling,
|
|
1752
|
+
logLevel
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
}, [
|
|
1756
|
+
absoluteTime,
|
|
1757
|
+
globalPlaybackRate,
|
|
1758
|
+
sharedAudioContext,
|
|
1759
|
+
fps,
|
|
1760
|
+
debugAudioScheduling,
|
|
1761
|
+
logLevel
|
|
1762
|
+
]);
|
|
1763
|
+
if (playingWhilePremounting) {
|
|
1764
|
+
mediaPlayerRef.current?.playAudio();
|
|
1765
|
+
}
|
|
1766
|
+
useLayoutEffect(() => {
|
|
1767
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1768
|
+
if (!mediaPlayer)
|
|
1769
|
+
return;
|
|
1770
|
+
if (playing && !isPlayerBuffering) {
|
|
1771
|
+
mediaPlayer.play();
|
|
1772
|
+
} else {
|
|
1773
|
+
mediaPlayer.pause();
|
|
1774
|
+
}
|
|
1775
|
+
}, [
|
|
1776
|
+
isPlayerBuffering,
|
|
1777
|
+
playing,
|
|
1778
|
+
logLevel,
|
|
1779
|
+
mediaPlayerReady,
|
|
1780
|
+
frame,
|
|
1781
|
+
mediaPlayerRef
|
|
1782
|
+
]);
|
|
1783
|
+
useLayoutEffect(() => {
|
|
1784
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1785
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
mediaPlayer.setTrimBefore(trimBefore, currentTimeRef.current);
|
|
1789
|
+
}, [trimBefore, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
|
|
1790
|
+
useLayoutEffect(() => {
|
|
1791
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1792
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
mediaPlayer.setTrimAfter(trimAfter, currentTimeRef.current);
|
|
1796
|
+
}, [trimAfter, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
|
|
1797
|
+
useLayoutEffect(() => {
|
|
1798
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1799
|
+
if (!mediaPlayer || !mediaPlayerReady)
|
|
1800
|
+
return;
|
|
1801
|
+
mediaPlayer.setMuted(effectiveMuted);
|
|
1802
|
+
}, [effectiveMuted, mediaPlayerReady, mediaPlayerRef]);
|
|
1803
|
+
useLayoutEffect(() => {
|
|
1804
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1805
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
mediaPlayer.setVolume(userPreferredVolume);
|
|
1809
|
+
}, [userPreferredVolume, mediaPlayerReady, mediaPlayerRef]);
|
|
1810
|
+
useLayoutEffect(() => {
|
|
1811
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1812
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
mediaPlayer.setPlaybackRate(playbackRate, currentTimeRef.current);
|
|
1816
|
+
}, [playbackRate, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
|
|
1817
|
+
useLayoutEffect(() => {
|
|
1818
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1819
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
mediaPlayer.setGlobalPlaybackRate(globalPlaybackRate);
|
|
1823
|
+
}, [globalPlaybackRate, mediaPlayerReady, mediaPlayerRef]);
|
|
1824
|
+
useLayoutEffect(() => {
|
|
1825
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1826
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
mediaPlayer.setLoop(loop);
|
|
1830
|
+
}, [loop, mediaPlayerReady, mediaPlayerRef]);
|
|
1831
|
+
useLayoutEffect(() => {
|
|
1832
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1833
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
mediaPlayer.setDurationInFrames(durationInFrames);
|
|
1837
|
+
}, [durationInFrames, mediaPlayerReady, mediaPlayerRef]);
|
|
1838
|
+
useLayoutEffect(() => {
|
|
1839
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1840
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
mediaPlayer.setIsPremounting(isPremounting);
|
|
1844
|
+
}, [isPremounting, mediaPlayerReady, mediaPlayerRef]);
|
|
1845
|
+
useLayoutEffect(() => {
|
|
1846
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1847
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
mediaPlayer.setIsPostmounting(isPostmounting);
|
|
1851
|
+
}, [isPostmounting, mediaPlayerReady, mediaPlayerRef]);
|
|
1852
|
+
useLayoutEffect(() => {
|
|
1853
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1854
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1857
|
+
mediaPlayer.setFps(fps);
|
|
1858
|
+
}, [fps, mediaPlayerReady, mediaPlayerRef]);
|
|
1859
|
+
useLayoutEffect(() => {
|
|
1860
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1861
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1862
|
+
return;
|
|
1863
|
+
}
|
|
1864
|
+
mediaPlayer.setSequenceOffset(sequenceOffset);
|
|
1865
|
+
}, [sequenceOffset, mediaPlayerReady, mediaPlayerRef]);
|
|
1866
|
+
useLayoutEffect(() => {
|
|
1867
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1868
|
+
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
mediaPlayer.setDebugAudioScheduling(debugAudioScheduling);
|
|
1872
|
+
}, [debugAudioScheduling, mediaPlayerReady, mediaPlayerRef]);
|
|
1873
|
+
useLayoutEffect(() => {
|
|
1874
|
+
const mediaPlayer = mediaPlayerRef.current;
|
|
1875
|
+
if (!mediaPlayer || !mediaPlayerReady)
|
|
1876
|
+
return;
|
|
1877
|
+
mediaPlayer.seekTo(currentTime).catch(() => {});
|
|
1878
|
+
Internals8.Log.trace({ logLevel, tag: "@remotion/media" }, `[${label}] Updating target time to ${currentTime.toFixed(3)}s`);
|
|
1879
|
+
}, [currentTime, logLevel, mediaPlayerReady, label, mediaPlayerRef]);
|
|
1880
|
+
};
|
|
1881
|
+
|
|
1500
1882
|
// src/use-media-in-timeline.ts
|
|
1501
|
-
import { useContext
|
|
1502
|
-
import { Internals as
|
|
1883
|
+
import { useContext as useContext2, useState, useEffect } from "react";
|
|
1884
|
+
import { Internals as Internals9, useCurrentFrame } from "remotion";
|
|
1503
1885
|
var useMediaInTimeline = ({
|
|
1504
1886
|
volume,
|
|
1505
1887
|
mediaVolume,
|
|
@@ -1516,9 +1898,9 @@ var useMediaInTimeline = ({
|
|
|
1516
1898
|
trimAfter,
|
|
1517
1899
|
controls
|
|
1518
1900
|
}) => {
|
|
1519
|
-
const parentSequence =
|
|
1520
|
-
const startsAt =
|
|
1521
|
-
const { registerSequence, unregisterSequence } =
|
|
1901
|
+
const parentSequence = useContext2(Internals9.SequenceContext);
|
|
1902
|
+
const startsAt = Internals9.useMediaStartsAt();
|
|
1903
|
+
const { registerSequence, unregisterSequence } = useContext2(Internals9.SequenceManager);
|
|
1522
1904
|
const [sequenceId] = useState(() => String(Math.random()));
|
|
1523
1905
|
const [mediaId] = useState(() => String(Math.random()));
|
|
1524
1906
|
const frame = useCurrentFrame();
|
|
@@ -1530,7 +1912,7 @@ var useMediaInTimeline = ({
|
|
|
1530
1912
|
rootId,
|
|
1531
1913
|
isStudio,
|
|
1532
1914
|
finalDisplayName
|
|
1533
|
-
} =
|
|
1915
|
+
} = Internals9.useBasicMediaInTimeline({
|
|
1534
1916
|
volume,
|
|
1535
1917
|
mediaVolume,
|
|
1536
1918
|
mediaType,
|
|
@@ -1560,7 +1942,7 @@ var useMediaInTimeline = ({
|
|
|
1560
1942
|
displayName: finalDisplayName,
|
|
1561
1943
|
rootId,
|
|
1562
1944
|
showInTimeline: true,
|
|
1563
|
-
nonce,
|
|
1945
|
+
nonce: nonce.get(),
|
|
1564
1946
|
loopDisplay,
|
|
1565
1947
|
stack,
|
|
1566
1948
|
from: 0,
|
|
@@ -1580,7 +1962,7 @@ var useMediaInTimeline = ({
|
|
|
1580
1962
|
rootId,
|
|
1581
1963
|
volume: volumes,
|
|
1582
1964
|
showInTimeline: true,
|
|
1583
|
-
nonce,
|
|
1965
|
+
nonce: nonce.get(),
|
|
1584
1966
|
startMediaFrom: 0 - startsAt + (trimBefore ?? 0),
|
|
1585
1967
|
doesVolumeChange,
|
|
1586
1968
|
loopDisplay: undefined,
|
|
@@ -1640,7 +2022,7 @@ var {
|
|
|
1640
2022
|
warnAboutTooHighVolume,
|
|
1641
2023
|
usePreload,
|
|
1642
2024
|
SequenceContext
|
|
1643
|
-
} =
|
|
2025
|
+
} = Internals10;
|
|
1644
2026
|
var AudioForPreviewAssertedShowing = ({
|
|
1645
2027
|
src,
|
|
1646
2028
|
playbackRate,
|
|
@@ -1658,6 +2040,7 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1658
2040
|
toneFrequency,
|
|
1659
2041
|
audioStreamIndex,
|
|
1660
2042
|
fallbackHtml5AudioProps,
|
|
2043
|
+
debugAudioScheduling,
|
|
1661
2044
|
onError,
|
|
1662
2045
|
controls
|
|
1663
2046
|
}) => {
|
|
@@ -1669,9 +2052,9 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1669
2052
|
const [mediaPlayerReady, setMediaPlayerReady] = useState2(false);
|
|
1670
2053
|
const [shouldFallbackToNativeAudio, setShouldFallbackToNativeAudio] = useState2(false);
|
|
1671
2054
|
const [playing] = Timeline.usePlayingState();
|
|
1672
|
-
const timelineContext =
|
|
2055
|
+
const timelineContext = Internals10.useTimelineContext();
|
|
1673
2056
|
const globalPlaybackRate = timelineContext.playbackRate;
|
|
1674
|
-
const sharedAudioContext =
|
|
2057
|
+
const sharedAudioContext = useContext3(SharedAudioContext);
|
|
1675
2058
|
const buffer = useBufferState();
|
|
1676
2059
|
const [mediaMuted] = useMediaMutedState();
|
|
1677
2060
|
const [mediaVolume] = useMediaVolumeState();
|
|
@@ -1693,9 +2076,10 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1693
2076
|
const currentTimeRef = useRef(currentTime);
|
|
1694
2077
|
currentTimeRef.current = currentTime;
|
|
1695
2078
|
const preloadedSrc = usePreload(src);
|
|
1696
|
-
const parentSequence =
|
|
2079
|
+
const parentSequence = useContext3(SequenceContext);
|
|
1697
2080
|
const isPremounting = Boolean(parentSequence?.premounting);
|
|
1698
2081
|
const isPostmounting = Boolean(parentSequence?.postmounting);
|
|
2082
|
+
const sequenceOffset = ((parentSequence?.cumulatedFrom ?? 0) + (parentSequence?.relativeFrom ?? 0)) / videoConfig.fps;
|
|
1699
2083
|
const loopDisplay = useLoopDisplay({
|
|
1700
2084
|
loop,
|
|
1701
2085
|
mediaDurationInSeconds,
|
|
@@ -1719,28 +2103,55 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1719
2103
|
trimBefore,
|
|
1720
2104
|
controls
|
|
1721
2105
|
});
|
|
1722
|
-
const bufferingContext =
|
|
2106
|
+
const bufferingContext = useContext3(Internals10.BufferingContextReact);
|
|
1723
2107
|
if (!bufferingContext) {
|
|
1724
2108
|
throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
|
|
1725
2109
|
}
|
|
1726
2110
|
const effectiveMuted = muted || mediaMuted || userPreferredVolume <= 0;
|
|
1727
|
-
const isPlayerBuffering =
|
|
2111
|
+
const isPlayerBuffering = Internals10.useIsPlayerBuffering(bufferingContext);
|
|
1728
2112
|
const initialPlaying = useRef(playing && !isPlayerBuffering);
|
|
1729
2113
|
const initialIsPremounting = useRef(isPremounting);
|
|
1730
2114
|
const initialIsPostmounting = useRef(isPostmounting);
|
|
1731
2115
|
const initialGlobalPlaybackRate = useRef(globalPlaybackRate);
|
|
1732
2116
|
const initialPlaybackRate = useRef(playbackRate);
|
|
1733
2117
|
const initialMuted = useRef(effectiveMuted);
|
|
2118
|
+
const initialSequenceOffset = useRef(sequenceOffset);
|
|
2119
|
+
useCommonEffects({
|
|
2120
|
+
mediaPlayerRef,
|
|
2121
|
+
mediaPlayerReady,
|
|
2122
|
+
currentTimeRef,
|
|
2123
|
+
playing,
|
|
2124
|
+
isPlayerBuffering,
|
|
2125
|
+
frame,
|
|
2126
|
+
trimBefore,
|
|
2127
|
+
trimAfter,
|
|
2128
|
+
effectiveMuted,
|
|
2129
|
+
userPreferredVolume,
|
|
2130
|
+
playbackRate,
|
|
2131
|
+
globalPlaybackRate,
|
|
2132
|
+
fps: videoConfig.fps,
|
|
2133
|
+
sequenceOffset,
|
|
2134
|
+
loop,
|
|
2135
|
+
debugAudioScheduling,
|
|
2136
|
+
durationInFrames: videoConfig.durationInFrames,
|
|
2137
|
+
isPremounting,
|
|
2138
|
+
isPostmounting,
|
|
2139
|
+
currentTime,
|
|
2140
|
+
logLevel,
|
|
2141
|
+
sharedAudioContext,
|
|
2142
|
+
label: "AudioForPreview"
|
|
2143
|
+
});
|
|
1734
2144
|
useEffect2(() => {
|
|
1735
2145
|
if (!sharedAudioContext)
|
|
1736
2146
|
return;
|
|
1737
2147
|
if (!sharedAudioContext.audioContext)
|
|
1738
2148
|
return;
|
|
2149
|
+
const { audioContext, audioSyncAnchor, scheduleAudioNode } = sharedAudioContext;
|
|
1739
2150
|
try {
|
|
1740
2151
|
const player = new MediaPlayer({
|
|
1741
2152
|
src: preloadedSrc,
|
|
1742
2153
|
logLevel,
|
|
1743
|
-
sharedAudioContext:
|
|
2154
|
+
sharedAudioContext: { audioContext, audioSyncAnchor, scheduleAudioNode },
|
|
1744
2155
|
loop,
|
|
1745
2156
|
trimAfter: initialTrimAfterRef.current,
|
|
1746
2157
|
trimBefore: initialTrimBeforeRef.current,
|
|
@@ -1749,13 +2160,15 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1749
2160
|
playbackRate: initialPlaybackRate.current,
|
|
1750
2161
|
audioStreamIndex: audioStreamIndex ?? 0,
|
|
1751
2162
|
debugOverlay: false,
|
|
2163
|
+
debugAudioScheduling,
|
|
1752
2164
|
bufferState: buffer,
|
|
1753
2165
|
isPostmounting: initialIsPostmounting.current,
|
|
1754
2166
|
isPremounting: initialIsPremounting.current,
|
|
1755
2167
|
globalPlaybackRate: initialGlobalPlaybackRate.current,
|
|
1756
2168
|
durationInFrames: videoConfig.durationInFrames,
|
|
1757
2169
|
onVideoFrameCallback: null,
|
|
1758
|
-
playing: initialPlaying.current
|
|
2170
|
+
playing: initialPlaying.current,
|
|
2171
|
+
sequenceOffset: initialSequenceOffset.current
|
|
1759
2172
|
});
|
|
1760
2173
|
mediaPlayerRef.current = player;
|
|
1761
2174
|
player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
|
|
@@ -1773,7 +2186,7 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1773
2186
|
if (action === "fail") {
|
|
1774
2187
|
throw errorToUse;
|
|
1775
2188
|
} else {
|
|
1776
|
-
|
|
2189
|
+
Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
1777
2190
|
setShouldFallbackToNativeAudio(true);
|
|
1778
2191
|
}
|
|
1779
2192
|
};
|
|
@@ -1796,7 +2209,7 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1796
2209
|
if (result.type === "success") {
|
|
1797
2210
|
setMediaPlayerReady(true);
|
|
1798
2211
|
setMediaDurationInSeconds(result.durationInSeconds);
|
|
1799
|
-
|
|
2212
|
+
Internals10.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] MediaPlayer initialized successfully`);
|
|
1800
2213
|
}
|
|
1801
2214
|
}).catch((error) => {
|
|
1802
2215
|
const [action, errorToUse] = callOnErrorAndResolve({
|
|
@@ -1809,7 +2222,7 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1809
2222
|
if (action === "fail") {
|
|
1810
2223
|
throw errorToUse;
|
|
1811
2224
|
} else {
|
|
1812
|
-
|
|
2225
|
+
Internals10.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] Failed to initialize MediaPlayer", error);
|
|
1813
2226
|
setShouldFallbackToNativeAudio(true);
|
|
1814
2227
|
}
|
|
1815
2228
|
});
|
|
@@ -1824,12 +2237,12 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1824
2237
|
if (action === "fail") {
|
|
1825
2238
|
throw errorToUse;
|
|
1826
2239
|
}
|
|
1827
|
-
|
|
2240
|
+
Internals10.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] MediaPlayer initialization failed", errorToUse);
|
|
1828
2241
|
setShouldFallbackToNativeAudio(true);
|
|
1829
2242
|
}
|
|
1830
2243
|
return () => {
|
|
1831
2244
|
if (mediaPlayerRef.current) {
|
|
1832
|
-
|
|
2245
|
+
Internals10.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] Disposing MediaPlayer`);
|
|
1833
2246
|
mediaPlayerRef.current.dispose();
|
|
1834
2247
|
mediaPlayerRef.current = null;
|
|
1835
2248
|
}
|
|
@@ -1840,108 +2253,15 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1840
2253
|
preloadedSrc,
|
|
1841
2254
|
logLevel,
|
|
1842
2255
|
sharedAudioContext,
|
|
1843
|
-
currentTimeRef,
|
|
1844
2256
|
loop,
|
|
1845
2257
|
videoConfig.fps,
|
|
1846
2258
|
audioStreamIndex,
|
|
1847
2259
|
disallowFallbackToHtml5Audio,
|
|
2260
|
+
debugAudioScheduling,
|
|
1848
2261
|
buffer,
|
|
1849
2262
|
onError,
|
|
1850
2263
|
videoConfig.durationInFrames
|
|
1851
|
-
]);
|
|
1852
|
-
useLayoutEffect(() => {
|
|
1853
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1854
|
-
if (!audioPlayer)
|
|
1855
|
-
return;
|
|
1856
|
-
if (playing && !isPlayerBuffering) {
|
|
1857
|
-
audioPlayer.play(currentTimeRef.current);
|
|
1858
|
-
} else {
|
|
1859
|
-
audioPlayer.pause();
|
|
1860
|
-
}
|
|
1861
|
-
}, [isPlayerBuffering, logLevel, playing]);
|
|
1862
|
-
useLayoutEffect(() => {
|
|
1863
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1864
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1865
|
-
return;
|
|
1866
|
-
}
|
|
1867
|
-
mediaPlayer.setTrimBefore(trimBefore, currentTimeRef.current);
|
|
1868
|
-
}, [trimBefore, mediaPlayerReady]);
|
|
1869
|
-
useLayoutEffect(() => {
|
|
1870
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1871
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1872
|
-
return;
|
|
1873
|
-
}
|
|
1874
|
-
mediaPlayer.setTrimAfter(trimAfter, currentTimeRef.current);
|
|
1875
|
-
}, [trimAfter, mediaPlayerReady]);
|
|
1876
|
-
useLayoutEffect(() => {
|
|
1877
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1878
|
-
if (!audioPlayer || !mediaPlayerReady)
|
|
1879
|
-
return;
|
|
1880
|
-
audioPlayer.setMuted(effectiveMuted);
|
|
1881
|
-
}, [effectiveMuted, mediaPlayerReady]);
|
|
1882
|
-
useEffect2(() => {
|
|
1883
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1884
|
-
if (!audioPlayer || !mediaPlayerReady) {
|
|
1885
|
-
return;
|
|
1886
|
-
}
|
|
1887
|
-
audioPlayer.setVolume(userPreferredVolume);
|
|
1888
|
-
}, [userPreferredVolume, mediaPlayerReady]);
|
|
1889
|
-
useEffect2(() => {
|
|
1890
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1891
|
-
if (!audioPlayer || !mediaPlayerReady) {
|
|
1892
|
-
return;
|
|
1893
|
-
}
|
|
1894
|
-
audioPlayer.setPlaybackRate(playbackRate, currentTimeRef.current);
|
|
1895
|
-
}, [playbackRate, mediaPlayerReady]);
|
|
1896
|
-
useLayoutEffect(() => {
|
|
1897
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1898
|
-
if (!audioPlayer || !mediaPlayerReady) {
|
|
1899
|
-
return;
|
|
1900
|
-
}
|
|
1901
|
-
audioPlayer.setGlobalPlaybackRate(globalPlaybackRate);
|
|
1902
|
-
}, [globalPlaybackRate, mediaPlayerReady]);
|
|
1903
|
-
useLayoutEffect(() => {
|
|
1904
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1905
|
-
if (!audioPlayer || !mediaPlayerReady) {
|
|
1906
|
-
return;
|
|
1907
|
-
}
|
|
1908
|
-
audioPlayer.setFps(videoConfig.fps);
|
|
1909
|
-
}, [videoConfig.fps, mediaPlayerReady]);
|
|
1910
|
-
useLayoutEffect(() => {
|
|
1911
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1912
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1913
|
-
return;
|
|
1914
|
-
}
|
|
1915
|
-
mediaPlayer.setLoop(loop);
|
|
1916
|
-
}, [loop, mediaPlayerReady]);
|
|
1917
|
-
useLayoutEffect(() => {
|
|
1918
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1919
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1920
|
-
return;
|
|
1921
|
-
}
|
|
1922
|
-
mediaPlayer.setDurationInFrames(videoConfig.durationInFrames);
|
|
1923
|
-
}, [videoConfig.durationInFrames, mediaPlayerReady]);
|
|
1924
|
-
useLayoutEffect(() => {
|
|
1925
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1926
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1927
|
-
return;
|
|
1928
|
-
}
|
|
1929
|
-
mediaPlayer.setIsPremounting(isPremounting);
|
|
1930
|
-
}, [isPremounting, mediaPlayerReady]);
|
|
1931
|
-
useLayoutEffect(() => {
|
|
1932
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
1933
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
mediaPlayer.setIsPostmounting(isPostmounting);
|
|
1937
|
-
}, [isPostmounting, mediaPlayerReady]);
|
|
1938
|
-
useLayoutEffect(() => {
|
|
1939
|
-
const audioPlayer = mediaPlayerRef.current;
|
|
1940
|
-
if (!audioPlayer || !mediaPlayerReady)
|
|
1941
|
-
return;
|
|
1942
|
-
audioPlayer.seekTo(currentTime).catch(() => {});
|
|
1943
|
-
Internals6.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
|
|
1944
|
-
}, [currentTime, logLevel, mediaPlayerReady]);
|
|
2264
|
+
]);
|
|
1945
2265
|
if (shouldFallbackToNativeAudio && !disallowFallbackToHtml5Audio) {
|
|
1946
2266
|
return /* @__PURE__ */ jsx(RemotionAudio, {
|
|
1947
2267
|
src,
|
|
@@ -1964,72 +2284,37 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1964
2284
|
}
|
|
1965
2285
|
return null;
|
|
1966
2286
|
};
|
|
1967
|
-
var audioSchema = {
|
|
1968
|
-
volume: {
|
|
1969
|
-
type: "number",
|
|
1970
|
-
min: 0,
|
|
1971
|
-
max: 20,
|
|
1972
|
-
step: 0.01,
|
|
1973
|
-
default: 1,
|
|
1974
|
-
description: "Volume"
|
|
1975
|
-
},
|
|
1976
|
-
playbackRate: {
|
|
1977
|
-
type: "number",
|
|
1978
|
-
min: 0,
|
|
1979
|
-
step: 0.01,
|
|
1980
|
-
default: 1,
|
|
1981
|
-
description: "Playback Rate"
|
|
1982
|
-
},
|
|
1983
|
-
trimBefore: { type: "number", min: 0, default: 0 },
|
|
1984
|
-
trimAfter: { type: "number", min: 0, default: 0 }
|
|
1985
|
-
};
|
|
1986
2287
|
var AudioForPreview = ({
|
|
1987
|
-
loop,
|
|
2288
|
+
loop = false,
|
|
1988
2289
|
src,
|
|
1989
2290
|
logLevel,
|
|
1990
2291
|
muted,
|
|
1991
2292
|
name,
|
|
1992
|
-
volume
|
|
2293
|
+
volume,
|
|
1993
2294
|
loopVolumeCurveBehavior,
|
|
1994
|
-
playbackRate
|
|
1995
|
-
trimAfter
|
|
1996
|
-
trimBefore
|
|
2295
|
+
playbackRate = 1,
|
|
2296
|
+
trimAfter,
|
|
2297
|
+
trimBefore,
|
|
1997
2298
|
showInTimeline,
|
|
1998
2299
|
stack,
|
|
1999
2300
|
disallowFallbackToHtml5Audio,
|
|
2000
2301
|
toneFrequency,
|
|
2001
2302
|
audioStreamIndex,
|
|
2002
2303
|
fallbackHtml5AudioProps,
|
|
2003
|
-
|
|
2304
|
+
debugAudioScheduling,
|
|
2305
|
+
onError,
|
|
2306
|
+
controls
|
|
2004
2307
|
}) => {
|
|
2005
|
-
const schemaInput = useMemo2(() => {
|
|
2006
|
-
if (typeof volumeProp !== "number") {
|
|
2007
|
-
return null;
|
|
2008
|
-
}
|
|
2009
|
-
return {
|
|
2010
|
-
volume: volumeProp,
|
|
2011
|
-
playbackRate: playbackRateProp,
|
|
2012
|
-
trimBefore: trimBeforeProp,
|
|
2013
|
-
trimAfter: trimAfterProp,
|
|
2014
|
-
loop: loop ?? false
|
|
2015
|
-
};
|
|
2016
|
-
}, [volumeProp, playbackRateProp, trimBeforeProp, trimAfterProp, loop]);
|
|
2017
|
-
const { controls, values } = Internals6.useSchema(schemaInput ? audioSchema : null, schemaInput);
|
|
2018
|
-
const volume = schemaInput !== null ? values.volume : volumeProp;
|
|
2019
|
-
const playbackRate = schemaInput !== null ? values.playbackRate : playbackRateProp;
|
|
2020
|
-
const trimBefore = schemaInput !== null ? values.trimBefore : trimBeforeProp;
|
|
2021
|
-
const trimAfter = schemaInput !== null ? values.trimAfter : trimAfterProp;
|
|
2022
|
-
const effectiveLoop = schemaInput !== null ? values.loop : loop ?? false;
|
|
2023
2308
|
const preloadedSrc = usePreload(src);
|
|
2024
|
-
const defaultLogLevel =
|
|
2309
|
+
const defaultLogLevel = Internals10.useLogLevel();
|
|
2025
2310
|
const frame = useCurrentFrame2();
|
|
2026
2311
|
const videoConfig = useVideoConfig2();
|
|
2027
2312
|
const currentTime = frame / videoConfig.fps;
|
|
2028
2313
|
const showShow = useMemo2(() => {
|
|
2029
2314
|
return getTimeInSeconds({
|
|
2030
2315
|
unloopedTimeInSeconds: currentTime,
|
|
2031
|
-
playbackRate
|
|
2032
|
-
loop
|
|
2316
|
+
playbackRate,
|
|
2317
|
+
loop,
|
|
2033
2318
|
trimBefore,
|
|
2034
2319
|
trimAfter,
|
|
2035
2320
|
mediaDurationInSeconds: Infinity,
|
|
@@ -2039,12 +2324,12 @@ var AudioForPreview = ({
|
|
|
2039
2324
|
}) !== null;
|
|
2040
2325
|
}, [
|
|
2041
2326
|
currentTime,
|
|
2042
|
-
effectiveLoop,
|
|
2043
2327
|
playbackRate,
|
|
2044
2328
|
src,
|
|
2045
2329
|
trimAfter,
|
|
2046
2330
|
trimBefore,
|
|
2047
|
-
videoConfig.fps
|
|
2331
|
+
videoConfig.fps,
|
|
2332
|
+
loop
|
|
2048
2333
|
]);
|
|
2049
2334
|
if (!showShow) {
|
|
2050
2335
|
return null;
|
|
@@ -2052,12 +2337,12 @@ var AudioForPreview = ({
|
|
|
2052
2337
|
return /* @__PURE__ */ jsx(AudioForPreviewAssertedShowing, {
|
|
2053
2338
|
audioStreamIndex: audioStreamIndex ?? 0,
|
|
2054
2339
|
src: preloadedSrc,
|
|
2055
|
-
playbackRate
|
|
2340
|
+
playbackRate,
|
|
2056
2341
|
logLevel: logLevel ?? defaultLogLevel,
|
|
2057
2342
|
muted: muted ?? false,
|
|
2058
2343
|
volume: volume ?? 1,
|
|
2059
2344
|
loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? "repeat",
|
|
2060
|
-
loop
|
|
2345
|
+
loop,
|
|
2061
2346
|
trimAfter,
|
|
2062
2347
|
trimBefore,
|
|
2063
2348
|
name,
|
|
@@ -2065,6 +2350,7 @@ var AudioForPreview = ({
|
|
|
2065
2350
|
stack,
|
|
2066
2351
|
disallowFallbackToHtml5Audio: disallowFallbackToHtml5Audio ?? false,
|
|
2067
2352
|
toneFrequency,
|
|
2353
|
+
debugAudioScheduling: debugAudioScheduling ?? false,
|
|
2068
2354
|
onError,
|
|
2069
2355
|
fallbackHtml5AudioProps,
|
|
2070
2356
|
controls
|
|
@@ -2072,11 +2358,11 @@ var AudioForPreview = ({
|
|
|
2072
2358
|
};
|
|
2073
2359
|
|
|
2074
2360
|
// src/audio/audio-for-rendering.tsx
|
|
2075
|
-
import { useContext as
|
|
2361
|
+
import { useContext as useContext4, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
2076
2362
|
import {
|
|
2077
2363
|
cancelRender as cancelRender2,
|
|
2078
2364
|
Html5Audio,
|
|
2079
|
-
Internals as
|
|
2365
|
+
Internals as Internals18,
|
|
2080
2366
|
random,
|
|
2081
2367
|
useCurrentFrame as useCurrentFrame3,
|
|
2082
2368
|
useDelayRender,
|
|
@@ -2085,13 +2371,13 @@ import {
|
|
|
2085
2371
|
|
|
2086
2372
|
// src/caches.ts
|
|
2087
2373
|
import React2 from "react";
|
|
2088
|
-
import { cancelRender, Internals as
|
|
2374
|
+
import { cancelRender, Internals as Internals15 } from "remotion";
|
|
2089
2375
|
|
|
2090
2376
|
// src/audio-extraction/audio-manager.ts
|
|
2091
|
-
import { Internals as
|
|
2377
|
+
import { Internals as Internals12 } from "remotion";
|
|
2092
2378
|
|
|
2093
2379
|
// src/audio-extraction/audio-iterator.ts
|
|
2094
|
-
import { Internals as
|
|
2380
|
+
import { Internals as Internals11 } from "remotion";
|
|
2095
2381
|
|
|
2096
2382
|
// src/audio-extraction/audio-cache.ts
|
|
2097
2383
|
var makeAudioCache = () => {
|
|
@@ -2162,7 +2448,7 @@ var makeAudioCache = () => {
|
|
|
2162
2448
|
};
|
|
2163
2449
|
|
|
2164
2450
|
// src/audio-extraction/audio-iterator.ts
|
|
2165
|
-
var
|
|
2451
|
+
var EXTRA_THRESHOLD_IN_SECONDS = 1.5;
|
|
2166
2452
|
var safetyOutOfOrderThreshold = 0.2;
|
|
2167
2453
|
var warned = {};
|
|
2168
2454
|
var warnAboutMatroskaOnce = (src, logLevel) => {
|
|
@@ -2170,7 +2456,7 @@ var warnAboutMatroskaOnce = (src, logLevel) => {
|
|
|
2170
2456
|
return;
|
|
2171
2457
|
}
|
|
2172
2458
|
warned[src] = true;
|
|
2173
|
-
|
|
2459
|
+
Internals11.Log.warn({ logLevel, tag: "@remotion/media" }, `Audio from ${src} will need to be read from the beginning. https://www.remotion.dev/docs/media/support#matroska-limitation`);
|
|
2174
2460
|
};
|
|
2175
2461
|
var makeAudioIterator2 = ({
|
|
2176
2462
|
audioSampleSink,
|
|
@@ -2180,7 +2466,7 @@ var makeAudioIterator2 = ({
|
|
|
2180
2466
|
actualMatroskaTimestamps,
|
|
2181
2467
|
logLevel
|
|
2182
2468
|
}) => {
|
|
2183
|
-
const sampleIterator = audioSampleSink.samples(isMatroska ? 0 : Math.max(0, startTimestamp -
|
|
2469
|
+
const sampleIterator = audioSampleSink.samples(isMatroska ? 0 : Math.max(0, startTimestamp - EXTRA_THRESHOLD_IN_SECONDS));
|
|
2184
2470
|
if (isMatroska) {
|
|
2185
2471
|
warnAboutMatroskaOnce(src, logLevel);
|
|
2186
2472
|
}
|
|
@@ -2238,7 +2524,7 @@ var makeAudioIterator2 = ({
|
|
|
2238
2524
|
if (openTimestamps.length > 0) {
|
|
2239
2525
|
const first = openTimestamps[0];
|
|
2240
2526
|
const last = openTimestamps[openTimestamps.length - 1];
|
|
2241
|
-
|
|
2527
|
+
Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, "Open audio samples for src", src, `${first.toFixed(3)}...${last.toFixed(3)}`);
|
|
2242
2528
|
}
|
|
2243
2529
|
};
|
|
2244
2530
|
const getCacheStats = () => {
|
|
@@ -2335,7 +2621,7 @@ var makeAudioManager = () => {
|
|
|
2335
2621
|
if (seenKeys.has(key)) {
|
|
2336
2622
|
iterator.prepareForDeletion();
|
|
2337
2623
|
iterators.splice(iterators.indexOf(iterator), 1);
|
|
2338
|
-
|
|
2624
|
+
Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted duplicate iterator for ${iterator.src}`);
|
|
2339
2625
|
}
|
|
2340
2626
|
seenKeys.add(key);
|
|
2341
2627
|
}
|
|
@@ -2356,7 +2642,7 @@ var makeAudioManager = () => {
|
|
|
2356
2642
|
attempts++;
|
|
2357
2643
|
}
|
|
2358
2644
|
if ((await getTotalCacheStats()).totalSize > maxCacheSize && attempts >= maxAttempts) {
|
|
2359
|
-
|
|
2645
|
+
Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Audio cache: Exceeded max cache size after ${maxAttempts} attempts. Still ${(await getTotalCacheStats()).totalSize} bytes used, target was ${maxCacheSize} bytes.`);
|
|
2360
2646
|
}
|
|
2361
2647
|
for (const iterator of iterators) {
|
|
2362
2648
|
if (iterator.src === src && await iterator.waitForCompletion() && iterator.canSatisfyRequestedTime(timeInSeconds)) {
|
|
@@ -2425,7 +2711,7 @@ var makeAudioManager = () => {
|
|
|
2425
2711
|
};
|
|
2426
2712
|
|
|
2427
2713
|
// src/video-extraction/keyframe-manager.ts
|
|
2428
|
-
import { Internals as
|
|
2714
|
+
import { Internals as Internals14 } from "remotion";
|
|
2429
2715
|
|
|
2430
2716
|
// src/render-timestamp-range.ts
|
|
2431
2717
|
var renderTimestampRange = (timestamps) => {
|
|
@@ -2439,7 +2725,7 @@ var renderTimestampRange = (timestamps) => {
|
|
|
2439
2725
|
};
|
|
2440
2726
|
|
|
2441
2727
|
// src/video-extraction/keyframe-bank.ts
|
|
2442
|
-
import { Internals as
|
|
2728
|
+
import { Internals as Internals13 } from "remotion";
|
|
2443
2729
|
|
|
2444
2730
|
// src/video-extraction/get-allocation-size.ts
|
|
2445
2731
|
var getAllocationSize = (sample) => {
|
|
@@ -2502,7 +2788,7 @@ var makeKeyframeBank = async ({
|
|
|
2502
2788
|
}
|
|
2503
2789
|
}
|
|
2504
2790
|
if (deletedTimestamps.length > 0) {
|
|
2505
|
-
|
|
2791
|
+
Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${deletedTimestamps.length} frame${deletedTimestamps.length === 1 ? "" : "s"} ${renderTimestampRange(deletedTimestamps)} for src ${src} because it is lower than ${timestampInSeconds}. Remaining: ${renderTimestampRange(frameTimestamps)}`);
|
|
2506
2792
|
}
|
|
2507
2793
|
};
|
|
2508
2794
|
const hasDecodedEnoughForTimestamp = (timestamp) => {
|
|
@@ -2525,7 +2811,7 @@ var makeKeyframeBank = async ({
|
|
|
2525
2811
|
frameTimestamps.push(frame.timestamp);
|
|
2526
2812
|
allocationSize += getAllocationSize(frame);
|
|
2527
2813
|
lastUsed = Date.now();
|
|
2528
|
-
|
|
2814
|
+
Internals13.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
|
|
2529
2815
|
};
|
|
2530
2816
|
const ensureEnoughFramesForTimestamp = async (timestampInSeconds, logLevel, fps) => {
|
|
2531
2817
|
while (!hasDecodedEnoughForTimestamp(timestampInSeconds)) {
|
|
@@ -2580,7 +2866,7 @@ var makeKeyframeBank = async ({
|
|
|
2580
2866
|
throw new Error("No first frame found");
|
|
2581
2867
|
}
|
|
2582
2868
|
const startTimestampInSeconds = firstFrame.value.timestamp;
|
|
2583
|
-
|
|
2869
|
+
Internals13.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec`);
|
|
2584
2870
|
addFrame(firstFrame.value, parentLogLevel);
|
|
2585
2871
|
const getRangeOfTimestamps = () => {
|
|
2586
2872
|
if (frameTimestamps.length === 0) {
|
|
@@ -2598,7 +2884,7 @@ var makeKeyframeBank = async ({
|
|
|
2598
2884
|
const prepareForDeletion = (logLevel, reason) => {
|
|
2599
2885
|
const range = getRangeOfTimestamps();
|
|
2600
2886
|
if (range) {
|
|
2601
|
-
|
|
2887
|
+
Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion (${reason}) of keyframe bank from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec`);
|
|
2602
2888
|
}
|
|
2603
2889
|
let framesDeleted = 0;
|
|
2604
2890
|
for (const frameTimestamp of frameTimestamps.slice()) {
|
|
@@ -2671,10 +2957,10 @@ var makeKeyframeManager = () => {
|
|
|
2671
2957
|
if (size === 0) {
|
|
2672
2958
|
continue;
|
|
2673
2959
|
}
|
|
2674
|
-
|
|
2960
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
|
|
2675
2961
|
}
|
|
2676
2962
|
}
|
|
2677
|
-
|
|
2963
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
|
|
2678
2964
|
};
|
|
2679
2965
|
const getCacheStats = () => {
|
|
2680
2966
|
let count = 0;
|
|
@@ -2728,7 +3014,7 @@ var makeKeyframeManager = () => {
|
|
|
2728
3014
|
const { framesDeleted } = mostInThePastBank.prepareForDeletion(logLevel, "deleted oldest keyframe bank to stay under max cache size");
|
|
2729
3015
|
sources[mostInThePastSrc].splice(mostInThePastIndex, 1);
|
|
2730
3016
|
if (range) {
|
|
2731
|
-
|
|
3017
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${framesDeleted} frames for src ${mostInThePastSrc} from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec to free up memory.`);
|
|
2732
3018
|
}
|
|
2733
3019
|
}
|
|
2734
3020
|
return { finish: false };
|
|
@@ -2742,12 +3028,12 @@ var makeKeyframeManager = () => {
|
|
|
2742
3028
|
if (finish) {
|
|
2743
3029
|
break;
|
|
2744
3030
|
}
|
|
2745
|
-
|
|
3031
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, "Deleted oldest keyframe bank to stay under max cache size", (cacheStats.totalSize / 1024 / 1024).toFixed(1), "out of", (maxCacheSize / 1024 / 1024).toFixed(1));
|
|
2746
3032
|
cacheStats = getTotalCacheStats();
|
|
2747
3033
|
attempts++;
|
|
2748
3034
|
}
|
|
2749
3035
|
if (cacheStats.totalSize > maxCacheSize && attempts >= maxAttempts) {
|
|
2750
|
-
|
|
3036
|
+
Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, `Exceeded max cache size after ${maxAttempts} attempts. Remaining cache size: ${(cacheStats.totalSize / 1024 / 1024).toFixed(1)} MB, target was ${(maxCacheSize / 1024 / 1024).toFixed(1)} MB.`);
|
|
2751
3037
|
}
|
|
2752
3038
|
};
|
|
2753
3039
|
const clearKeyframeBanksBeforeTime = ({
|
|
@@ -2768,7 +3054,7 @@ var makeKeyframeManager = () => {
|
|
|
2768
3054
|
}
|
|
2769
3055
|
if (range.lastTimestamp < threshold) {
|
|
2770
3056
|
bank.prepareForDeletion(logLevel, "cleared before threshold " + threshold);
|
|
2771
|
-
|
|
3057
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${range.firstTimestamp}sec to ${range.lastTimestamp}sec`);
|
|
2772
3058
|
const bankIndex = banks.indexOf(bank);
|
|
2773
3059
|
delete sources[src][bankIndex];
|
|
2774
3060
|
} else {
|
|
@@ -2790,7 +3076,7 @@ var makeKeyframeManager = () => {
|
|
|
2790
3076
|
const existingBanks = sources[src] ?? [];
|
|
2791
3077
|
const existingBank = existingBanks?.find((bank) => bank.canSatisfyTimestamp(timestamp));
|
|
2792
3078
|
if (!existingBank) {
|
|
2793
|
-
|
|
3079
|
+
Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `Creating new keyframe bank for src ${src} at timestamp ${timestamp}`);
|
|
2794
3080
|
const newKeyframeBank = await makeKeyframeBank({
|
|
2795
3081
|
videoSampleSink,
|
|
2796
3082
|
logLevel,
|
|
@@ -2801,10 +3087,10 @@ var makeKeyframeManager = () => {
|
|
|
2801
3087
|
return newKeyframeBank;
|
|
2802
3088
|
}
|
|
2803
3089
|
if (existingBank.canSatisfyTimestamp(timestamp)) {
|
|
2804
|
-
|
|
3090
|
+
Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists and satisfies timestamp ${timestamp}`);
|
|
2805
3091
|
return existingBank;
|
|
2806
3092
|
}
|
|
2807
|
-
|
|
3093
|
+
Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
|
|
2808
3094
|
existingBank.prepareForDeletion(logLevel, "already existed but evicted");
|
|
2809
3095
|
sources[src] = sources[src].filter((bank) => bank !== existingBank);
|
|
2810
3096
|
const replacementKeybank = await makeKeyframeBank({
|
|
@@ -2895,20 +3181,20 @@ var getUncachedMaxCacheSize = (logLevel) => {
|
|
|
2895
3181
|
if (window.remotion_mediaCacheSizeInBytes > 20000 * 1024 * 1024) {
|
|
2896
3182
|
cancelRender(new Error(`The maximum value for the "mediaCacheSizeInBytes" prop is 20GB (${20000 * 1024 * 1024}), got: ${window.remotion_mediaCacheSizeInBytes}`));
|
|
2897
3183
|
}
|
|
2898
|
-
|
|
3184
|
+
Internals15.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
|
|
2899
3185
|
return window.remotion_mediaCacheSizeInBytes;
|
|
2900
3186
|
}
|
|
2901
3187
|
if (typeof window !== "undefined" && window.remotion_initialMemoryAvailable !== undefined && window.remotion_initialMemoryAvailable !== null) {
|
|
2902
3188
|
const value = window.remotion_initialMemoryAvailable / 2;
|
|
2903
3189
|
if (value < 500 * 1024 * 1024) {
|
|
2904
|
-
|
|
3190
|
+
Internals15.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on minimum value of 500MB (which is more than half of the available system memory!)`);
|
|
2905
3191
|
return 500 * 1024 * 1024;
|
|
2906
3192
|
}
|
|
2907
3193
|
if (value > 20000 * 1024 * 1024) {
|
|
2908
|
-
|
|
3194
|
+
Internals15.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on maximum value of 20GB (which is less than half of the available system memory)`);
|
|
2909
3195
|
return 20000 * 1024 * 1024;
|
|
2910
3196
|
}
|
|
2911
|
-
|
|
3197
|
+
Internals15.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
|
|
2912
3198
|
return value;
|
|
2913
3199
|
}
|
|
2914
3200
|
return 1000 * 1000 * 1000;
|
|
@@ -2922,7 +3208,7 @@ var getMaxVideoCacheSize = (logLevel) => {
|
|
|
2922
3208
|
return cachedMaxCacheSize;
|
|
2923
3209
|
};
|
|
2924
3210
|
var useMaxMediaCacheSize = (logLevel) => {
|
|
2925
|
-
const context = React2.useContext(
|
|
3211
|
+
const context = React2.useContext(Internals15.MaxMediaCacheSizeContext);
|
|
2926
3212
|
if (context === null) {
|
|
2927
3213
|
return getMaxVideoCacheSize(logLevel);
|
|
2928
3214
|
}
|
|
@@ -3171,7 +3457,7 @@ var combineAudioDataAndClosePrevious = (audioDataArray) => {
|
|
|
3171
3457
|
};
|
|
3172
3458
|
|
|
3173
3459
|
// src/get-sink.ts
|
|
3174
|
-
import { Internals as
|
|
3460
|
+
import { Internals as Internals16 } from "remotion";
|
|
3175
3461
|
|
|
3176
3462
|
// src/video-extraction/get-frames-since-keyframe.ts
|
|
3177
3463
|
import {
|
|
@@ -3324,7 +3610,7 @@ var sinkPromises = {};
|
|
|
3324
3610
|
var getSink = (src, logLevel) => {
|
|
3325
3611
|
let promise = sinkPromises[src];
|
|
3326
3612
|
if (!promise) {
|
|
3327
|
-
|
|
3613
|
+
Internals16.Log.verbose({
|
|
3328
3614
|
logLevel,
|
|
3329
3615
|
tag: "@remotion/media"
|
|
3330
3616
|
}, `Sink for ${src} was not found, creating new sink`);
|
|
@@ -3464,7 +3750,7 @@ var extractAudio = (params) => {
|
|
|
3464
3750
|
};
|
|
3465
3751
|
|
|
3466
3752
|
// src/video-extraction/extract-frame.ts
|
|
3467
|
-
import { Internals as
|
|
3753
|
+
import { Internals as Internals17 } from "remotion";
|
|
3468
3754
|
var extractFrameInternal = async ({
|
|
3469
3755
|
src,
|
|
3470
3756
|
timeInSeconds: unloopedTimeInSeconds,
|
|
@@ -3545,7 +3831,7 @@ var extractFrameInternal = async ({
|
|
|
3545
3831
|
durationInSeconds: await sink.getDuration()
|
|
3546
3832
|
};
|
|
3547
3833
|
} catch (err) {
|
|
3548
|
-
|
|
3834
|
+
Internals17.Log.info({ logLevel, tag: "@remotion/media" }, `Error decoding ${src} at time ${timeInSeconds}: ${err}`, err);
|
|
3549
3835
|
return { type: "cannot-decode", durationInSeconds: mediaDurationInSeconds };
|
|
3550
3836
|
}
|
|
3551
3837
|
};
|
|
@@ -3941,13 +4227,13 @@ var AudioForRendering = ({
|
|
|
3941
4227
|
trimBefore,
|
|
3942
4228
|
onError
|
|
3943
4229
|
}) => {
|
|
3944
|
-
const defaultLogLevel =
|
|
4230
|
+
const defaultLogLevel = Internals18.useLogLevel();
|
|
3945
4231
|
const logLevel = overriddenLogLevel ?? defaultLogLevel;
|
|
3946
4232
|
const frame = useCurrentFrame3();
|
|
3947
|
-
const absoluteFrame =
|
|
3948
|
-
const videoConfig =
|
|
3949
|
-
const { registerRenderAsset, unregisterRenderAsset } =
|
|
3950
|
-
const startsAt =
|
|
4233
|
+
const absoluteFrame = Internals18.useTimelinePosition();
|
|
4234
|
+
const videoConfig = Internals18.useUnsafeVideoConfig();
|
|
4235
|
+
const { registerRenderAsset, unregisterRenderAsset } = useContext4(Internals18.RenderAssetManager);
|
|
4236
|
+
const startsAt = Internals18.useMediaStartsAt();
|
|
3951
4237
|
const environment = useRemotionEnvironment();
|
|
3952
4238
|
if (!videoConfig) {
|
|
3953
4239
|
throw new Error("No video config found");
|
|
@@ -3958,7 +4244,7 @@ var AudioForRendering = ({
|
|
|
3958
4244
|
const { fps } = videoConfig;
|
|
3959
4245
|
const { delayRender, continueRender } = useDelayRender();
|
|
3960
4246
|
const [replaceWithHtml5Audio, setReplaceWithHtml5Audio] = useState3(false);
|
|
3961
|
-
const sequenceContext =
|
|
4247
|
+
const sequenceContext = useContext4(Internals18.SequenceContext);
|
|
3962
4248
|
const id = useMemo3(() => `media-audio-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
|
|
3963
4249
|
src,
|
|
3964
4250
|
sequenceContext?.cumulatedFrom,
|
|
@@ -3966,7 +4252,7 @@ var AudioForRendering = ({
|
|
|
3966
4252
|
sequenceContext?.durationInFrames
|
|
3967
4253
|
]);
|
|
3968
4254
|
const maxCacheSize = useMaxMediaCacheSize(logLevel);
|
|
3969
|
-
const audioEnabled =
|
|
4255
|
+
const audioEnabled = Internals18.useAudioEnabled();
|
|
3970
4256
|
useLayoutEffect2(() => {
|
|
3971
4257
|
const timestamp = frame / fps;
|
|
3972
4258
|
const durationInSeconds = 1 / fps;
|
|
@@ -4016,7 +4302,7 @@ var AudioForRendering = ({
|
|
|
4016
4302
|
if (action === "fail") {
|
|
4017
4303
|
cancelRender2(errorToUse);
|
|
4018
4304
|
}
|
|
4019
|
-
|
|
4305
|
+
Internals18.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
4020
4306
|
setReplaceWithHtml5Audio(true);
|
|
4021
4307
|
};
|
|
4022
4308
|
if (result.type === "unknown-container-format") {
|
|
@@ -4043,12 +4329,12 @@ var AudioForRendering = ({
|
|
|
4043
4329
|
frame,
|
|
4044
4330
|
startsAt
|
|
4045
4331
|
});
|
|
4046
|
-
const volume =
|
|
4332
|
+
const volume = Internals18.evaluateVolume({
|
|
4047
4333
|
volume: volumeProp,
|
|
4048
4334
|
frame: volumePropsFrame,
|
|
4049
4335
|
mediaVolume: 1
|
|
4050
4336
|
});
|
|
4051
|
-
|
|
4337
|
+
Internals18.warnAboutTooHighVolume(volume);
|
|
4052
4338
|
if (audio && volume > 0) {
|
|
4053
4339
|
applyVolume(audio.data, volume);
|
|
4054
4340
|
registerRenderAsset({
|
|
@@ -4124,9 +4410,27 @@ var AudioForRendering = ({
|
|
|
4124
4410
|
|
|
4125
4411
|
// src/audio/audio.tsx
|
|
4126
4412
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
4127
|
-
var { validateMediaProps } =
|
|
4128
|
-
var
|
|
4129
|
-
|
|
4413
|
+
var { validateMediaProps } = Internals19;
|
|
4414
|
+
var audioSchema = {
|
|
4415
|
+
volume: {
|
|
4416
|
+
type: "number",
|
|
4417
|
+
min: 0,
|
|
4418
|
+
max: 20,
|
|
4419
|
+
step: 0.01,
|
|
4420
|
+
default: 1,
|
|
4421
|
+
description: "Volume"
|
|
4422
|
+
},
|
|
4423
|
+
playbackRate: {
|
|
4424
|
+
type: "number",
|
|
4425
|
+
min: 0.1,
|
|
4426
|
+
step: 0.01,
|
|
4427
|
+
default: 1,
|
|
4428
|
+
description: "Playback Rate"
|
|
4429
|
+
},
|
|
4430
|
+
loop: { type: "boolean", default: false, description: "Loop" }
|
|
4431
|
+
};
|
|
4432
|
+
var AudioInner = (props) => {
|
|
4433
|
+
const { name, stack, showInTimeline, controls, ...otherProps } = props;
|
|
4130
4434
|
const environment = useRemotionEnvironment2();
|
|
4131
4435
|
if (typeof props.src !== "string") {
|
|
4132
4436
|
throw new TypeError(`The \`<Audio>\` tag requires a string for \`src\`, but got ${JSON.stringify(props.src)} instead.`);
|
|
@@ -4140,17 +4444,19 @@ var Audio = (props) => {
|
|
|
4140
4444
|
return /* @__PURE__ */ jsx3(AudioForPreview, {
|
|
4141
4445
|
name,
|
|
4142
4446
|
...otherProps,
|
|
4143
|
-
stack: stack ?? null
|
|
4447
|
+
stack: stack ?? null,
|
|
4448
|
+
controls
|
|
4144
4449
|
});
|
|
4145
4450
|
};
|
|
4146
|
-
|
|
4451
|
+
var Audio = Internals19.wrapInSchema(AudioInner, audioSchema);
|
|
4452
|
+
Internals19.addSequenceStackTraces(Audio);
|
|
4147
4453
|
|
|
4148
4454
|
// src/video/video.tsx
|
|
4149
|
-
import { Internals as
|
|
4455
|
+
import { Internals as Internals22, useRemotionEnvironment as useRemotionEnvironment4 } from "remotion";
|
|
4150
4456
|
|
|
4151
4457
|
// src/video/video-for-preview.tsx
|
|
4152
4458
|
import {
|
|
4153
|
-
useContext as
|
|
4459
|
+
useContext as useContext5,
|
|
4154
4460
|
useEffect as useEffect3,
|
|
4155
4461
|
useLayoutEffect as useLayoutEffect3,
|
|
4156
4462
|
useMemo as useMemo4,
|
|
@@ -4159,7 +4465,7 @@ import {
|
|
|
4159
4465
|
} from "react";
|
|
4160
4466
|
import {
|
|
4161
4467
|
Html5Video,
|
|
4162
|
-
Internals as
|
|
4468
|
+
Internals as Internals20,
|
|
4163
4469
|
useBufferState as useBufferState2,
|
|
4164
4470
|
useCurrentFrame as useCurrentFrame4,
|
|
4165
4471
|
useVideoConfig as useVideoConfig3
|
|
@@ -4177,7 +4483,7 @@ var {
|
|
|
4177
4483
|
usePreload: usePreload2,
|
|
4178
4484
|
SequenceContext: SequenceContext2,
|
|
4179
4485
|
SequenceVisibilityToggleContext
|
|
4180
|
-
} =
|
|
4486
|
+
} = Internals20;
|
|
4181
4487
|
var VideoForPreviewAssertedShowing = ({
|
|
4182
4488
|
src: unpreloadedSrc,
|
|
4183
4489
|
style,
|
|
@@ -4198,6 +4504,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4198
4504
|
fallbackOffthreadVideoProps,
|
|
4199
4505
|
audioStreamIndex,
|
|
4200
4506
|
debugOverlay,
|
|
4507
|
+
debugAudioScheduling,
|
|
4201
4508
|
headless,
|
|
4202
4509
|
onError,
|
|
4203
4510
|
controls
|
|
@@ -4213,26 +4520,28 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4213
4520
|
const [mediaPlayerReady, setMediaPlayerReady] = useState4(false);
|
|
4214
4521
|
const [shouldFallbackToNativeVideo, setShouldFallbackToNativeVideo] = useState4(false);
|
|
4215
4522
|
const [playing] = Timeline2.usePlayingState();
|
|
4216
|
-
const timelineContext =
|
|
4523
|
+
const timelineContext = Internals20.useTimelineContext();
|
|
4217
4524
|
const globalPlaybackRate = timelineContext.playbackRate;
|
|
4218
|
-
const sharedAudioContext =
|
|
4525
|
+
const sharedAudioContext = useContext5(SharedAudioContext2);
|
|
4219
4526
|
const buffer = useBufferState2();
|
|
4220
4527
|
const [mediaMuted] = useMediaMutedState2();
|
|
4221
4528
|
const [mediaVolume] = useMediaVolumeState2();
|
|
4222
4529
|
const [mediaDurationInSeconds, setMediaDurationInSeconds] = useState4(null);
|
|
4223
|
-
const { hidden } =
|
|
4530
|
+
const { hidden } = useContext5(SequenceVisibilityToggleContext);
|
|
4224
4531
|
const volumePropFrame = useFrameForVolumeProp2(loopVolumeCurveBehavior);
|
|
4225
4532
|
const userPreferredVolume = evaluateVolume2({
|
|
4226
4533
|
frame: volumePropFrame,
|
|
4227
4534
|
volume,
|
|
4228
4535
|
mediaVolume
|
|
4229
4536
|
});
|
|
4537
|
+
if (!videoConfig) {
|
|
4538
|
+
throw new Error("No video config found");
|
|
4539
|
+
}
|
|
4230
4540
|
warnAboutTooHighVolume2(userPreferredVolume);
|
|
4231
|
-
const parentSequence =
|
|
4541
|
+
const parentSequence = useContext5(SequenceContext2);
|
|
4232
4542
|
const isPremounting = Boolean(parentSequence?.premounting);
|
|
4233
4543
|
const isPostmounting = Boolean(parentSequence?.postmounting);
|
|
4234
|
-
const
|
|
4235
|
-
const isNextFrameGoingToPlay = playingWhilePremounting && premountFramesRemaining > 0 && premountFramesRemaining <= 1.000000001;
|
|
4544
|
+
const sequenceOffset = ((parentSequence?.cumulatedFrom ?? 0) + (parentSequence?.relativeFrom ?? 0)) / videoConfig.fps;
|
|
4236
4545
|
const loopDisplay = useLoopDisplay({
|
|
4237
4546
|
loop,
|
|
4238
4547
|
mediaDurationInSeconds,
|
|
@@ -4257,34 +4566,35 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4257
4566
|
controls
|
|
4258
4567
|
});
|
|
4259
4568
|
const isSequenceHidden = hidden[timelineId] ?? false;
|
|
4260
|
-
if (!videoConfig) {
|
|
4261
|
-
throw new Error("No video config found");
|
|
4262
|
-
}
|
|
4263
4569
|
const currentTime = frame / videoConfig.fps;
|
|
4264
4570
|
const currentTimeRef = useRef2(currentTime);
|
|
4265
4571
|
currentTimeRef.current = currentTime;
|
|
4266
4572
|
const preloadedSrc = usePreload2(src);
|
|
4267
|
-
const buffering =
|
|
4573
|
+
const buffering = useContext5(Internals20.BufferingContextReact);
|
|
4268
4574
|
if (!buffering) {
|
|
4269
4575
|
throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
|
|
4270
4576
|
}
|
|
4271
4577
|
const effectiveMuted = isSequenceHidden || muted || mediaMuted || userPreferredVolume <= 0;
|
|
4272
|
-
const isPlayerBuffering =
|
|
4578
|
+
const isPlayerBuffering = Internals20.useIsPlayerBuffering(buffering);
|
|
4273
4579
|
const initialPlaying = useRef2(playing && !isPlayerBuffering);
|
|
4274
4580
|
const initialIsPremounting = useRef2(isPremounting);
|
|
4275
4581
|
const initialIsPostmounting = useRef2(isPostmounting);
|
|
4276
4582
|
const initialGlobalPlaybackRate = useRef2(globalPlaybackRate);
|
|
4277
4583
|
const initialPlaybackRate = useRef2(playbackRate);
|
|
4278
4584
|
const initialMuted = useRef2(effectiveMuted);
|
|
4585
|
+
const initialSequenceOffset = useRef2(sequenceOffset);
|
|
4279
4586
|
useEffect3(() => {
|
|
4280
4587
|
if (!sharedAudioContext)
|
|
4281
4588
|
return;
|
|
4589
|
+
if (!sharedAudioContext.audioContext)
|
|
4590
|
+
return;
|
|
4591
|
+
const { audioContext, audioSyncAnchor, scheduleAudioNode } = sharedAudioContext;
|
|
4282
4592
|
try {
|
|
4283
4593
|
const player = new MediaPlayer({
|
|
4284
4594
|
canvas: canvasRef.current,
|
|
4285
4595
|
src: preloadedSrc,
|
|
4286
4596
|
logLevel,
|
|
4287
|
-
sharedAudioContext:
|
|
4597
|
+
sharedAudioContext: { audioContext, audioSyncAnchor, scheduleAudioNode },
|
|
4288
4598
|
loop,
|
|
4289
4599
|
trimAfter: initialTrimAfterRef.current,
|
|
4290
4600
|
trimBefore: initialTrimBeforeRef.current,
|
|
@@ -4292,13 +4602,15 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4292
4602
|
playbackRate: initialPlaybackRate.current,
|
|
4293
4603
|
audioStreamIndex,
|
|
4294
4604
|
debugOverlay,
|
|
4605
|
+
debugAudioScheduling,
|
|
4295
4606
|
bufferState: buffer,
|
|
4296
4607
|
isPremounting: initialIsPremounting.current,
|
|
4297
4608
|
isPostmounting: initialIsPostmounting.current,
|
|
4298
4609
|
globalPlaybackRate: initialGlobalPlaybackRate.current,
|
|
4299
4610
|
durationInFrames: videoConfig.durationInFrames,
|
|
4300
4611
|
onVideoFrameCallback: initialOnVideoFrameRef.current ?? null,
|
|
4301
|
-
playing: initialPlaying.current
|
|
4612
|
+
playing: initialPlaying.current,
|
|
4613
|
+
sequenceOffset: initialSequenceOffset.current
|
|
4302
4614
|
});
|
|
4303
4615
|
mediaPlayerRef.current = player;
|
|
4304
4616
|
player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
|
|
@@ -4316,7 +4628,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4316
4628
|
if (action === "fail") {
|
|
4317
4629
|
throw errorToUse;
|
|
4318
4630
|
}
|
|
4319
|
-
|
|
4631
|
+
Internals20.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
4320
4632
|
setShouldFallbackToNativeVideo(true);
|
|
4321
4633
|
};
|
|
4322
4634
|
if (result.type === "unknown-container-format") {
|
|
@@ -4350,7 +4662,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4350
4662
|
if (action === "fail") {
|
|
4351
4663
|
throw errorToUse;
|
|
4352
4664
|
}
|
|
4353
|
-
|
|
4665
|
+
Internals20.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] Failed to initialize MediaPlayer", errorToUse);
|
|
4354
4666
|
setShouldFallbackToNativeVideo(true);
|
|
4355
4667
|
});
|
|
4356
4668
|
} catch (error) {
|
|
@@ -4364,12 +4676,12 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4364
4676
|
if (action === "fail") {
|
|
4365
4677
|
throw errorToUse;
|
|
4366
4678
|
}
|
|
4367
|
-
|
|
4679
|
+
Internals20.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] MediaPlayer initialization failed", errorToUse);
|
|
4368
4680
|
setShouldFallbackToNativeVideo(true);
|
|
4369
4681
|
}
|
|
4370
4682
|
return () => {
|
|
4371
4683
|
if (mediaPlayerRef.current) {
|
|
4372
|
-
|
|
4684
|
+
Internals20.Log.trace({ logLevel, tag: "@remotion/media" }, `[VideoForPreview] Disposing MediaPlayer`);
|
|
4373
4685
|
mediaPlayerRef.current.dispose();
|
|
4374
4686
|
mediaPlayerRef.current = null;
|
|
4375
4687
|
}
|
|
@@ -4380,6 +4692,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4380
4692
|
audioStreamIndex,
|
|
4381
4693
|
buffer,
|
|
4382
4694
|
debugOverlay,
|
|
4695
|
+
debugAudioScheduling,
|
|
4383
4696
|
disallowFallbackToOffthreadVideo,
|
|
4384
4697
|
logLevel,
|
|
4385
4698
|
loop,
|
|
@@ -4390,65 +4703,33 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4390
4703
|
videoConfig.durationInFrames
|
|
4391
4704
|
]);
|
|
4392
4705
|
const classNameValue = useMemo4(() => {
|
|
4393
|
-
return [
|
|
4706
|
+
return [Internals20.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals20.truthy).join(" ");
|
|
4394
4707
|
}, [className]);
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
if (isNextFrameGoingToPlay) {
|
|
4400
|
-
const currentTimeUntilZero = premountFramesRemaining / videoConfig.fps / globalPlaybackRate;
|
|
4401
|
-
mediaPlayer.playAudio(currentTimeRef.current - currentTimeUntilZero);
|
|
4402
|
-
}
|
|
4403
|
-
}, [
|
|
4404
|
-
isNextFrameGoingToPlay,
|
|
4405
|
-
premountFramesRemaining,
|
|
4406
|
-
videoConfig.fps,
|
|
4407
|
-
globalPlaybackRate
|
|
4408
|
-
]);
|
|
4409
|
-
useEffect3(() => {
|
|
4410
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4411
|
-
if (!mediaPlayer)
|
|
4412
|
-
return;
|
|
4413
|
-
if (playing && !isPlayerBuffering && !isNextFrameGoingToPlay) {
|
|
4414
|
-
mediaPlayer.play(currentTimeRef.current);
|
|
4415
|
-
} else {
|
|
4416
|
-
mediaPlayer.pause();
|
|
4417
|
-
}
|
|
4418
|
-
}, [
|
|
4419
|
-
isPlayerBuffering,
|
|
4708
|
+
useCommonEffects({
|
|
4709
|
+
mediaPlayerRef,
|
|
4710
|
+
mediaPlayerReady,
|
|
4711
|
+
currentTimeRef,
|
|
4420
4712
|
playing,
|
|
4713
|
+
isPlayerBuffering,
|
|
4714
|
+
frame,
|
|
4715
|
+
trimBefore,
|
|
4716
|
+
trimAfter,
|
|
4717
|
+
effectiveMuted,
|
|
4718
|
+
userPreferredVolume,
|
|
4719
|
+
playbackRate,
|
|
4720
|
+
globalPlaybackRate,
|
|
4721
|
+
fps: videoConfig.fps,
|
|
4722
|
+
sequenceOffset,
|
|
4723
|
+
loop,
|
|
4724
|
+
debugAudioScheduling,
|
|
4725
|
+
durationInFrames: videoConfig.durationInFrames,
|
|
4726
|
+
isPremounting,
|
|
4727
|
+
isPostmounting,
|
|
4728
|
+
currentTime,
|
|
4421
4729
|
logLevel,
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
useEffect3(() => {
|
|
4426
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4427
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4428
|
-
return;
|
|
4429
|
-
}
|
|
4430
|
-
mediaPlayer.setTrimBefore(trimBefore, currentTimeRef.current);
|
|
4431
|
-
}, [trimBefore, mediaPlayerReady]);
|
|
4432
|
-
useEffect3(() => {
|
|
4433
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4434
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4435
|
-
return;
|
|
4436
|
-
}
|
|
4437
|
-
mediaPlayer.setTrimAfter(trimAfter, currentTimeRef.current);
|
|
4438
|
-
}, [trimAfter, mediaPlayerReady]);
|
|
4439
|
-
useLayoutEffect3(() => {
|
|
4440
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4441
|
-
if (!mediaPlayer || !mediaPlayerReady)
|
|
4442
|
-
return;
|
|
4443
|
-
mediaPlayer.setMuted(effectiveMuted);
|
|
4444
|
-
}, [effectiveMuted, mediaPlayerReady]);
|
|
4445
|
-
useLayoutEffect3(() => {
|
|
4446
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4447
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4448
|
-
return;
|
|
4449
|
-
}
|
|
4450
|
-
mediaPlayer.setVolume(userPreferredVolume);
|
|
4451
|
-
}, [userPreferredVolume, mediaPlayerReady]);
|
|
4730
|
+
sharedAudioContext,
|
|
4731
|
+
label: "VideoForPreview"
|
|
4732
|
+
});
|
|
4452
4733
|
useLayoutEffect3(() => {
|
|
4453
4734
|
const mediaPlayer = mediaPlayerRef.current;
|
|
4454
4735
|
if (!mediaPlayer || !mediaPlayerReady) {
|
|
@@ -4456,55 +4737,6 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4456
4737
|
}
|
|
4457
4738
|
mediaPlayer.setDebugOverlay(debugOverlay);
|
|
4458
4739
|
}, [debugOverlay, mediaPlayerReady]);
|
|
4459
|
-
useLayoutEffect3(() => {
|
|
4460
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4461
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4462
|
-
return;
|
|
4463
|
-
}
|
|
4464
|
-
mediaPlayer.setPlaybackRate(playbackRate, currentTimeRef.current);
|
|
4465
|
-
}, [playbackRate, mediaPlayerReady]);
|
|
4466
|
-
useLayoutEffect3(() => {
|
|
4467
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4468
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4469
|
-
return;
|
|
4470
|
-
}
|
|
4471
|
-
mediaPlayer.setGlobalPlaybackRate(globalPlaybackRate);
|
|
4472
|
-
}, [globalPlaybackRate, mediaPlayerReady]);
|
|
4473
|
-
useLayoutEffect3(() => {
|
|
4474
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4475
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4476
|
-
return;
|
|
4477
|
-
}
|
|
4478
|
-
mediaPlayer.setLoop(loop);
|
|
4479
|
-
}, [loop, mediaPlayerReady]);
|
|
4480
|
-
useLayoutEffect3(() => {
|
|
4481
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4482
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4483
|
-
return;
|
|
4484
|
-
}
|
|
4485
|
-
mediaPlayer.setDurationInFrames(videoConfig.durationInFrames);
|
|
4486
|
-
}, [videoConfig.durationInFrames, mediaPlayerReady]);
|
|
4487
|
-
useLayoutEffect3(() => {
|
|
4488
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4489
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4490
|
-
return;
|
|
4491
|
-
}
|
|
4492
|
-
mediaPlayer.setIsPremounting(isPremounting);
|
|
4493
|
-
}, [isPremounting, mediaPlayerReady]);
|
|
4494
|
-
useLayoutEffect3(() => {
|
|
4495
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4496
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4497
|
-
return;
|
|
4498
|
-
}
|
|
4499
|
-
mediaPlayer.setIsPostmounting(isPostmounting);
|
|
4500
|
-
}, [isPostmounting, mediaPlayerReady]);
|
|
4501
|
-
useLayoutEffect3(() => {
|
|
4502
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4503
|
-
if (!mediaPlayer || !mediaPlayerReady) {
|
|
4504
|
-
return;
|
|
4505
|
-
}
|
|
4506
|
-
mediaPlayer.setFps(videoConfig.fps);
|
|
4507
|
-
}, [videoConfig.fps, mediaPlayerReady]);
|
|
4508
4740
|
useLayoutEffect3(() => {
|
|
4509
4741
|
const mediaPlayer = mediaPlayerRef.current;
|
|
4510
4742
|
if (!mediaPlayer || !mediaPlayerReady) {
|
|
@@ -4512,13 +4744,6 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4512
4744
|
}
|
|
4513
4745
|
mediaPlayer.setVideoFrameCallback(onVideoFrame ?? null);
|
|
4514
4746
|
}, [onVideoFrame, mediaPlayerReady]);
|
|
4515
|
-
useLayoutEffect3(() => {
|
|
4516
|
-
const mediaPlayer = mediaPlayerRef.current;
|
|
4517
|
-
if (!mediaPlayer || !mediaPlayerReady)
|
|
4518
|
-
return;
|
|
4519
|
-
mediaPlayer.seekTo(currentTime).catch(() => {});
|
|
4520
|
-
Internals16.Log.trace({ logLevel, tag: "@remotion/media" }, `[VideoForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
|
|
4521
|
-
}, [currentTime, logLevel, mediaPlayerReady]);
|
|
4522
4747
|
const actualStyle = useMemo4(() => {
|
|
4523
4748
|
return {
|
|
4524
4749
|
...style,
|
|
@@ -4548,66 +4773,21 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4548
4773
|
}
|
|
4549
4774
|
return /* @__PURE__ */ jsx4("canvas", {
|
|
4550
4775
|
ref: canvasRef,
|
|
4551
|
-
width: videoConfig.width,
|
|
4552
|
-
height: videoConfig.height,
|
|
4553
4776
|
style: actualStyle,
|
|
4554
4777
|
className: classNameValue
|
|
4555
4778
|
});
|
|
4556
4779
|
};
|
|
4557
|
-
var videoSchema = {
|
|
4558
|
-
volume: {
|
|
4559
|
-
type: "number",
|
|
4560
|
-
min: 0,
|
|
4561
|
-
max: 20,
|
|
4562
|
-
step: 0.01,
|
|
4563
|
-
default: 1,
|
|
4564
|
-
description: "Volume"
|
|
4565
|
-
},
|
|
4566
|
-
playbackRate: {
|
|
4567
|
-
type: "number",
|
|
4568
|
-
min: 0,
|
|
4569
|
-
step: 0.01,
|
|
4570
|
-
default: 1,
|
|
4571
|
-
description: "Playback Rate"
|
|
4572
|
-
},
|
|
4573
|
-
trimBefore: { type: "number", min: 0, default: 0 },
|
|
4574
|
-
trimAfter: { type: "number", min: 0, default: 0 }
|
|
4575
|
-
};
|
|
4576
4780
|
var VideoForPreview = (props) => {
|
|
4577
|
-
const schemaInput = useMemo4(() => {
|
|
4578
|
-
if (typeof props.volume !== "number") {
|
|
4579
|
-
return null;
|
|
4580
|
-
}
|
|
4581
|
-
return {
|
|
4582
|
-
volume: props.volume,
|
|
4583
|
-
playbackRate: props.playbackRate,
|
|
4584
|
-
trimBefore: props.trimBefore,
|
|
4585
|
-
trimAfter: props.trimAfter,
|
|
4586
|
-
loop: props.loop
|
|
4587
|
-
};
|
|
4588
|
-
}, [
|
|
4589
|
-
props.volume,
|
|
4590
|
-
props.playbackRate,
|
|
4591
|
-
props.trimBefore,
|
|
4592
|
-
props.trimAfter,
|
|
4593
|
-
props.loop
|
|
4594
|
-
]);
|
|
4595
|
-
const { controls, values } = Internals16.useSchema(schemaInput ? videoSchema : null, schemaInput);
|
|
4596
|
-
const volume = schemaInput !== null ? values.volume : props.volume;
|
|
4597
|
-
const playbackRate = schemaInput !== null ? values.playbackRate : props.playbackRate;
|
|
4598
|
-
const trimBefore = schemaInput !== null ? values.trimBefore : props.trimBefore;
|
|
4599
|
-
const trimAfter = schemaInput !== null ? values.trimAfter : props.trimAfter;
|
|
4600
|
-
const effectiveLoop = schemaInput !== null ? values.loop : props.loop;
|
|
4601
4781
|
const frame = useCurrentFrame4();
|
|
4602
4782
|
const videoConfig = useVideoConfig3();
|
|
4603
4783
|
const currentTime = frame / videoConfig.fps;
|
|
4604
4784
|
const showShow = useMemo4(() => {
|
|
4605
4785
|
return getTimeInSeconds({
|
|
4606
4786
|
unloopedTimeInSeconds: currentTime,
|
|
4607
|
-
playbackRate,
|
|
4608
|
-
loop:
|
|
4609
|
-
trimBefore,
|
|
4610
|
-
trimAfter,
|
|
4787
|
+
playbackRate: props.playbackRate,
|
|
4788
|
+
loop: props.loop,
|
|
4789
|
+
trimBefore: props.trimBefore,
|
|
4790
|
+
trimAfter: props.trimAfter,
|
|
4611
4791
|
mediaDurationInSeconds: Infinity,
|
|
4612
4792
|
fps: videoConfig.fps,
|
|
4613
4793
|
ifNoMediaDuration: "infinity",
|
|
@@ -4615,37 +4795,32 @@ var VideoForPreview = (props) => {
|
|
|
4615
4795
|
}) !== null;
|
|
4616
4796
|
}, [
|
|
4617
4797
|
currentTime,
|
|
4618
|
-
|
|
4619
|
-
playbackRate,
|
|
4798
|
+
props.loop,
|
|
4799
|
+
props.playbackRate,
|
|
4620
4800
|
props.src,
|
|
4621
|
-
|
|
4622
|
-
trimBefore,
|
|
4623
|
-
|
|
4801
|
+
videoConfig.fps,
|
|
4802
|
+
props.trimBefore,
|
|
4803
|
+
props.trimAfter
|
|
4624
4804
|
]);
|
|
4625
4805
|
if (!showShow) {
|
|
4626
4806
|
return null;
|
|
4627
4807
|
}
|
|
4628
4808
|
return /* @__PURE__ */ jsx4(VideoForPreviewAssertedShowing, {
|
|
4629
4809
|
...props,
|
|
4630
|
-
|
|
4631
|
-
playbackRate,
|
|
4632
|
-
loop: effectiveLoop,
|
|
4633
|
-
trimBefore,
|
|
4634
|
-
trimAfter,
|
|
4635
|
-
controls
|
|
4810
|
+
controls: props.controls
|
|
4636
4811
|
});
|
|
4637
4812
|
};
|
|
4638
4813
|
|
|
4639
4814
|
// src/video/video-for-rendering.tsx
|
|
4640
4815
|
import {
|
|
4641
|
-
useContext as
|
|
4816
|
+
useContext as useContext6,
|
|
4642
4817
|
useLayoutEffect as useLayoutEffect4,
|
|
4643
4818
|
useMemo as useMemo5,
|
|
4644
4819
|
useRef as useRef3,
|
|
4645
4820
|
useState as useState5
|
|
4646
4821
|
} from "react";
|
|
4647
4822
|
import {
|
|
4648
|
-
Internals as
|
|
4823
|
+
Internals as Internals21,
|
|
4649
4824
|
Loop,
|
|
4650
4825
|
random as random2,
|
|
4651
4826
|
useCurrentFrame as useCurrentFrame5,
|
|
@@ -4682,11 +4857,11 @@ var VideoForRendering = ({
|
|
|
4682
4857
|
throw new TypeError("No `src` was passed to <Video>.");
|
|
4683
4858
|
}
|
|
4684
4859
|
const frame = useCurrentFrame5();
|
|
4685
|
-
const absoluteFrame =
|
|
4860
|
+
const absoluteFrame = Internals21.useTimelinePosition();
|
|
4686
4861
|
const { fps } = useVideoConfig4();
|
|
4687
|
-
const { registerRenderAsset, unregisterRenderAsset } =
|
|
4688
|
-
const startsAt =
|
|
4689
|
-
const sequenceContext =
|
|
4862
|
+
const { registerRenderAsset, unregisterRenderAsset } = useContext6(Internals21.RenderAssetManager);
|
|
4863
|
+
const startsAt = Internals21.useMediaStartsAt();
|
|
4864
|
+
const sequenceContext = useContext6(Internals21.SequenceContext);
|
|
4690
4865
|
const id = useMemo5(() => `media-video-${random2(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
|
|
4691
4866
|
src,
|
|
4692
4867
|
sequenceContext?.cumulatedFrom,
|
|
@@ -4697,8 +4872,8 @@ var VideoForRendering = ({
|
|
|
4697
4872
|
const { delayRender, continueRender, cancelRender: cancelRender3 } = useDelayRender2();
|
|
4698
4873
|
const canvasRef = useRef3(null);
|
|
4699
4874
|
const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState5(false);
|
|
4700
|
-
const audioEnabled =
|
|
4701
|
-
const videoEnabled =
|
|
4875
|
+
const audioEnabled = Internals21.useAudioEnabled();
|
|
4876
|
+
const videoEnabled = Internals21.useVideoEnabled();
|
|
4702
4877
|
const maxCacheSize = useMaxMediaCacheSize(logLevel);
|
|
4703
4878
|
const [error, setError] = useState5(null);
|
|
4704
4879
|
if (error) {
|
|
@@ -4762,7 +4937,7 @@ var VideoForRendering = ({
|
|
|
4762
4937
|
return;
|
|
4763
4938
|
}
|
|
4764
4939
|
if (window.remotion_isMainTab) {
|
|
4765
|
-
|
|
4940
|
+
Internals21.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
|
|
4766
4941
|
}
|
|
4767
4942
|
setReplaceWithOffthreadVideo({
|
|
4768
4943
|
durationInSeconds: mediaDurationInSeconds
|
|
@@ -4817,12 +4992,12 @@ var VideoForRendering = ({
|
|
|
4817
4992
|
frame,
|
|
4818
4993
|
startsAt
|
|
4819
4994
|
});
|
|
4820
|
-
const volume =
|
|
4995
|
+
const volume = Internals21.evaluateVolume({
|
|
4821
4996
|
volume: volumeProp,
|
|
4822
4997
|
frame: volumePropsFrame,
|
|
4823
4998
|
mediaVolume: 1
|
|
4824
4999
|
});
|
|
4825
|
-
|
|
5000
|
+
Internals21.warnAboutTooHighVolume(volume);
|
|
4826
5001
|
if (audio && volume > 0) {
|
|
4827
5002
|
applyVolume(audio.data, volume);
|
|
4828
5003
|
registerRenderAsset({
|
|
@@ -4878,10 +5053,10 @@ var VideoForRendering = ({
|
|
|
4878
5053
|
onError
|
|
4879
5054
|
]);
|
|
4880
5055
|
const classNameValue = useMemo5(() => {
|
|
4881
|
-
return [
|
|
5056
|
+
return [Internals21.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals21.truthy).join(" ");
|
|
4882
5057
|
}, [className]);
|
|
4883
5058
|
if (replaceWithOffthreadVideo) {
|
|
4884
|
-
const fallback = /* @__PURE__ */ jsx5(
|
|
5059
|
+
const fallback = /* @__PURE__ */ jsx5(Internals21.InnerOffthreadVideo, {
|
|
4885
5060
|
src,
|
|
4886
5061
|
playbackRate: playbackRate ?? 1,
|
|
4887
5062
|
muted: muted ?? false,
|
|
@@ -4921,7 +5096,7 @@ var VideoForRendering = ({
|
|
|
4921
5096
|
}
|
|
4922
5097
|
return /* @__PURE__ */ jsx5(Loop, {
|
|
4923
5098
|
layout: "none",
|
|
4924
|
-
durationInFrames:
|
|
5099
|
+
durationInFrames: Internals21.calculateMediaDuration({
|
|
4925
5100
|
trimAfter: trimAfterValue,
|
|
4926
5101
|
mediaDurationInFrames: replaceWithOffthreadVideo.durationInSeconds * fps,
|
|
4927
5102
|
playbackRate,
|
|
@@ -4944,7 +5119,53 @@ var VideoForRendering = ({
|
|
|
4944
5119
|
|
|
4945
5120
|
// src/video/video.tsx
|
|
4946
5121
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
4947
|
-
var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } =
|
|
5122
|
+
var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } = Internals22;
|
|
5123
|
+
var videoSchema = {
|
|
5124
|
+
volume: {
|
|
5125
|
+
type: "number",
|
|
5126
|
+
min: 0,
|
|
5127
|
+
max: 20,
|
|
5128
|
+
step: 0.01,
|
|
5129
|
+
default: 1,
|
|
5130
|
+
description: "Volume"
|
|
5131
|
+
},
|
|
5132
|
+
playbackRate: {
|
|
5133
|
+
type: "number",
|
|
5134
|
+
min: 0.1,
|
|
5135
|
+
step: 0.01,
|
|
5136
|
+
default: 1,
|
|
5137
|
+
description: "Playback Rate"
|
|
5138
|
+
},
|
|
5139
|
+
loop: { type: "boolean", default: false, description: "Loop" },
|
|
5140
|
+
"style.translate": {
|
|
5141
|
+
type: "translate",
|
|
5142
|
+
step: 1,
|
|
5143
|
+
default: "0px 0px",
|
|
5144
|
+
description: "Position"
|
|
5145
|
+
},
|
|
5146
|
+
"style.scale": {
|
|
5147
|
+
type: "number",
|
|
5148
|
+
min: 0.05,
|
|
5149
|
+
max: 100,
|
|
5150
|
+
step: 0.01,
|
|
5151
|
+
default: 1,
|
|
5152
|
+
description: "Scale"
|
|
5153
|
+
},
|
|
5154
|
+
"style.rotate": {
|
|
5155
|
+
type: "rotation",
|
|
5156
|
+
step: 1,
|
|
5157
|
+
default: "0deg",
|
|
5158
|
+
description: "Rotation"
|
|
5159
|
+
},
|
|
5160
|
+
"style.opacity": {
|
|
5161
|
+
type: "number",
|
|
5162
|
+
min: 0,
|
|
5163
|
+
max: 1,
|
|
5164
|
+
step: 0.01,
|
|
5165
|
+
default: 1,
|
|
5166
|
+
description: "Opacity"
|
|
5167
|
+
}
|
|
5168
|
+
};
|
|
4948
5169
|
var InnerVideo = ({
|
|
4949
5170
|
src,
|
|
4950
5171
|
audioStreamIndex,
|
|
@@ -4968,8 +5189,10 @@ var InnerVideo = ({
|
|
|
4968
5189
|
toneFrequency,
|
|
4969
5190
|
showInTimeline,
|
|
4970
5191
|
debugOverlay,
|
|
5192
|
+
debugAudioScheduling,
|
|
4971
5193
|
headless,
|
|
4972
|
-
onError
|
|
5194
|
+
onError,
|
|
5195
|
+
controls
|
|
4973
5196
|
}) => {
|
|
4974
5197
|
const environment = useRemotionEnvironment4();
|
|
4975
5198
|
if (typeof src !== "string") {
|
|
@@ -5034,11 +5257,13 @@ var InnerVideo = ({
|
|
|
5034
5257
|
disallowFallbackToOffthreadVideo,
|
|
5035
5258
|
fallbackOffthreadVideoProps,
|
|
5036
5259
|
debugOverlay: debugOverlay ?? false,
|
|
5260
|
+
debugAudioScheduling: debugAudioScheduling ?? false,
|
|
5037
5261
|
headless: headless ?? false,
|
|
5038
|
-
onError
|
|
5262
|
+
onError,
|
|
5263
|
+
controls
|
|
5039
5264
|
});
|
|
5040
5265
|
};
|
|
5041
|
-
var
|
|
5266
|
+
var VideoInner = ({
|
|
5042
5267
|
src,
|
|
5043
5268
|
audioStreamIndex,
|
|
5044
5269
|
className,
|
|
@@ -5061,10 +5286,12 @@ var Video = ({
|
|
|
5061
5286
|
stack,
|
|
5062
5287
|
toneFrequency,
|
|
5063
5288
|
debugOverlay,
|
|
5289
|
+
debugAudioScheduling,
|
|
5064
5290
|
headless,
|
|
5065
|
-
onError
|
|
5291
|
+
onError,
|
|
5292
|
+
controls
|
|
5066
5293
|
}) => {
|
|
5067
|
-
const fallbackLogLevel =
|
|
5294
|
+
const fallbackLogLevel = Internals22.useLogLevel();
|
|
5068
5295
|
return /* @__PURE__ */ jsx6(InnerVideo, {
|
|
5069
5296
|
audioStreamIndex: audioStreamIndex ?? 0,
|
|
5070
5297
|
className,
|
|
@@ -5088,11 +5315,14 @@ var Video = ({
|
|
|
5088
5315
|
toneFrequency: toneFrequency ?? 1,
|
|
5089
5316
|
stack,
|
|
5090
5317
|
debugOverlay: debugOverlay ?? false,
|
|
5318
|
+
debugAudioScheduling: debugAudioScheduling ?? false,
|
|
5091
5319
|
headless: headless ?? false,
|
|
5092
|
-
onError
|
|
5320
|
+
onError,
|
|
5321
|
+
controls
|
|
5093
5322
|
});
|
|
5094
5323
|
};
|
|
5095
|
-
|
|
5324
|
+
var Video = Internals22.wrapInSchema(VideoInner, videoSchema);
|
|
5325
|
+
Internals22.addSequenceStackTraces(Video);
|
|
5096
5326
|
|
|
5097
5327
|
// src/index.ts
|
|
5098
5328
|
var experimental_Audio = Audio;
|