@remotion/media 4.0.487 → 4.0.488
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-preview-iterator.d.ts +8 -17
- package/dist/audio/get-scheduled-time.d.ts +5 -5
- package/dist/audio-iterator-manager.d.ts +22 -13
- package/dist/debug-overlay/preview-overlay.d.ts +14 -14
- package/dist/esm/index.mjs +152 -136
- package/dist/make-iterator-with-priming.d.ts +15 -7
- package/package.json +5 -5
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AudioBufferSlice } from '../make-iterator-with-priming';
|
|
2
2
|
export declare const HEALTHY_BUFFER_THRESHOLD_SECONDS = 1;
|
|
3
3
|
export declare const ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
|
|
4
4
|
export type QueuedNode = {
|
|
5
5
|
node: AudioBufferSourceNode;
|
|
6
6
|
timestamp: number;
|
|
7
7
|
buffer: AudioBuffer;
|
|
8
|
+
sourceDurationInSeconds: number;
|
|
8
9
|
scheduledTime: number;
|
|
9
10
|
playbackRate: number;
|
|
10
11
|
scheduledAtAnchor: number;
|
|
@@ -13,26 +14,16 @@ export type QueuedPeriod = {
|
|
|
13
14
|
from: number;
|
|
14
15
|
until: number;
|
|
15
16
|
};
|
|
16
|
-
export
|
|
17
|
+
export type MakeAudioIteratorOptions = {
|
|
17
18
|
startFromSecond: number;
|
|
18
|
-
|
|
19
|
-
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
20
|
-
audioSink: AudioBufferSink;
|
|
21
|
-
loop: boolean;
|
|
22
|
-
playbackRate: number;
|
|
23
|
-
sequenceDurationInSeconds: number;
|
|
19
|
+
iterator: AsyncGenerator<AudioBufferSlice, void, unknown>;
|
|
24
20
|
unscheduleAudioNode: (node: AudioBufferSourceNode) => void;
|
|
25
|
-
}
|
|
21
|
+
};
|
|
22
|
+
export declare const makeAudioIterator: ({ startFromSecond, iterator, unscheduleAudioNode, }: MakeAudioIteratorOptions) => {
|
|
26
23
|
destroy: () => void;
|
|
27
|
-
getNextFn: () => Promise<IteratorResult<
|
|
24
|
+
getNextFn: () => Promise<IteratorResult<AudioBufferSlice, void>>;
|
|
28
25
|
isDestroyed: () => boolean;
|
|
29
|
-
addQueuedAudioNode: (
|
|
30
|
-
node: AudioBufferSourceNode;
|
|
31
|
-
timestamp: number;
|
|
32
|
-
buffer: AudioBuffer;
|
|
33
|
-
scheduledTime: number;
|
|
34
|
-
scheduledAtAnchor: number;
|
|
35
|
-
}) => void;
|
|
26
|
+
addQueuedAudioNode: (queuedNode: QueuedNode) => void;
|
|
36
27
|
guessNextTimestamp: () => number;
|
|
37
28
|
getQueuedPeriod: () => {
|
|
38
29
|
from: number;
|
|
@@ -4,15 +4,15 @@ export declare const getScheduledTime: ({ mediaTimestamp, targetTime, currentTim
|
|
|
4
4
|
currentTime: number;
|
|
5
5
|
sequenceStartTime: number;
|
|
6
6
|
}) => number;
|
|
7
|
-
export declare const getDurationOfNode: ({
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export declare const getDurationOfNode: ({ sourceDurationInSeconds, sourceOffsetInSeconds, offset, }: {
|
|
8
|
+
sourceDurationInSeconds: number;
|
|
9
|
+
sourceOffsetInSeconds: number;
|
|
10
10
|
offset: number;
|
|
11
|
-
originalUnloopedMediaTimestamp: number;
|
|
12
11
|
}) => number;
|
|
13
|
-
export declare const getTrimStartForAudioNode: ({ mediaTimestamp, targetTime, sequenceStartTime, combinedPlaybackRate, }: {
|
|
12
|
+
export declare const getTrimStartForAudioNode: ({ mediaTimestamp, targetTime, sequenceStartTime, combinedPlaybackRate, sourceStartOffsetInSeconds, }: {
|
|
14
13
|
mediaTimestamp: number;
|
|
15
14
|
targetTime: number;
|
|
16
15
|
sequenceStartTime: number;
|
|
17
16
|
combinedPlaybackRate: number;
|
|
17
|
+
sourceStartOffsetInSeconds: number;
|
|
18
18
|
}) => number;
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { type InputAudioTrack } from 'mediabunny';
|
|
2
2
|
import { type ScheduleAudioNodeResult } from 'remotion';
|
|
3
3
|
import type { DelayPlaybackIfNotPremounting } from './delay-playback-if-not-premounting';
|
|
4
|
-
import type
|
|
4
|
+
import { type AudioBufferSlice } from './make-iterator-with-priming';
|
|
5
5
|
import type { Nonce } from './nonce-manager';
|
|
6
6
|
import type { SharedAudioContextForMediaPlayer } from './shared-audio-context-for-media-player';
|
|
7
|
-
type ScheduleAudioNode = (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number) => ScheduleAudioNodeResult;
|
|
7
|
+
type ScheduleAudioNode = (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number, sourceOffsetInSeconds: number, sourceDurationInSeconds: number) => ScheduleAudioNodeResult;
|
|
8
|
+
export type AudioIteratorAnchor = {
|
|
9
|
+
unloopedStartInSeconds: number;
|
|
10
|
+
mediaStartInSeconds: number;
|
|
11
|
+
};
|
|
12
|
+
export declare const anchorToContinuousTime: ({ anchor, unloopedTimeInSeconds, playbackRate, }: {
|
|
13
|
+
anchor: AudioIteratorAnchor;
|
|
14
|
+
unloopedTimeInSeconds: number;
|
|
15
|
+
playbackRate: number;
|
|
16
|
+
}) => number;
|
|
8
17
|
export declare const audioIteratorManager: ({ audioTrack, delayPlaybackHandleIfNotPremounting, sharedAudioContext, getSequenceEndTimestamp, getSequenceDurationInSeconds, getMediaEndTimestamp, getStartTime, initialMuted, drawDebugOverlay, initialPlaybackRate, initialTrimBefore, initialTrimAfter, initialSequenceOffset, initialSequenceDurationInFrames, initialLoop, initialFps, }: {
|
|
9
18
|
audioTrack: InputAudioTrack;
|
|
10
19
|
delayPlaybackHandleIfNotPremounting: () => DelayPlaybackIfNotPremounting;
|
|
@@ -23,8 +32,9 @@ export declare const audioIteratorManager: ({ audioTrack, delayPlaybackHandleIfN
|
|
|
23
32
|
initialLoop: boolean;
|
|
24
33
|
initialFps: number;
|
|
25
34
|
}) => {
|
|
26
|
-
startAudioIterator: ({ nonce, playbackRate, startFromSecond, scheduleAudioNode, getTargetTime, logLevel, loop, unscheduleAudioNode, getAudioContextCurrentTimeMockedInTest, }: {
|
|
35
|
+
startAudioIterator: ({ nonce, playbackRate, startFromSecond, unloopedStartFromSecond, scheduleAudioNode, getTargetTime, logLevel, loop, unscheduleAudioNode, getAudioContextCurrentTimeMockedInTest, }: {
|
|
27
36
|
startFromSecond: number;
|
|
37
|
+
unloopedStartFromSecond: number;
|
|
28
38
|
nonce: Nonce;
|
|
29
39
|
playbackRate: number;
|
|
30
40
|
scheduleAudioNode: ScheduleAudioNode;
|
|
@@ -36,26 +46,23 @@ export declare const audioIteratorManager: ({ audioTrack, delayPlaybackHandleIfN
|
|
|
36
46
|
}) => void;
|
|
37
47
|
getAudioBufferIterator: () => {
|
|
38
48
|
destroy: () => void;
|
|
39
|
-
getNextFn: () => Promise<IteratorResult<
|
|
49
|
+
getNextFn: () => Promise<IteratorResult<AudioBufferSlice, void>>;
|
|
40
50
|
isDestroyed: () => boolean;
|
|
41
|
-
addQueuedAudioNode: (
|
|
42
|
-
node: AudioBufferSourceNode;
|
|
43
|
-
timestamp: number;
|
|
44
|
-
buffer: AudioBuffer;
|
|
45
|
-
scheduledTime: number;
|
|
46
|
-
scheduledAtAnchor: number;
|
|
47
|
-
}) => void;
|
|
51
|
+
addQueuedAudioNode: (queuedNode: import("./audio/audio-preview-iterator").QueuedNode) => void;
|
|
48
52
|
guessNextTimestamp: () => number;
|
|
49
53
|
getQueuedPeriod: () => {
|
|
50
54
|
from: number;
|
|
51
55
|
until: number;
|
|
52
56
|
} | null;
|
|
53
57
|
} | null;
|
|
58
|
+
getCurrentAnchor: () => AudioIteratorAnchor | null;
|
|
54
59
|
destroyIterator: () => void;
|
|
55
|
-
seek: ({ newTime, nonce, playbackRate, scheduleAudioNode, getTargetTime, logLevel, loop, trimBefore, trimAfter, sequenceOffset, sequenceDurationInFrames, fps, getAudioContextCurrentTimeMockedInTest, }: {
|
|
60
|
+
seek: ({ newTime, unloopedNewTime, nonce, playbackRate, localPlaybackRate, scheduleAudioNode, getTargetTime, logLevel, loop, trimBefore, trimAfter, sequenceOffset, sequenceDurationInFrames, fps, getAudioContextCurrentTimeMockedInTest, }: {
|
|
56
61
|
newTime: number;
|
|
62
|
+
unloopedNewTime: number;
|
|
57
63
|
nonce: Nonce;
|
|
58
64
|
playbackRate: number;
|
|
65
|
+
localPlaybackRate: number;
|
|
59
66
|
scheduleAudioNode: ScheduleAudioNode;
|
|
60
67
|
getTargetTime: (mediaTimestamp: number, currentTime: number) => number | null;
|
|
61
68
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
@@ -71,13 +78,15 @@ export declare const audioIteratorManager: ({ audioTrack, delayPlaybackHandleIfN
|
|
|
71
78
|
getTotalAudioScheduledInSeconds: () => number;
|
|
72
79
|
setMuted: (newMuted: boolean) => void;
|
|
73
80
|
setVolume: (volume: number) => void;
|
|
74
|
-
scheduleAudioChunk: ({ buffer, mediaTimestamp, originalUnloopedMediaTimestamp, playbackRate, scheduleAudioNode, logLevel, }: {
|
|
81
|
+
scheduleAudioChunk: ({ buffer, mediaTimestamp, originalUnloopedMediaTimestamp, sourceOffsetInSeconds, sourceDurationInSeconds, playbackRate, scheduleAudioNode, logLevel, }: {
|
|
75
82
|
buffer: AudioBuffer;
|
|
76
83
|
mediaTimestamp: number;
|
|
77
84
|
playbackRate: number;
|
|
78
85
|
scheduleAudioNode: ScheduleAudioNode;
|
|
79
86
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
80
87
|
originalUnloopedMediaTimestamp: number;
|
|
88
|
+
sourceOffsetInSeconds: number;
|
|
89
|
+
sourceDurationInSeconds: number;
|
|
81
90
|
}) => void;
|
|
82
91
|
waitForNScheduledNodes: (n: number) => Promise<void>;
|
|
83
92
|
};
|
|
@@ -7,11 +7,12 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
|
|
|
7
7
|
} | null;
|
|
8
8
|
playing: boolean;
|
|
9
9
|
audioIteratorManager: {
|
|
10
|
-
startAudioIterator: ({ nonce, playbackRate, startFromSecond, scheduleAudioNode, getTargetTime, logLevel, loop, unscheduleAudioNode, getAudioContextCurrentTimeMockedInTest, }: {
|
|
10
|
+
startAudioIterator: ({ nonce, playbackRate, startFromSecond, unloopedStartFromSecond, scheduleAudioNode, getTargetTime, logLevel, loop, unscheduleAudioNode, getAudioContextCurrentTimeMockedInTest, }: {
|
|
11
11
|
startFromSecond: number;
|
|
12
|
+
unloopedStartFromSecond: number;
|
|
12
13
|
nonce: import("../nonce-manager").Nonce;
|
|
13
14
|
playbackRate: number;
|
|
14
|
-
scheduleAudioNode: (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number) => import("remotion").ScheduleAudioNodeResult;
|
|
15
|
+
scheduleAudioNode: (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number, sourceOffsetInSeconds: number, sourceDurationInSeconds: number) => import("remotion").ScheduleAudioNodeResult;
|
|
15
16
|
getTargetTime: (mediaTimestamp: number, currentTime: number) => number | null;
|
|
16
17
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
17
18
|
loop: boolean;
|
|
@@ -20,27 +21,24 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
|
|
|
20
21
|
}) => void;
|
|
21
22
|
getAudioBufferIterator: () => {
|
|
22
23
|
destroy: () => void;
|
|
23
|
-
getNextFn: () => Promise<IteratorResult<import("../make-iterator-with-priming").
|
|
24
|
+
getNextFn: () => Promise<IteratorResult<import("../make-iterator-with-priming").AudioBufferSlice, void>>;
|
|
24
25
|
isDestroyed: () => boolean;
|
|
25
|
-
addQueuedAudioNode: (
|
|
26
|
-
node: AudioBufferSourceNode;
|
|
27
|
-
timestamp: number;
|
|
28
|
-
buffer: AudioBuffer;
|
|
29
|
-
scheduledTime: number;
|
|
30
|
-
scheduledAtAnchor: number;
|
|
31
|
-
}) => void;
|
|
26
|
+
addQueuedAudioNode: (queuedNode: import("../audio/audio-preview-iterator").QueuedNode) => void;
|
|
32
27
|
guessNextTimestamp: () => number;
|
|
33
28
|
getQueuedPeriod: () => {
|
|
34
29
|
from: number;
|
|
35
30
|
until: number;
|
|
36
31
|
} | null;
|
|
37
32
|
} | null;
|
|
33
|
+
getCurrentAnchor: () => import("../audio-iterator-manager").AudioIteratorAnchor | null;
|
|
38
34
|
destroyIterator: () => void;
|
|
39
|
-
seek: ({ newTime, nonce, playbackRate, scheduleAudioNode, getTargetTime, logLevel, loop, trimBefore, trimAfter, sequenceOffset, sequenceDurationInFrames, fps, getAudioContextCurrentTimeMockedInTest, }: {
|
|
35
|
+
seek: ({ newTime, unloopedNewTime, nonce, playbackRate, localPlaybackRate, scheduleAudioNode, getTargetTime, logLevel, loop, trimBefore, trimAfter, sequenceOffset, sequenceDurationInFrames, fps, getAudioContextCurrentTimeMockedInTest, }: {
|
|
40
36
|
newTime: number;
|
|
37
|
+
unloopedNewTime: number;
|
|
41
38
|
nonce: import("../nonce-manager").Nonce;
|
|
42
39
|
playbackRate: number;
|
|
43
|
-
|
|
40
|
+
localPlaybackRate: number;
|
|
41
|
+
scheduleAudioNode: (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number, sourceOffsetInSeconds: number, sourceDurationInSeconds: number) => import("remotion").ScheduleAudioNodeResult;
|
|
44
42
|
getTargetTime: (mediaTimestamp: number, currentTime: number) => number | null;
|
|
45
43
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
46
44
|
loop: boolean;
|
|
@@ -55,13 +53,15 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
|
|
|
55
53
|
getTotalAudioScheduledInSeconds: () => number;
|
|
56
54
|
setMuted: (newMuted: boolean) => void;
|
|
57
55
|
setVolume: (volume: number) => void;
|
|
58
|
-
scheduleAudioChunk: ({ buffer, mediaTimestamp, originalUnloopedMediaTimestamp, playbackRate, scheduleAudioNode, logLevel, }: {
|
|
56
|
+
scheduleAudioChunk: ({ buffer, mediaTimestamp, originalUnloopedMediaTimestamp, sourceOffsetInSeconds, sourceDurationInSeconds, playbackRate, scheduleAudioNode, logLevel, }: {
|
|
59
57
|
buffer: AudioBuffer;
|
|
60
58
|
mediaTimestamp: number;
|
|
61
59
|
playbackRate: number;
|
|
62
|
-
scheduleAudioNode: (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number) => import("remotion").ScheduleAudioNodeResult;
|
|
60
|
+
scheduleAudioNode: (node: AudioBufferSourceNode, mediaTimestamp: number, originalUnloopedMediaTimestamp: number, sourceOffsetInSeconds: number, sourceDurationInSeconds: number) => import("remotion").ScheduleAudioNodeResult;
|
|
63
61
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
64
62
|
originalUnloopedMediaTimestamp: number;
|
|
63
|
+
sourceOffsetInSeconds: number;
|
|
64
|
+
sourceDurationInSeconds: number;
|
|
65
65
|
}) => void;
|
|
66
66
|
waitForNScheduledNodes: (n: number) => Promise<void>;
|
|
67
67
|
} | null;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -146,97 +146,21 @@ import {
|
|
|
146
146
|
} from "mediabunny";
|
|
147
147
|
import { Internals as Internals3 } from "remotion";
|
|
148
148
|
|
|
149
|
-
// src/make-iterator-with-priming.ts
|
|
150
|
-
var AUDIO_PRIMING_SECONDS = 0.5;
|
|
151
|
-
async function* makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp) {
|
|
152
|
-
const primingStart = Math.max(0, timeToSeek - AUDIO_PRIMING_SECONDS);
|
|
153
|
-
const iterator = audioSink.buffers(primingStart, maximumTimestamp);
|
|
154
|
-
for await (const buffer of iterator) {
|
|
155
|
-
if (buffer.timestamp + buffer.duration <= timeToSeek) {
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
yield {
|
|
159
|
-
buffer,
|
|
160
|
-
timestamp: buffer.timestamp
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
async function* makeLoopingIterator({
|
|
165
|
-
audioSink,
|
|
166
|
-
segmentStartInSeconds,
|
|
167
|
-
segmentEndInSeconds,
|
|
168
|
-
playbackRate,
|
|
169
|
-
sequenceDurationInSeconds
|
|
170
|
-
}) {
|
|
171
|
-
const duration = segmentEndInSeconds - segmentStartInSeconds;
|
|
172
|
-
let iteration = 0;
|
|
173
|
-
let broken = false;
|
|
174
|
-
while (true) {
|
|
175
|
-
for await (const item of makeIteratorWithPrimingInner(audioSink, segmentStartInSeconds, segmentEndInSeconds)) {
|
|
176
|
-
const timestamp = item.timestamp + iteration * duration;
|
|
177
|
-
const endTimestamp = duration * iteration + (item.timestamp - segmentStartInSeconds + item.buffer.duration);
|
|
178
|
-
if (endTimestamp > sequenceDurationInSeconds * playbackRate) {
|
|
179
|
-
broken = true;
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
yield {
|
|
183
|
-
buffer: item.buffer,
|
|
184
|
-
timestamp
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
if (broken) {
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
iteration++;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
var makeIteratorWithPriming = ({
|
|
194
|
-
audioSink,
|
|
195
|
-
timeToSeek,
|
|
196
|
-
maximumTimestamp,
|
|
197
|
-
loop,
|
|
198
|
-
playbackRate,
|
|
199
|
-
sequenceDurationInSeconds
|
|
200
|
-
}) => {
|
|
201
|
-
if (loop) {
|
|
202
|
-
return makeLoopingIterator({
|
|
203
|
-
audioSink,
|
|
204
|
-
segmentStartInSeconds: timeToSeek,
|
|
205
|
-
segmentEndInSeconds: maximumTimestamp,
|
|
206
|
-
playbackRate,
|
|
207
|
-
sequenceDurationInSeconds
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp);
|
|
211
|
-
};
|
|
212
|
-
|
|
213
149
|
// src/audio/audio-preview-iterator.ts
|
|
214
150
|
var ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
|
|
215
151
|
var makeAudioIterator = ({
|
|
216
152
|
startFromSecond,
|
|
217
|
-
|
|
218
|
-
audioSink,
|
|
219
|
-
loop,
|
|
220
|
-
playbackRate,
|
|
221
|
-
sequenceDurationInSeconds,
|
|
153
|
+
iterator,
|
|
222
154
|
unscheduleAudioNode
|
|
223
155
|
}) => {
|
|
224
156
|
let destroyed = false;
|
|
225
|
-
const iterator = makeIteratorWithPriming({
|
|
226
|
-
audioSink,
|
|
227
|
-
timeToSeek: startFromSecond,
|
|
228
|
-
maximumTimestamp,
|
|
229
|
-
loop,
|
|
230
|
-
playbackRate,
|
|
231
|
-
sequenceDurationInSeconds
|
|
232
|
-
});
|
|
233
157
|
const queuedAudioNodes = [];
|
|
234
158
|
let mostRecentTimestamp = -Infinity;
|
|
235
159
|
const cleanupAudioQueue = () => {
|
|
236
|
-
for (const node of queuedAudioNodes) {
|
|
237
|
-
unscheduleAudioNode(node
|
|
160
|
+
for (const { node } of queuedAudioNodes) {
|
|
161
|
+
unscheduleAudioNode(node);
|
|
238
162
|
try {
|
|
239
|
-
node.
|
|
163
|
+
node.stop();
|
|
240
164
|
} catch {}
|
|
241
165
|
}
|
|
242
166
|
queuedAudioNodes.length = 0;
|
|
@@ -244,7 +168,7 @@ var makeAudioIterator = ({
|
|
|
244
168
|
const getNextFn = async () => {
|
|
245
169
|
const next = await iterator.next();
|
|
246
170
|
if (next.value) {
|
|
247
|
-
mostRecentTimestamp = Math.max(mostRecentTimestamp, next.value.
|
|
171
|
+
mostRecentTimestamp = Math.max(mostRecentTimestamp, next.value.timelineTimestamp + next.value.sourceDurationInSeconds);
|
|
248
172
|
}
|
|
249
173
|
return next;
|
|
250
174
|
};
|
|
@@ -260,21 +184,8 @@ var makeAudioIterator = ({
|
|
|
260
184
|
isDestroyed: () => {
|
|
261
185
|
return destroyed;
|
|
262
186
|
},
|
|
263
|
-
addQueuedAudioNode: ({
|
|
264
|
-
|
|
265
|
-
timestamp,
|
|
266
|
-
buffer,
|
|
267
|
-
scheduledTime,
|
|
268
|
-
scheduledAtAnchor
|
|
269
|
-
}) => {
|
|
270
|
-
queuedAudioNodes.push({
|
|
271
|
-
node,
|
|
272
|
-
timestamp,
|
|
273
|
-
buffer,
|
|
274
|
-
scheduledTime,
|
|
275
|
-
playbackRate,
|
|
276
|
-
scheduledAtAnchor
|
|
277
|
-
});
|
|
187
|
+
addQueuedAudioNode: (queuedNode) => {
|
|
188
|
+
queuedAudioNodes.push(queuedNode);
|
|
278
189
|
},
|
|
279
190
|
guessNextTimestamp: () => {
|
|
280
191
|
return !Number.isFinite(mostRecentTimestamp) ? startFromSecond : mostRecentTimestamp;
|
|
@@ -283,7 +194,7 @@ var makeAudioIterator = ({
|
|
|
283
194
|
let until = -Infinity;
|
|
284
195
|
let from = Infinity;
|
|
285
196
|
for (const node of queuedAudioNodes) {
|
|
286
|
-
until = Math.max(until, node.timestamp + node.
|
|
197
|
+
until = Math.max(until, node.timestamp + node.sourceDurationInSeconds);
|
|
287
198
|
from = Math.min(from, node.timestamp);
|
|
288
199
|
}
|
|
289
200
|
if (!Number.isFinite(from) || !Number.isFinite(until)) {
|
|
@@ -318,27 +229,23 @@ var getScheduledTime = ({
|
|
|
318
229
|
return scheduledTime;
|
|
319
230
|
};
|
|
320
231
|
var getDurationOfNode = ({
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
offset
|
|
324
|
-
originalUnloopedMediaTimestamp
|
|
232
|
+
sourceDurationInSeconds,
|
|
233
|
+
sourceOffsetInSeconds,
|
|
234
|
+
offset
|
|
325
235
|
}) => {
|
|
326
|
-
|
|
327
|
-
const needsTrimEnd = originalUnloopedMediaEndTime > loopSegmentMediaEndTimestamp;
|
|
328
|
-
const durationMinusOffset = bufferDuration - offset;
|
|
329
|
-
const duration = needsTrimEnd ? durationMinusOffset - Math.max(0, originalUnloopedMediaEndTime - loopSegmentMediaEndTimestamp) : durationMinusOffset;
|
|
330
|
-
return duration;
|
|
236
|
+
return Math.max(0, sourceDurationInSeconds - (offset - sourceOffsetInSeconds));
|
|
331
237
|
};
|
|
332
238
|
var getTrimStartForAudioNode = ({
|
|
333
239
|
mediaTimestamp,
|
|
334
240
|
targetTime,
|
|
335
241
|
sequenceStartTime,
|
|
336
|
-
combinedPlaybackRate
|
|
242
|
+
combinedPlaybackRate,
|
|
243
|
+
sourceStartOffsetInSeconds
|
|
337
244
|
}) => {
|
|
338
245
|
const needsTrimStart = mediaTimestamp < sequenceStartTime;
|
|
339
246
|
const offsetBecauseOfTrim = needsTrimStart ? sequenceStartTime - mediaTimestamp : 0;
|
|
340
247
|
const offsetBecauseOfTooLate = targetTime < 0 ? -targetTime * combinedPlaybackRate : 0;
|
|
341
|
-
return offsetBecauseOfTrim + offsetBecauseOfTooLate;
|
|
248
|
+
return sourceStartOffsetInSeconds + offsetBecauseOfTrim + offsetBecauseOfTooLate;
|
|
342
249
|
};
|
|
343
250
|
|
|
344
251
|
// src/audio/sort-by-priority.ts
|
|
@@ -442,7 +349,79 @@ var waitForTurn = ({
|
|
|
442
349
|
processNext();
|
|
443
350
|
};
|
|
444
351
|
|
|
352
|
+
// src/make-iterator-with-priming.ts
|
|
353
|
+
var AUDIO_PRIMING_SECONDS = 0.5;
|
|
354
|
+
async function* makeIteratorWithPriming({
|
|
355
|
+
audioSink,
|
|
356
|
+
timeToSeek,
|
|
357
|
+
maximumTimestamp
|
|
358
|
+
}) {
|
|
359
|
+
const primingStart = Math.max(0, timeToSeek - AUDIO_PRIMING_SECONDS);
|
|
360
|
+
const iterator = audioSink.buffers(primingStart, maximumTimestamp);
|
|
361
|
+
for await (const buffer of iterator) {
|
|
362
|
+
const sourceStart = Math.max(buffer.timestamp, timeToSeek);
|
|
363
|
+
const sourceEnd = Math.min(buffer.timestamp + buffer.duration, maximumTimestamp);
|
|
364
|
+
if (sourceEnd <= sourceStart) {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
yield {
|
|
368
|
+
buffer,
|
|
369
|
+
timelineTimestamp: sourceStart,
|
|
370
|
+
sourceOffsetInSeconds: sourceStart - buffer.timestamp,
|
|
371
|
+
sourceDurationInSeconds: sourceEnd - sourceStart
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async function* makeLoopingIterator({
|
|
376
|
+
audioSink,
|
|
377
|
+
seekTimeInSeconds,
|
|
378
|
+
loopStartInSeconds,
|
|
379
|
+
segmentEndInSeconds,
|
|
380
|
+
maximumContinuousTimestamp
|
|
381
|
+
}) {
|
|
382
|
+
if (segmentEndInSeconds <= loopStartInSeconds) {
|
|
383
|
+
throw new Error(`Cannot loop audio over an empty range (${loopStartInSeconds} to ${segmentEndInSeconds})`);
|
|
384
|
+
}
|
|
385
|
+
let passStartInSeconds = seekTimeInSeconds;
|
|
386
|
+
let passBaseTimestamp = seekTimeInSeconds;
|
|
387
|
+
while (true) {
|
|
388
|
+
let yieldedInPass = false;
|
|
389
|
+
for await (const item of makeIteratorWithPriming({
|
|
390
|
+
audioSink,
|
|
391
|
+
timeToSeek: passStartInSeconds,
|
|
392
|
+
maximumTimestamp: segmentEndInSeconds
|
|
393
|
+
})) {
|
|
394
|
+
yieldedInPass = true;
|
|
395
|
+
const timelineTimestamp = passBaseTimestamp + (item.timelineTimestamp - passStartInSeconds);
|
|
396
|
+
const sourceDurationInSeconds = Math.min(item.sourceDurationInSeconds, maximumContinuousTimestamp - timelineTimestamp);
|
|
397
|
+
if (sourceDurationInSeconds <= 0) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
yield {
|
|
401
|
+
...item,
|
|
402
|
+
timelineTimestamp,
|
|
403
|
+
sourceDurationInSeconds
|
|
404
|
+
};
|
|
405
|
+
if (timelineTimestamp + sourceDurationInSeconds >= maximumContinuousTimestamp) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (!yieldedInPass) {
|
|
410
|
+
throw new Error(`Audio loop pass from ${passStartInSeconds} to ${segmentEndInSeconds} yielded no buffers`);
|
|
411
|
+
}
|
|
412
|
+
passBaseTimestamp += segmentEndInSeconds - passStartInSeconds;
|
|
413
|
+
passStartInSeconds = loopStartInSeconds;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
445
417
|
// src/audio-iterator-manager.ts
|
|
418
|
+
var anchorToContinuousTime = ({
|
|
419
|
+
anchor,
|
|
420
|
+
unloopedTimeInSeconds,
|
|
421
|
+
playbackRate
|
|
422
|
+
}) => {
|
|
423
|
+
return anchor.mediaStartInSeconds + (unloopedTimeInSeconds - anchor.unloopedStartInSeconds) * playbackRate;
|
|
424
|
+
};
|
|
446
425
|
var audioIteratorManager = ({
|
|
447
426
|
audioTrack,
|
|
448
427
|
delayPlaybackHandleIfNotPremounting,
|
|
@@ -477,6 +456,7 @@ var audioIteratorManager = ({
|
|
|
477
456
|
gainNode.connect(sharedAudioContext.gainNode);
|
|
478
457
|
const audioSink = new AudioBufferSink(audioTrack);
|
|
479
458
|
let audioBufferIterator = null;
|
|
459
|
+
let currentAnchor = null;
|
|
480
460
|
let audioIteratorsCreated = 0;
|
|
481
461
|
let totalAudioScheduledInSeconds = 0;
|
|
482
462
|
let currentDelayHandle = null;
|
|
@@ -509,6 +489,8 @@ var audioIteratorManager = ({
|
|
|
509
489
|
buffer,
|
|
510
490
|
mediaTimestamp,
|
|
511
491
|
originalUnloopedMediaTimestamp,
|
|
492
|
+
sourceOffsetInSeconds,
|
|
493
|
+
sourceDurationInSeconds,
|
|
512
494
|
playbackRate,
|
|
513
495
|
scheduleAudioNode,
|
|
514
496
|
logLevel
|
|
@@ -523,7 +505,7 @@ var audioIteratorManager = ({
|
|
|
523
505
|
node.buffer = buffer;
|
|
524
506
|
node.playbackRate.value = playbackRate;
|
|
525
507
|
node.connect(gainNode);
|
|
526
|
-
const started = scheduleAudioNode(node, mediaTimestamp, originalUnloopedMediaTimestamp);
|
|
508
|
+
const started = scheduleAudioNode(node, mediaTimestamp, originalUnloopedMediaTimestamp, sourceOffsetInSeconds, sourceDurationInSeconds);
|
|
527
509
|
if (started.type === "not-started") {
|
|
528
510
|
Internals3.Log.verbose({ logLevel, tag: "audio-scheduling" }, "not started, disconnected: %s %s", mediaTimestamp.toFixed(3), buffer.duration.toFixed(3));
|
|
529
511
|
node.disconnect();
|
|
@@ -533,7 +515,9 @@ var audioIteratorManager = ({
|
|
|
533
515
|
node,
|
|
534
516
|
timestamp: mediaTimestamp,
|
|
535
517
|
buffer,
|
|
518
|
+
sourceDurationInSeconds,
|
|
536
519
|
scheduledTime: started.scheduledTime,
|
|
520
|
+
playbackRate,
|
|
537
521
|
scheduledAtAnchor: sharedAudioContext.audioSyncAnchor.value
|
|
538
522
|
});
|
|
539
523
|
};
|
|
@@ -548,22 +532,24 @@ var audioIteratorManager = ({
|
|
|
548
532
|
}
|
|
549
533
|
const startTime = getStartTime();
|
|
550
534
|
const sequenceEndTime = getSequenceEndTimestamp();
|
|
551
|
-
if (buffer.
|
|
535
|
+
if (buffer.timelineTimestamp + buffer.sourceDurationInSeconds <= startTime) {
|
|
552
536
|
return;
|
|
553
537
|
}
|
|
554
|
-
if (buffer.
|
|
538
|
+
if (buffer.timelineTimestamp >= sequenceEndTime) {
|
|
555
539
|
return;
|
|
556
540
|
}
|
|
557
|
-
const scheduledStart = Math.max(buffer.
|
|
558
|
-
const scheduledEnd = Math.min(buffer.
|
|
541
|
+
const scheduledStart = Math.max(buffer.timelineTimestamp, startTime);
|
|
542
|
+
const scheduledEnd = Math.min(buffer.timelineTimestamp + buffer.sourceDurationInSeconds, sequenceEndTime);
|
|
559
543
|
totalAudioScheduledInSeconds += Math.max(0, scheduledEnd - scheduledStart);
|
|
560
544
|
scheduleAudioChunk({
|
|
561
545
|
buffer: buffer.buffer.buffer,
|
|
562
|
-
mediaTimestamp: buffer.
|
|
546
|
+
mediaTimestamp: buffer.timelineTimestamp,
|
|
563
547
|
playbackRate,
|
|
564
548
|
scheduleAudioNode,
|
|
565
549
|
logLevel,
|
|
566
|
-
originalUnloopedMediaTimestamp: buffer.buffer.timestamp
|
|
550
|
+
originalUnloopedMediaTimestamp: buffer.buffer.timestamp,
|
|
551
|
+
sourceOffsetInSeconds: buffer.sourceOffsetInSeconds,
|
|
552
|
+
sourceDurationInSeconds: buffer.sourceDurationInSeconds
|
|
567
553
|
});
|
|
568
554
|
drawDebugOverlay();
|
|
569
555
|
};
|
|
@@ -611,7 +597,7 @@ var audioIteratorManager = ({
|
|
|
611
597
|
onDone();
|
|
612
598
|
return;
|
|
613
599
|
}
|
|
614
|
-
onScheduled(result.value.
|
|
600
|
+
onScheduled(result.value.timelineTimestamp);
|
|
615
601
|
notifyNodeScheduled();
|
|
616
602
|
onAudioChunk({
|
|
617
603
|
buffer: result.value,
|
|
@@ -651,6 +637,7 @@ var audioIteratorManager = ({
|
|
|
651
637
|
nonce,
|
|
652
638
|
playbackRate,
|
|
653
639
|
startFromSecond,
|
|
640
|
+
unloopedStartFromSecond,
|
|
654
641
|
scheduleAudioNode,
|
|
655
642
|
getTargetTime,
|
|
656
643
|
logLevel,
|
|
@@ -669,14 +656,25 @@ var audioIteratorManager = ({
|
|
|
669
656
|
unblockCurrentDelayHandle();
|
|
670
657
|
const delayHandle = delayPlaybackHandleIfNotPremounting();
|
|
671
658
|
currentDelayHandle = delayHandle;
|
|
659
|
+
currentAnchor = {
|
|
660
|
+
unloopedStartInSeconds: unloopedStartFromSecond,
|
|
661
|
+
mediaStartInSeconds: startFromSecond
|
|
662
|
+
};
|
|
663
|
+
const maximumContinuousTimestamp = startFromSecond + getSequenceDurationInSeconds() * playbackRate;
|
|
664
|
+
const source = loop ? makeLoopingIterator({
|
|
665
|
+
audioSink,
|
|
666
|
+
seekTimeInSeconds: startFromSecond,
|
|
667
|
+
loopStartInSeconds: getStartTime(),
|
|
668
|
+
segmentEndInSeconds: maximumTimestamp,
|
|
669
|
+
maximumContinuousTimestamp
|
|
670
|
+
}) : makeIteratorWithPriming({
|
|
671
|
+
audioSink,
|
|
672
|
+
timeToSeek: startFromSecond,
|
|
673
|
+
maximumTimestamp
|
|
674
|
+
});
|
|
672
675
|
const iterator = makeAudioIterator({
|
|
673
676
|
startFromSecond,
|
|
674
|
-
|
|
675
|
-
audioSink,
|
|
676
|
-
logLevel,
|
|
677
|
-
loop,
|
|
678
|
-
playbackRate,
|
|
679
|
-
sequenceDurationInSeconds: getSequenceDurationInSeconds(),
|
|
677
|
+
iterator: source,
|
|
680
678
|
unscheduleAudioNode
|
|
681
679
|
});
|
|
682
680
|
audioIteratorsCreated++;
|
|
@@ -707,8 +705,10 @@ var audioIteratorManager = ({
|
|
|
707
705
|
};
|
|
708
706
|
const seek = ({
|
|
709
707
|
newTime,
|
|
708
|
+
unloopedNewTime,
|
|
710
709
|
nonce,
|
|
711
710
|
playbackRate,
|
|
711
|
+
localPlaybackRate,
|
|
712
712
|
scheduleAudioNode,
|
|
713
713
|
getTargetTime,
|
|
714
714
|
logLevel,
|
|
@@ -740,18 +740,23 @@ var audioIteratorManager = ({
|
|
|
740
740
|
return;
|
|
741
741
|
}
|
|
742
742
|
if (audioBufferIterator && !audioBufferIterator.isDestroyed()) {
|
|
743
|
+
const timeToCheck = loop && currentAnchor ? anchorToContinuousTime({
|
|
744
|
+
anchor: currentAnchor,
|
|
745
|
+
unloopedTimeInSeconds: unloopedNewTime,
|
|
746
|
+
playbackRate: localPlaybackRate
|
|
747
|
+
}) : newTime;
|
|
743
748
|
const queuedPeriod = audioBufferIterator.getQueuedPeriod();
|
|
744
749
|
const queuedPeriodMinusLatency = queuedPeriod ? {
|
|
745
750
|
from: queuedPeriod.from - ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT - sharedAudioContext.audioContext.baseLatency - sharedAudioContext.audioContext.outputLatency,
|
|
746
751
|
until: queuedPeriod.until
|
|
747
752
|
} : null;
|
|
748
|
-
const currentTimeIsAlreadyQueued = isAlreadyQueued(
|
|
753
|
+
const currentTimeIsAlreadyQueued = isAlreadyQueued(timeToCheck, queuedPeriodMinusLatency);
|
|
749
754
|
if (currentTimeIsAlreadyQueued) {
|
|
750
755
|
processNext();
|
|
751
756
|
return;
|
|
752
757
|
}
|
|
753
758
|
const currentIteratorTimestamp = audioBufferIterator.guessNextTimestamp();
|
|
754
|
-
if (currentIteratorTimestamp <
|
|
759
|
+
if (currentIteratorTimestamp < timeToCheck && Math.abs(currentIteratorTimestamp - timeToCheck) < 1) {
|
|
755
760
|
processNext();
|
|
756
761
|
return;
|
|
757
762
|
}
|
|
@@ -760,6 +765,7 @@ var audioIteratorManager = ({
|
|
|
760
765
|
nonce,
|
|
761
766
|
playbackRate,
|
|
762
767
|
startFromSecond: newTime,
|
|
768
|
+
unloopedStartFromSecond: unloopedNewTime,
|
|
763
769
|
scheduleAudioNode,
|
|
764
770
|
getTargetTime,
|
|
765
771
|
logLevel,
|
|
@@ -771,9 +777,11 @@ var audioIteratorManager = ({
|
|
|
771
777
|
return {
|
|
772
778
|
startAudioIterator,
|
|
773
779
|
getAudioBufferIterator: () => audioBufferIterator,
|
|
780
|
+
getCurrentAnchor: () => currentAnchor,
|
|
774
781
|
destroyIterator: () => {
|
|
775
782
|
audioBufferIterator?.destroy();
|
|
776
783
|
audioBufferIterator = null;
|
|
784
|
+
currentAnchor = null;
|
|
777
785
|
unblockCurrentDelayHandle();
|
|
778
786
|
},
|
|
779
787
|
seek,
|
|
@@ -1817,6 +1825,7 @@ class MediaPlayer {
|
|
|
1817
1825
|
nonce,
|
|
1818
1826
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1819
1827
|
startFromSecond: startTime,
|
|
1828
|
+
unloopedStartFromSecond: startTimeUnresolved,
|
|
1820
1829
|
scheduleAudioNode: this.scheduleAudioNode,
|
|
1821
1830
|
getTargetTime: this.getTargetTime,
|
|
1822
1831
|
logLevel: this.logLevel,
|
|
@@ -1848,10 +1857,10 @@ class MediaPlayer {
|
|
|
1848
1857
|
__callDispose(__stack, _err, _hasErr);
|
|
1849
1858
|
}
|
|
1850
1859
|
}
|
|
1851
|
-
seekToWithQueue = async (newTime) => {
|
|
1860
|
+
seekToWithQueue = async (newTime, unloopedNewTime) => {
|
|
1852
1861
|
const nonce = this.nonceManager.createAsyncOperation();
|
|
1853
1862
|
await this.seekPromiseChain;
|
|
1854
|
-
this.seekPromiseChain = this.seekToDoNotCallDirectly(newTime, nonce);
|
|
1863
|
+
this.seekPromiseChain = this.seekToDoNotCallDirectly(newTime, unloopedNewTime, nonce);
|
|
1855
1864
|
await this.seekPromiseChain;
|
|
1856
1865
|
};
|
|
1857
1866
|
async seekTo(time) {
|
|
@@ -1859,9 +1868,9 @@ class MediaPlayer {
|
|
|
1859
1868
|
if (newTime === null) {
|
|
1860
1869
|
throw new Error(`should have asserted that the time is not null`);
|
|
1861
1870
|
}
|
|
1862
|
-
await this.seekToWithQueue(newTime);
|
|
1871
|
+
await this.seekToWithQueue(newTime, time);
|
|
1863
1872
|
}
|
|
1864
|
-
async seekToDoNotCallDirectly(newTime, nonce) {
|
|
1873
|
+
async seekToDoNotCallDirectly(newTime, unloopedNewTime, nonce) {
|
|
1865
1874
|
if (nonce.isStale()) {
|
|
1866
1875
|
return;
|
|
1867
1876
|
}
|
|
@@ -1873,8 +1882,10 @@ class MediaPlayer {
|
|
|
1873
1882
|
}),
|
|
1874
1883
|
this.audioIteratorManager?.seek({
|
|
1875
1884
|
newTime,
|
|
1885
|
+
unloopedNewTime,
|
|
1876
1886
|
nonce,
|
|
1877
1887
|
playbackRate: this.playbackRate * this.globalPlaybackRate,
|
|
1888
|
+
localPlaybackRate: this.playbackRate,
|
|
1878
1889
|
getTargetTime: this.getTargetTime,
|
|
1879
1890
|
logLevel: this.logLevel,
|
|
1880
1891
|
loop: this.loop,
|
|
@@ -2020,14 +2031,19 @@ class MediaPlayer {
|
|
|
2020
2031
|
}
|
|
2021
2032
|
const globalTime = (currentTime - this.sharedAudioContext.audioSyncAnchor.value) * this.globalPlaybackRate;
|
|
2022
2033
|
const timeInSeconds = globalTime - this.sequenceOffset;
|
|
2023
|
-
const
|
|
2034
|
+
const anchor = this.loop ? this.audioIteratorManager?.getCurrentAnchor() ?? null : null;
|
|
2035
|
+
const localTime = anchor ? anchorToContinuousTime({
|
|
2036
|
+
anchor,
|
|
2037
|
+
unloopedTimeInSeconds: timeInSeconds,
|
|
2038
|
+
playbackRate: this.playbackRate
|
|
2039
|
+
}) : this.getTrimmedTime(timeInSeconds);
|
|
2024
2040
|
if (localTime === null) {
|
|
2025
2041
|
return null;
|
|
2026
2042
|
}
|
|
2027
2043
|
const targetTime = (mediaTimestamp - localTime) / (this.playbackRate * this.globalPlaybackRate);
|
|
2028
2044
|
return targetTime;
|
|
2029
2045
|
};
|
|
2030
|
-
scheduleAudioNode = (node, mediaTimestamp, originalUnloopedMediaTimestamp) => {
|
|
2046
|
+
scheduleAudioNode = (node, mediaTimestamp, originalUnloopedMediaTimestamp, sourceOffsetInSeconds, sourceDurationInSeconds) => {
|
|
2031
2047
|
if (!this.sharedAudioContext) {
|
|
2032
2048
|
throw new Error("Shared audio context not found");
|
|
2033
2049
|
}
|
|
@@ -2040,18 +2056,17 @@ class MediaPlayer {
|
|
|
2040
2056
|
};
|
|
2041
2057
|
}
|
|
2042
2058
|
const sequenceStartTime = this.getStartTime();
|
|
2043
|
-
const loopSegmentMediaEndTimestamp = this.getLoopSegmentMediaEndTimestamp();
|
|
2044
2059
|
const offset = getTrimStartForAudioNode({
|
|
2045
2060
|
mediaTimestamp,
|
|
2046
2061
|
targetTime,
|
|
2047
2062
|
sequenceStartTime,
|
|
2048
|
-
combinedPlaybackRate
|
|
2063
|
+
combinedPlaybackRate,
|
|
2064
|
+
sourceStartOffsetInSeconds: sourceOffsetInSeconds
|
|
2049
2065
|
});
|
|
2050
2066
|
const duration = getDurationOfNode({
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
offset
|
|
2054
|
-
originalUnloopedMediaTimestamp
|
|
2067
|
+
sourceDurationInSeconds,
|
|
2068
|
+
sourceOffsetInSeconds,
|
|
2069
|
+
offset
|
|
2055
2070
|
});
|
|
2056
2071
|
const scheduledTime = getScheduledTime({
|
|
2057
2072
|
mediaTimestamp,
|
|
@@ -2062,6 +2077,7 @@ class MediaPlayer {
|
|
|
2062
2077
|
return this.sharedAudioContext.scheduleAudioNode({
|
|
2063
2078
|
node,
|
|
2064
2079
|
mediaTimestamp,
|
|
2080
|
+
sourceOffset: sourceOffsetInSeconds,
|
|
2065
2081
|
scheduledTime,
|
|
2066
2082
|
duration,
|
|
2067
2083
|
offset,
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import type { AudioBufferSink, WrappedAudioBuffer } from 'mediabunny';
|
|
2
|
-
export type
|
|
2
|
+
export type AudioBufferSlice = {
|
|
3
3
|
buffer: WrappedAudioBuffer;
|
|
4
|
-
|
|
4
|
+
timelineTimestamp: number;
|
|
5
|
+
sourceOffsetInSeconds: number;
|
|
6
|
+
sourceDurationInSeconds: number;
|
|
5
7
|
};
|
|
6
|
-
export declare
|
|
8
|
+
export declare function makeIteratorWithPriming({ audioSink, timeToSeek, maximumTimestamp }: {
|
|
7
9
|
audioSink: AudioBufferSink;
|
|
8
10
|
timeToSeek: number;
|
|
9
11
|
maximumTimestamp: number;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
}): AsyncGenerator<AudioBufferSlice, void, unknown>;
|
|
13
|
+
type MakeLoopingIteratorOptions = {
|
|
14
|
+
audioSink: AudioBufferSink;
|
|
15
|
+
seekTimeInSeconds: number;
|
|
16
|
+
loopStartInSeconds: number;
|
|
17
|
+
segmentEndInSeconds: number;
|
|
18
|
+
maximumContinuousTimestamp: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function makeLoopingIterator({ audioSink, seekTimeInSeconds, loopStartInSeconds, segmentEndInSeconds, maximumContinuousTimestamp }: MakeLoopingIteratorOptions): AsyncGenerator<AudioBufferSlice, void, unknown>;
|
|
21
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.488",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"make": "tsgo && bun --env-file=../.env.bundle bundle.ts"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"mediabunny": "1.50.
|
|
26
|
-
"remotion": "4.0.
|
|
25
|
+
"mediabunny": "1.50.8",
|
|
26
|
+
"remotion": "4.0.488",
|
|
27
27
|
"zod": "4.3.6"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"react-dom": ">=16.8.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
35
|
-
"@remotion/player": "4.0.
|
|
34
|
+
"@remotion/eslint-config-internal": "4.0.488",
|
|
35
|
+
"@remotion/player": "4.0.488",
|
|
36
36
|
"@vitest/browser-webdriverio": "4.0.9",
|
|
37
37
|
"eslint": "9.19.0",
|
|
38
38
|
"react": "19.2.3",
|