@remotion/media 4.0.370 → 4.0.372
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/allow-wait.d.ts +6 -0
- package/dist/audio/allow-wait.js +15 -0
- package/dist/audio/audio-for-preview.js +2 -2
- package/dist/audio/audio-preview-iterator.d.ts +3 -3
- package/dist/audio/audio-preview-iterator.js +13 -13
- package/dist/audio-extraction/extract-audio.js +2 -0
- package/dist/audio-iterator-manager.d.ts +5 -4
- package/dist/audio-iterator-manager.js +66 -42
- package/dist/convert-audiodata/combine-audiodata.d.ts +1 -1
- package/dist/convert-audiodata/combine-audiodata.js +5 -1
- package/dist/convert-audiodata/convert-audiodata.d.ts +5 -1
- package/dist/convert-audiodata/convert-audiodata.js +29 -8
- package/dist/debug-overlay/preview-overlay.js +1 -1
- package/dist/esm/index.mjs +164 -94
- package/dist/media-player.js +1 -0
- package/dist/video/props.d.ts +0 -1
- package/dist/video/video-for-rendering.js +2 -2
- package/package.json +4 -4
- package/dist/audio/audio-iterator.d.ts +0 -11
- package/dist/audio/audio-iterator.js +0 -24
- package/dist/video/media-player.d.ts +0 -98
- package/dist/video/media-player.js +0 -532
- package/dist/video/timeout-utils.d.ts +0 -5
- package/dist/video/timeout-utils.js +0 -24
package/dist/esm/index.mjs
CHANGED
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
import { Internals as Internals14, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
|
|
3
3
|
|
|
4
4
|
// src/audio/audio-for-preview.tsx
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useContext as useContext2,
|
|
7
|
+
useEffect as useEffect2,
|
|
8
|
+
useLayoutEffect,
|
|
9
|
+
useMemo as useMemo2,
|
|
10
|
+
useRef,
|
|
11
|
+
useState as useState2
|
|
12
|
+
} from "react";
|
|
6
13
|
import {
|
|
7
14
|
Internals as Internals6,
|
|
8
15
|
Audio as RemotionAudio,
|
|
@@ -48,13 +55,30 @@ import { ALL_FORMATS, Input, UrlSource } from "mediabunny";
|
|
|
48
55
|
import { Internals as Internals3 } from "remotion";
|
|
49
56
|
|
|
50
57
|
// src/audio-iterator-manager.ts
|
|
51
|
-
import { AudioBufferSink } from "mediabunny";
|
|
58
|
+
import { AudioBufferSink, InputDisposedError } from "mediabunny";
|
|
52
59
|
|
|
53
60
|
// src/helpers/round-to-4-digits.ts
|
|
54
61
|
var roundTo4Digits = (timestamp) => {
|
|
55
62
|
return Math.round(timestamp * 1000) / 1000;
|
|
56
63
|
};
|
|
57
64
|
|
|
65
|
+
// src/audio/allow-wait.ts
|
|
66
|
+
var allowWaitRoutine = async (next, waitFn) => {
|
|
67
|
+
const result = await Promise.race([
|
|
68
|
+
next,
|
|
69
|
+
new Promise((resolve) => {
|
|
70
|
+
Promise.resolve().then(() => resolve());
|
|
71
|
+
})
|
|
72
|
+
]);
|
|
73
|
+
if (!result) {
|
|
74
|
+
const unblock = waitFn.waitCallback();
|
|
75
|
+
const newRes = await next;
|
|
76
|
+
unblock();
|
|
77
|
+
return newRes;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
};
|
|
81
|
+
|
|
58
82
|
// src/audio/audio-preview-iterator.ts
|
|
59
83
|
var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
60
84
|
let destroyed = false;
|
|
@@ -71,7 +95,7 @@ var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
|
71
95
|
let iteratorEnded = false;
|
|
72
96
|
const getNextOrNullIfNotAvailable = async (allowWait) => {
|
|
73
97
|
const next = iterator.next();
|
|
74
|
-
const result = allowWait ? await next : await Promise.race([
|
|
98
|
+
const result = allowWait ? await allowWaitRoutine(next, allowWait) : await Promise.race([
|
|
75
99
|
next,
|
|
76
100
|
new Promise((resolve) => {
|
|
77
101
|
Promise.resolve().then(() => resolve());
|
|
@@ -101,7 +125,7 @@ var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
|
101
125
|
buffer: result.value ?? null
|
|
102
126
|
};
|
|
103
127
|
};
|
|
104
|
-
const tryToSatisfySeek = async (time, allowWait) => {
|
|
128
|
+
const tryToSatisfySeek = async (time, allowWait, onBufferScheduled) => {
|
|
105
129
|
if (lastReturnedBuffer) {
|
|
106
130
|
const bufferTimestamp = roundTo4Digits(lastReturnedBuffer.timestamp);
|
|
107
131
|
const bufferEndTimestamp = roundTo4Digits(lastReturnedBuffer.timestamp + lastReturnedBuffer.duration);
|
|
@@ -112,19 +136,20 @@ var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
|
112
136
|
};
|
|
113
137
|
}
|
|
114
138
|
if (roundTo4Digits(time) <= bufferEndTimestamp) {
|
|
139
|
+
onBufferScheduled(lastReturnedBuffer);
|
|
115
140
|
return {
|
|
116
|
-
type: "satisfied"
|
|
117
|
-
buffers: [lastReturnedBuffer]
|
|
141
|
+
type: "satisfied"
|
|
118
142
|
};
|
|
119
143
|
}
|
|
120
144
|
}
|
|
121
145
|
if (iteratorEnded) {
|
|
146
|
+
if (lastReturnedBuffer) {
|
|
147
|
+
onBufferScheduled(lastReturnedBuffer);
|
|
148
|
+
}
|
|
122
149
|
return {
|
|
123
|
-
type: "satisfied"
|
|
124
|
-
buffers: lastReturnedBuffer ? [lastReturnedBuffer] : []
|
|
150
|
+
type: "satisfied"
|
|
125
151
|
};
|
|
126
152
|
}
|
|
127
|
-
const toBeReturned = [];
|
|
128
153
|
while (true) {
|
|
129
154
|
const buffer = await getNextOrNullIfNotAvailable(allowWait);
|
|
130
155
|
if (buffer.type === "need-to-wait-for-it") {
|
|
@@ -136,21 +161,23 @@ var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
|
136
161
|
if (buffer.type === "got-buffer-or-end") {
|
|
137
162
|
if (buffer.buffer === null) {
|
|
138
163
|
iteratorEnded = true;
|
|
164
|
+
if (lastReturnedBuffer) {
|
|
165
|
+
onBufferScheduled(lastReturnedBuffer);
|
|
166
|
+
}
|
|
139
167
|
return {
|
|
140
|
-
type: "satisfied"
|
|
141
|
-
buffers: lastReturnedBuffer ? [lastReturnedBuffer] : []
|
|
168
|
+
type: "satisfied"
|
|
142
169
|
};
|
|
143
170
|
}
|
|
144
171
|
const bufferTimestamp = roundTo4Digits(buffer.buffer.timestamp);
|
|
145
172
|
const bufferEndTimestamp = roundTo4Digits(buffer.buffer.timestamp + buffer.buffer.duration);
|
|
146
173
|
const timestamp = roundTo4Digits(time);
|
|
147
174
|
if (bufferTimestamp <= timestamp && bufferEndTimestamp > timestamp) {
|
|
175
|
+
onBufferScheduled(buffer.buffer);
|
|
148
176
|
return {
|
|
149
|
-
type: "satisfied"
|
|
150
|
-
buffers: [...toBeReturned, buffer.buffer]
|
|
177
|
+
type: "satisfied"
|
|
151
178
|
};
|
|
152
179
|
}
|
|
153
|
-
|
|
180
|
+
onBufferScheduled(buffer.buffer);
|
|
154
181
|
continue;
|
|
155
182
|
}
|
|
156
183
|
throw new Error("Unreachable");
|
|
@@ -211,13 +238,9 @@ var makeAudioIterator = (audioSink, startFromSecond) => {
|
|
|
211
238
|
audioChunksForAfterResuming.length = 0;
|
|
212
239
|
return chunks;
|
|
213
240
|
},
|
|
214
|
-
getQueuedPeriod: (
|
|
241
|
+
getQueuedPeriod: () => {
|
|
215
242
|
let until = -Infinity;
|
|
216
243
|
let from = Infinity;
|
|
217
|
-
for (const buffer of pendingBuffers) {
|
|
218
|
-
until = Math.max(until, buffer.timestamp + buffer.duration);
|
|
219
|
-
from = Math.min(from, buffer.timestamp);
|
|
220
|
-
}
|
|
221
244
|
for (const node of queuedAudioNodes) {
|
|
222
245
|
until = Math.max(until, node.timestamp + node.buffer.duration);
|
|
223
246
|
from = Math.min(from, node.timestamp);
|
|
@@ -314,28 +337,36 @@ var audioIteratorManager = ({
|
|
|
314
337
|
const iterator = makeAudioIterator(audioSink, startFromSecond);
|
|
315
338
|
audioIteratorsCreated++;
|
|
316
339
|
audioBufferIterator = iterator;
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
340
|
+
try {
|
|
341
|
+
for (let i = 0;i < 3; i++) {
|
|
342
|
+
const result = await iterator.getNext();
|
|
343
|
+
if (iterator.isDestroyed()) {
|
|
344
|
+
delayHandle.unblock();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (nonce.isStale()) {
|
|
348
|
+
delayHandle.unblock();
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (!result.value) {
|
|
352
|
+
delayHandle.unblock();
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
onAudioChunk({
|
|
356
|
+
getIsPlaying,
|
|
357
|
+
buffer: result.value,
|
|
358
|
+
playbackRate,
|
|
359
|
+
scheduleAudioNode
|
|
360
|
+
});
|
|
326
361
|
}
|
|
327
|
-
|
|
328
|
-
|
|
362
|
+
} catch (e) {
|
|
363
|
+
if (e instanceof InputDisposedError) {
|
|
329
364
|
return;
|
|
330
365
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
playbackRate,
|
|
335
|
-
scheduleAudioNode
|
|
336
|
-
});
|
|
366
|
+
throw e;
|
|
367
|
+
} finally {
|
|
368
|
+
delayHandle.unblock();
|
|
337
369
|
}
|
|
338
|
-
delayHandle.unblock();
|
|
339
370
|
};
|
|
340
371
|
const pausePlayback = () => {
|
|
341
372
|
if (!audioBufferIterator) {
|
|
@@ -349,7 +380,8 @@ var audioIteratorManager = ({
|
|
|
349
380
|
fps,
|
|
350
381
|
playbackRate,
|
|
351
382
|
getIsPlaying,
|
|
352
|
-
scheduleAudioNode
|
|
383
|
+
scheduleAudioNode,
|
|
384
|
+
bufferState
|
|
353
385
|
}) => {
|
|
354
386
|
if (!audioBufferIterator) {
|
|
355
387
|
await startAudioIterator({
|
|
@@ -361,10 +393,18 @@ var audioIteratorManager = ({
|
|
|
361
393
|
});
|
|
362
394
|
return;
|
|
363
395
|
}
|
|
364
|
-
const currentTimeIsAlreadyQueued = isAlreadyQueued(newTime, audioBufferIterator.getQueuedPeriod(
|
|
365
|
-
const toBeScheduled = [];
|
|
396
|
+
const currentTimeIsAlreadyQueued = isAlreadyQueued(newTime, audioBufferIterator.getQueuedPeriod());
|
|
366
397
|
if (!currentTimeIsAlreadyQueued) {
|
|
367
|
-
const audioSatisfyResult = await audioBufferIterator.tryToSatisfySeek(newTime,
|
|
398
|
+
const audioSatisfyResult = await audioBufferIterator.tryToSatisfySeek(newTime, null, (buffer) => {
|
|
399
|
+
if (!nonce.isStale()) {
|
|
400
|
+
onAudioChunk({
|
|
401
|
+
getIsPlaying,
|
|
402
|
+
buffer,
|
|
403
|
+
playbackRate,
|
|
404
|
+
scheduleAudioNode
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
});
|
|
368
408
|
if (nonce.isStale()) {
|
|
369
409
|
return;
|
|
370
410
|
}
|
|
@@ -378,12 +418,28 @@ var audioIteratorManager = ({
|
|
|
378
418
|
});
|
|
379
419
|
return;
|
|
380
420
|
}
|
|
381
|
-
toBeScheduled.push(...audioSatisfyResult.buffers);
|
|
382
421
|
}
|
|
383
|
-
const nextTime = newTime + 1 / fps *
|
|
384
|
-
const nextIsAlreadyQueued = isAlreadyQueued(nextTime, audioBufferIterator.getQueuedPeriod(
|
|
422
|
+
const nextTime = newTime + 1 / fps * Math.max(1, playbackRate) * 3;
|
|
423
|
+
const nextIsAlreadyQueued = isAlreadyQueued(nextTime, audioBufferIterator.getQueuedPeriod());
|
|
385
424
|
if (!nextIsAlreadyQueued) {
|
|
386
|
-
const audioSatisfyResult = await audioBufferIterator.tryToSatisfySeek(nextTime,
|
|
425
|
+
const audioSatisfyResult = await audioBufferIterator.tryToSatisfySeek(nextTime, {
|
|
426
|
+
type: "allow-wait",
|
|
427
|
+
waitCallback: () => {
|
|
428
|
+
const handle = bufferState.delayPlayback();
|
|
429
|
+
return () => {
|
|
430
|
+
handle.unblock();
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
}, (buffer) => {
|
|
434
|
+
if (!nonce.isStale()) {
|
|
435
|
+
onAudioChunk({
|
|
436
|
+
getIsPlaying,
|
|
437
|
+
buffer,
|
|
438
|
+
playbackRate,
|
|
439
|
+
scheduleAudioNode
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
});
|
|
387
443
|
if (nonce.isStale()) {
|
|
388
444
|
return;
|
|
389
445
|
}
|
|
@@ -395,17 +451,7 @@ var audioIteratorManager = ({
|
|
|
395
451
|
getIsPlaying,
|
|
396
452
|
scheduleAudioNode
|
|
397
453
|
});
|
|
398
|
-
return;
|
|
399
454
|
}
|
|
400
|
-
toBeScheduled.push(...audioSatisfyResult.buffers);
|
|
401
|
-
}
|
|
402
|
-
for (const buffer of toBeScheduled) {
|
|
403
|
-
onAudioChunk({
|
|
404
|
-
getIsPlaying,
|
|
405
|
-
buffer,
|
|
406
|
-
playbackRate,
|
|
407
|
-
scheduleAudioNode
|
|
408
|
-
});
|
|
409
455
|
}
|
|
410
456
|
};
|
|
411
457
|
const resumeScheduledAudioChunks = ({
|
|
@@ -476,7 +522,7 @@ var drawPreviewOverlay = ({
|
|
|
476
522
|
`Audio time: ${(audioTime - audioSyncAnchor).toFixed(3)}s`
|
|
477
523
|
];
|
|
478
524
|
if (audioIteratorManager2) {
|
|
479
|
-
const queuedPeriod = audioIteratorManager2.getAudioBufferIterator()?.getQueuedPeriod(
|
|
525
|
+
const queuedPeriod = audioIteratorManager2.getAudioBufferIterator()?.getQueuedPeriod();
|
|
480
526
|
const numberOfChunksAfterResuming = audioIteratorManager2?.getAudioBufferIterator()?.getNumberOfChunksAfterResuming();
|
|
481
527
|
if (queuedPeriod) {
|
|
482
528
|
lines.push(`Audio queued until: ${(queuedPeriod.until - (audioTime - audioSyncAnchor)).toFixed(3)}s`);
|
|
@@ -963,7 +1009,8 @@ class MediaPlayer {
|
|
|
963
1009
|
fps: this.fps,
|
|
964
1010
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
965
1011
|
getIsPlaying: () => this.playing,
|
|
966
|
-
scheduleAudioNode: this.scheduleAudioNode
|
|
1012
|
+
scheduleAudioNode: this.scheduleAudioNode,
|
|
1013
|
+
bufferState: this.bufferState
|
|
967
1014
|
});
|
|
968
1015
|
}
|
|
969
1016
|
async play(time) {
|
|
@@ -1478,7 +1525,7 @@ var AudioForPreviewAssertedShowing = ({
|
|
|
1478
1525
|
audioPlayer.pause();
|
|
1479
1526
|
}
|
|
1480
1527
|
}, [isPlayerBuffering, logLevel, playing]);
|
|
1481
|
-
|
|
1528
|
+
useLayoutEffect(() => {
|
|
1482
1529
|
const audioPlayer = mediaPlayerRef.current;
|
|
1483
1530
|
if (!audioPlayer || !mediaPlayerReady)
|
|
1484
1531
|
return;
|
|
@@ -1643,7 +1690,7 @@ var AudioForPreview = ({
|
|
|
1643
1690
|
};
|
|
1644
1691
|
|
|
1645
1692
|
// src/audio/audio-for-rendering.tsx
|
|
1646
|
-
import { useContext as useContext3, useLayoutEffect, useMemo as useMemo3, useState as useState3 } from "react";
|
|
1693
|
+
import { useContext as useContext3, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useState as useState3 } from "react";
|
|
1647
1694
|
import {
|
|
1648
1695
|
cancelRender as cancelRender2,
|
|
1649
1696
|
Html5Audio,
|
|
@@ -2681,33 +2728,28 @@ var getMaxVideoCacheSize = (logLevel) => {
|
|
|
2681
2728
|
return cachedMaxCacheSize;
|
|
2682
2729
|
};
|
|
2683
2730
|
|
|
2684
|
-
// src/convert-audiodata/
|
|
2685
|
-
var
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
numberOfFrames += audioData.numberOfFrames;
|
|
2731
|
+
// src/convert-audiodata/convert-audiodata.ts
|
|
2732
|
+
var FORMAT = "s16";
|
|
2733
|
+
var fixFloatingPoint2 = (value) => {
|
|
2734
|
+
if (value % 1 < 0.0000001) {
|
|
2735
|
+
return Math.floor(value);
|
|
2690
2736
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
for (const audioData of audioDataArray) {
|
|
2694
|
-
arr.set(audioData.data, offset);
|
|
2695
|
-
offset += audioData.data.length;
|
|
2737
|
+
if (value % 1 > 0.9999999) {
|
|
2738
|
+
return Math.ceil(value);
|
|
2696
2739
|
}
|
|
2697
|
-
return
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2740
|
+
return value;
|
|
2741
|
+
};
|
|
2742
|
+
var ceilButNotIfFloatingPointIssue = (value) => {
|
|
2743
|
+
const fixed = fixFloatingPoint2(value);
|
|
2744
|
+
return Math.ceil(fixed);
|
|
2702
2745
|
};
|
|
2703
|
-
|
|
2704
|
-
// src/convert-audiodata/convert-audiodata.ts
|
|
2705
|
-
var FORMAT = "s16";
|
|
2706
2746
|
var convertAudioData = ({
|
|
2707
2747
|
audioData,
|
|
2708
2748
|
trimStartInSeconds,
|
|
2709
2749
|
trimEndInSeconds,
|
|
2710
|
-
playbackRate
|
|
2750
|
+
playbackRate,
|
|
2751
|
+
audioDataTimestamp,
|
|
2752
|
+
isLast
|
|
2711
2753
|
}) => {
|
|
2712
2754
|
const {
|
|
2713
2755
|
numberOfChannels: srcNumberOfChannels,
|
|
@@ -2715,10 +2757,10 @@ var convertAudioData = ({
|
|
|
2715
2757
|
numberOfFrames
|
|
2716
2758
|
} = audioData;
|
|
2717
2759
|
const ratio = currentSampleRate / TARGET_SAMPLE_RATE;
|
|
2718
|
-
const frameOffset = Math.floor(trimStartInSeconds * audioData.sampleRate);
|
|
2719
|
-
const unroundedFrameCount = numberOfFrames -
|
|
2720
|
-
const frameCount = Math.
|
|
2721
|
-
const newNumberOfFrames = Math.
|
|
2760
|
+
const frameOffset = Math.floor(fixFloatingPoint2(trimStartInSeconds * audioData.sampleRate));
|
|
2761
|
+
const unroundedFrameCount = numberOfFrames - trimEndInSeconds * audioData.sampleRate - frameOffset;
|
|
2762
|
+
const frameCount = isLast ? ceilButNotIfFloatingPointIssue(unroundedFrameCount) : Math.round(unroundedFrameCount);
|
|
2763
|
+
const newNumberOfFrames = isLast ? ceilButNotIfFloatingPointIssue(unroundedFrameCount / ratio / playbackRate) : Math.round(unroundedFrameCount / ratio / playbackRate);
|
|
2722
2764
|
if (newNumberOfFrames === 0) {
|
|
2723
2765
|
throw new Error("Cannot resample - the given sample rate would result in less than 1 sample");
|
|
2724
2766
|
}
|
|
@@ -2731,11 +2773,13 @@ var convertAudioData = ({
|
|
|
2731
2773
|
});
|
|
2732
2774
|
const data = new Int16Array(newNumberOfFrames * TARGET_NUMBER_OF_CHANNELS);
|
|
2733
2775
|
const chunkSize = frameCount / newNumberOfFrames;
|
|
2776
|
+
const timestampOffsetMicroseconds = frameOffset / audioData.sampleRate * 1e6;
|
|
2734
2777
|
if (newNumberOfFrames === frameCount && TARGET_NUMBER_OF_CHANNELS === srcNumberOfChannels && playbackRate === 1) {
|
|
2735
2778
|
return {
|
|
2736
2779
|
data: srcChannels,
|
|
2737
2780
|
numberOfFrames: newNumberOfFrames,
|
|
2738
|
-
timestamp:
|
|
2781
|
+
timestamp: audioDataTimestamp * 1e6 + fixFloatingPoint2(timestampOffsetMicroseconds),
|
|
2782
|
+
durationInMicroSeconds: fixFloatingPoint2(newNumberOfFrames / TARGET_SAMPLE_RATE * 1e6)
|
|
2739
2783
|
};
|
|
2740
2784
|
}
|
|
2741
2785
|
resampleAudioData({
|
|
@@ -2748,11 +2792,35 @@ var convertAudioData = ({
|
|
|
2748
2792
|
const newAudioData = {
|
|
2749
2793
|
data,
|
|
2750
2794
|
numberOfFrames: newNumberOfFrames,
|
|
2751
|
-
timestamp:
|
|
2795
|
+
timestamp: audioDataTimestamp * 1e6 + fixFloatingPoint2(timestampOffsetMicroseconds),
|
|
2796
|
+
durationInMicroSeconds: fixFloatingPoint2(newNumberOfFrames / TARGET_SAMPLE_RATE * 1e6)
|
|
2752
2797
|
};
|
|
2753
2798
|
return newAudioData;
|
|
2754
2799
|
};
|
|
2755
2800
|
|
|
2801
|
+
// src/convert-audiodata/combine-audiodata.ts
|
|
2802
|
+
var combineAudioDataAndClosePrevious = (audioDataArray) => {
|
|
2803
|
+
let numberOfFrames = 0;
|
|
2804
|
+
let durationInMicroSeconds = 0;
|
|
2805
|
+
const { timestamp } = audioDataArray[0];
|
|
2806
|
+
for (const audioData of audioDataArray) {
|
|
2807
|
+
numberOfFrames += audioData.numberOfFrames;
|
|
2808
|
+
durationInMicroSeconds += audioData.durationInMicroSeconds;
|
|
2809
|
+
}
|
|
2810
|
+
const arr = new Int16Array(numberOfFrames * TARGET_NUMBER_OF_CHANNELS);
|
|
2811
|
+
let offset = 0;
|
|
2812
|
+
for (const audioData of audioDataArray) {
|
|
2813
|
+
arr.set(audioData.data, offset);
|
|
2814
|
+
offset += audioData.data.length;
|
|
2815
|
+
}
|
|
2816
|
+
return {
|
|
2817
|
+
data: arr,
|
|
2818
|
+
numberOfFrames,
|
|
2819
|
+
timestamp: fixFloatingPoint2(timestamp),
|
|
2820
|
+
durationInMicroSeconds: fixFloatingPoint2(durationInMicroSeconds)
|
|
2821
|
+
};
|
|
2822
|
+
};
|
|
2823
|
+
|
|
2756
2824
|
// src/get-sink.ts
|
|
2757
2825
|
import { Internals as Internals12 } from "remotion";
|
|
2758
2826
|
var sinkPromises = {};
|
|
@@ -2852,7 +2920,9 @@ var extractAudioInternal = async ({
|
|
|
2852
2920
|
audioData: audioDataRaw,
|
|
2853
2921
|
trimStartInSeconds,
|
|
2854
2922
|
trimEndInSeconds,
|
|
2855
|
-
playbackRate
|
|
2923
|
+
playbackRate,
|
|
2924
|
+
audioDataTimestamp: sample.timestamp,
|
|
2925
|
+
isLast: isLastSample
|
|
2856
2926
|
});
|
|
2857
2927
|
audioDataRaw.close();
|
|
2858
2928
|
if (audioData.numberOfFrames === 0) {
|
|
@@ -3273,7 +3343,7 @@ var AudioForRendering = ({
|
|
|
3273
3343
|
sequenceContext?.relativeFrom,
|
|
3274
3344
|
sequenceContext?.durationInFrames
|
|
3275
3345
|
]);
|
|
3276
|
-
|
|
3346
|
+
useLayoutEffect2(() => {
|
|
3277
3347
|
const timestamp = frame / fps;
|
|
3278
3348
|
const durationInSeconds = 1 / fps;
|
|
3279
3349
|
if (replaceWithHtml5Audio) {
|
|
@@ -3458,7 +3528,7 @@ import { Internals as Internals17, useRemotionEnvironment as useRemotionEnvironm
|
|
|
3458
3528
|
import {
|
|
3459
3529
|
useContext as useContext4,
|
|
3460
3530
|
useEffect as useEffect3,
|
|
3461
|
-
useLayoutEffect as
|
|
3531
|
+
useLayoutEffect as useLayoutEffect3,
|
|
3462
3532
|
useMemo as useMemo4,
|
|
3463
3533
|
useRef as useRef2,
|
|
3464
3534
|
useState as useState4
|
|
@@ -3679,7 +3749,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
3679
3749
|
mediaPlayer.pause();
|
|
3680
3750
|
}
|
|
3681
3751
|
}, [isPlayerBuffering, playing, logLevel, mediaPlayerReady]);
|
|
3682
|
-
|
|
3752
|
+
useLayoutEffect3(() => {
|
|
3683
3753
|
const mediaPlayer = mediaPlayerRef.current;
|
|
3684
3754
|
if (!mediaPlayer || !mediaPlayerReady)
|
|
3685
3755
|
return;
|
|
@@ -3838,7 +3908,7 @@ var VideoForPreview = (props) => {
|
|
|
3838
3908
|
// src/video/video-for-rendering.tsx
|
|
3839
3909
|
import {
|
|
3840
3910
|
useContext as useContext5,
|
|
3841
|
-
useLayoutEffect as
|
|
3911
|
+
useLayoutEffect as useLayoutEffect4,
|
|
3842
3912
|
useMemo as useMemo5,
|
|
3843
3913
|
useRef as useRef3,
|
|
3844
3914
|
useState as useState5
|
|
@@ -3897,7 +3967,7 @@ var VideoForRendering = ({
|
|
|
3897
3967
|
const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState5(false);
|
|
3898
3968
|
const audioEnabled = Internals16.useAudioEnabled();
|
|
3899
3969
|
const videoEnabled = Internals16.useVideoEnabled();
|
|
3900
|
-
|
|
3970
|
+
useLayoutEffect4(() => {
|
|
3901
3971
|
if (!canvasRef.current) {
|
|
3902
3972
|
return;
|
|
3903
3973
|
}
|
|
@@ -4091,15 +4161,15 @@ var VideoForRendering = ({
|
|
|
4091
4161
|
volume: volumeProp,
|
|
4092
4162
|
id,
|
|
4093
4163
|
onError: fallbackOffthreadVideoProps?.onError,
|
|
4094
|
-
toneFrequency
|
|
4164
|
+
toneFrequency,
|
|
4095
4165
|
showInTimeline: false,
|
|
4096
4166
|
crossOrigin: undefined,
|
|
4097
4167
|
onAutoPlayError: () => {
|
|
4098
4168
|
return;
|
|
4099
4169
|
},
|
|
4100
4170
|
pauseWhenBuffering: false,
|
|
4101
|
-
trimAfter:
|
|
4102
|
-
trimBefore:
|
|
4171
|
+
trimAfter: trimAfterValue,
|
|
4172
|
+
trimBefore: trimBeforeValue,
|
|
4103
4173
|
useWebAudioApi: false,
|
|
4104
4174
|
startFrom: undefined,
|
|
4105
4175
|
endAt: undefined,
|
package/dist/media-player.js
CHANGED
package/dist/video/props.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { LogLevel, LoopVolumeCurveBehavior, OnVideoFrame, VolumeProp } from 'remotion';
|
|
2
2
|
export type FallbackOffthreadVideoProps = {
|
|
3
3
|
acceptableTimeShiftInSeconds?: number;
|
|
4
|
-
toneFrequency?: number;
|
|
5
4
|
transparent?: boolean;
|
|
6
5
|
toneMapped?: boolean;
|
|
7
6
|
onError?: (err: Error) => void;
|
|
@@ -213,9 +213,9 @@ export const VideoForRendering = ({ volume: volumeProp, playbackRate, src, muted
|
|
|
213
213
|
.join(' ');
|
|
214
214
|
}, [className]);
|
|
215
215
|
if (replaceWithOffthreadVideo) {
|
|
216
|
-
const fallback = (_jsx(Internals.InnerOffthreadVideo, { src: src, playbackRate: playbackRate ?? 1, muted: muted ?? false, acceptableTimeShiftInSeconds: fallbackOffthreadVideoProps?.acceptableTimeShiftInSeconds, loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? 'repeat', delayRenderRetries: delayRenderRetries ?? undefined, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined, style: style, allowAmplificationDuringRender: true, transparent: fallbackOffthreadVideoProps?.transparent ?? true, toneMapped: fallbackOffthreadVideoProps?.toneMapped ?? true, audioStreamIndex: audioStreamIndex ?? 0, name: name, className: className, onVideoFrame: onVideoFrame, volume: volumeProp, id: id, onError: fallbackOffthreadVideoProps?.onError, toneFrequency:
|
|
216
|
+
const fallback = (_jsx(Internals.InnerOffthreadVideo, { src: src, playbackRate: playbackRate ?? 1, muted: muted ?? false, acceptableTimeShiftInSeconds: fallbackOffthreadVideoProps?.acceptableTimeShiftInSeconds, loopVolumeCurveBehavior: loopVolumeCurveBehavior ?? 'repeat', delayRenderRetries: delayRenderRetries ?? undefined, delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined, style: style, allowAmplificationDuringRender: true, transparent: fallbackOffthreadVideoProps?.transparent ?? true, toneMapped: fallbackOffthreadVideoProps?.toneMapped ?? true, audioStreamIndex: audioStreamIndex ?? 0, name: name, className: className, onVideoFrame: onVideoFrame, volume: volumeProp, id: id, onError: fallbackOffthreadVideoProps?.onError, toneFrequency: toneFrequency,
|
|
217
217
|
// these shouldn't matter during rendering / should not appear at all
|
|
218
|
-
showInTimeline: false, crossOrigin: undefined, onAutoPlayError: () => undefined, pauseWhenBuffering: false, trimAfter:
|
|
218
|
+
showInTimeline: false, crossOrigin: undefined, onAutoPlayError: () => undefined, pauseWhenBuffering: false, trimAfter: trimAfterValue, trimBefore: trimBeforeValue, useWebAudioApi: false, startFrom: undefined, endAt: undefined, stack: stack, _remotionInternalNativeLoopPassed: false }));
|
|
219
219
|
if (loop) {
|
|
220
220
|
if (!replaceWithOffthreadVideo.durationInSeconds) {
|
|
221
221
|
cancelRender(new Error(`Cannot render video ${src}: @remotion/media was unable to render, and fell back to <OffthreadVideo>. Also, "loop" was set, but <OffthreadVideo> does not support looping and @remotion/media could also not determine the duration of the video.`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.372",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"make": "tsc -d && bun --env-file=../.env.bundle bundle.ts"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"mediabunny": "1.24.
|
|
25
|
-
"remotion": "4.0.
|
|
24
|
+
"mediabunny": "1.24.3",
|
|
25
|
+
"remotion": "4.0.372",
|
|
26
26
|
"webdriverio": "9.19.2"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"react-dom": ">=16.8.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
33
|
+
"@remotion/eslint-config-internal": "4.0.372",
|
|
34
34
|
"@vitest/browser": "^3.2.4",
|
|
35
35
|
"eslint": "9.19.0",
|
|
36
36
|
"react": "19.0.0",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { AudioBufferSink } from 'mediabunny';
|
|
2
|
-
export declare const HEALTHY_BUFFER_THRESHOLD_SECONDS = 1;
|
|
3
|
-
export declare const makeAudioIterator: (audioSink: AudioBufferSink, startFromSecond: number) => {
|
|
4
|
-
iterator: AsyncGenerator<import("mediabunny").WrappedAudioBuffer, void, unknown>;
|
|
5
|
-
destroy: () => void;
|
|
6
|
-
isReadyToPlay: () => boolean;
|
|
7
|
-
setAudioIteratorStarted: (started: boolean) => void;
|
|
8
|
-
getNext: () => Promise<IteratorResult<import("mediabunny").WrappedAudioBuffer, void>>;
|
|
9
|
-
setAudioBufferHealth: (health: number) => void;
|
|
10
|
-
};
|
|
11
|
-
export type AudioIterator = ReturnType<typeof makeAudioIterator>;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const HEALTHY_BUFFER_THRESHOLD_SECONDS = 1;
|
|
2
|
-
export const makeAudioIterator = (audioSink, startFromSecond) => {
|
|
3
|
-
const iterator = audioSink.buffers(startFromSecond);
|
|
4
|
-
let audioIteratorStarted = false;
|
|
5
|
-
let audioBufferHealth = 0;
|
|
6
|
-
return {
|
|
7
|
-
iterator,
|
|
8
|
-
destroy: () => {
|
|
9
|
-
iterator.return().catch(() => undefined);
|
|
10
|
-
},
|
|
11
|
-
isReadyToPlay: () => {
|
|
12
|
-
return audioIteratorStarted && audioBufferHealth > 0;
|
|
13
|
-
},
|
|
14
|
-
setAudioIteratorStarted: (started) => {
|
|
15
|
-
audioIteratorStarted = started;
|
|
16
|
-
},
|
|
17
|
-
getNext: () => {
|
|
18
|
-
return iterator.next();
|
|
19
|
-
},
|
|
20
|
-
setAudioBufferHealth: (health) => {
|
|
21
|
-
audioBufferHealth = health;
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
};
|