@remotion/media 4.0.451 → 4.0.452

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.
@@ -37,12 +37,12 @@ var __callDispose = (stack, error, hasError) => {
37
37
  };
38
38
 
39
39
  // src/audio/audio.tsx
40
- import { Internals as Internals19, Sequence, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
40
+ import { Internals as Internals17, Sequence, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
41
41
 
42
42
  // src/audio/audio-for-preview.tsx
43
43
  import { useContext as useContext3, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
44
44
  import {
45
- Internals as Internals10,
45
+ Internals as Internals8,
46
46
  Audio as RemotionAudio,
47
47
  useBufferState,
48
48
  useCurrentFrame as useCurrentFrame2,
@@ -102,219 +102,123 @@ var calculateEndTime = ({
102
102
 
103
103
  // src/media-player.ts
104
104
  import { ALL_FORMATS, Input, UrlSource } from "mediabunny";
105
- import { Internals as Internals6 } from "remotion";
105
+ import { Internals as Internals4 } from "remotion";
106
106
 
107
107
  // src/audio-iterator-manager.ts
108
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";
113
-
114
- // src/helpers/round-to-4-digits.ts
115
- var roundTo4Digits = (timestamp) => {
116
- return Math.round(timestamp * 1000) / 1000;
117
- };
118
-
119
- // src/set-global-time-anchor.ts
120
109
  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;
110
+
111
+ // src/make-iterator-with-priming.ts
112
+ var AUDIO_PRIMING_SECONDS = 0.5;
113
+ async function* makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp) {
114
+ const primingStart = Math.max(0, timeToSeek - AUDIO_PRIMING_SECONDS);
115
+ const iterator = audioSink.buffers(primingStart, maximumTimestamp);
116
+ for await (const buffer of iterator) {
117
+ if (buffer.timestamp + buffer.duration <= timeToSeek) {
118
+ continue;
119
+ }
120
+ yield {
121
+ buffer,
122
+ timestamp: buffer.timestamp
123
+ };
134
124
  }
135
- if (debugAudioScheduling) {
136
- Internals2.Log.info({ logLevel, tag: "audio-scheduling" }, "Anchor changed from %s to %s with shift %s", audioSyncAnchor.value, newAnchor, shift);
125
+ }
126
+ async function* makeLoopingIterator({
127
+ audioSink,
128
+ segmentStartInSeconds,
129
+ segmentEndInSeconds,
130
+ playbackRate,
131
+ sequenceDurationInSeconds
132
+ }) {
133
+ const duration = segmentEndInSeconds - segmentStartInSeconds;
134
+ let iteration = 0;
135
+ let broken = false;
136
+ while (true) {
137
+ for await (const item of makeIteratorWithPrimingInner(audioSink, segmentStartInSeconds, segmentEndInSeconds)) {
138
+ const timestamp = item.timestamp + iteration * duration;
139
+ const endTimestamp = duration * iteration + (item.timestamp - segmentStartInSeconds + item.buffer.duration);
140
+ if (endTimestamp > sequenceDurationInSeconds * playbackRate) {
141
+ broken = true;
142
+ break;
143
+ }
144
+ yield {
145
+ buffer: item.buffer,
146
+ timestamp
147
+ };
148
+ }
149
+ if (broken) {
150
+ break;
151
+ }
152
+ iteration++;
153
+ }
154
+ }
155
+ var makeIteratorWithPriming = ({
156
+ audioSink,
157
+ timeToSeek,
158
+ maximumTimestamp,
159
+ loop,
160
+ playbackRate,
161
+ sequenceDurationInSeconds
162
+ }) => {
163
+ if (loop) {
164
+ return makeLoopingIterator({
165
+ audioSink,
166
+ segmentStartInSeconds: timeToSeek,
167
+ segmentEndInSeconds: maximumTimestamp,
168
+ playbackRate,
169
+ sequenceDurationInSeconds
170
+ });
137
171
  }
138
- audioSyncAnchor.value = newAnchor;
172
+ return makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp);
139
173
  };
140
174
 
141
175
  // src/audio/audio-preview-iterator.ts
176
+ var ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
142
177
  var makeAudioIterator = ({
143
178
  startFromSecond,
144
179
  maximumTimestamp,
145
- cache,
146
- debugAudioScheduling
180
+ audioSink,
181
+ loop,
182
+ playbackRate,
183
+ sequenceDurationInSeconds,
184
+ unscheduleAudioNode
147
185
  }) => {
148
186
  let destroyed = false;
149
- const iterator = cache.makeIteratorOrUsePrewarmed(startFromSecond, maximumTimestamp);
187
+ const iterator = makeIteratorWithPriming({
188
+ audioSink,
189
+ timeToSeek: startFromSecond,
190
+ maximumTimestamp,
191
+ loop,
192
+ playbackRate,
193
+ sequenceDurationInSeconds
194
+ });
150
195
  const queuedAudioNodes = [];
151
- const audioChunksForAfterResuming = [];
152
196
  let mostRecentTimestamp = -Infinity;
153
- let pendingNext = null;
154
- const cleanupAudioQueue = (audioContext) => {
197
+ const cleanupAudioQueue = () => {
155
198
  for (const node of queuedAudioNodes) {
156
- try {
157
- const isAlreadyPlaying = node.scheduledTime - ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT < audioContext.audioContext.currentTime;
158
- const wasScheduledForThisAnchor = node.scheduledAtAnchor === audioContext.audioSyncAnchor.value;
159
- if (isAlreadyPlaying && wasScheduledForThisAnchor) {
160
- continue;
161
- }
162
- if (debugAudioScheduling) {
163
- const currentlyHearing = audioContext.audioContext.getOutputTimestamp().contextTime;
164
- const nodeEndTime = node.scheduledTime + node.buffer.duration / node.playbackRate;
165
- Internals3.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, `Stopping node ${node.timestamp.toFixed(3)}, currently hearing = ${currentlyHearing.toFixed(3)} currentTime = ${audioContext.audioContext.currentTime.toFixed(3)} nodeEndTime = ${nodeEndTime.toFixed(3)} scheduledTime = ${node.scheduledTime.toFixed(3)}`);
166
- }
167
- node.node.stop();
168
- } catch {}
169
- }
170
- queuedAudioNodes.length = 0;
171
- };
172
- const getNextOrNullIfNotAvailable = async () => {
173
- let next = pendingNext;
174
- if (!next) {
175
- next = iterator.next();
176
- }
177
- pendingNext = null;
178
- const result = await Promise.race([
179
- next,
180
- new Promise((resolve) => {
181
- Promise.resolve().then(() => resolve());
182
- })
183
- ]);
184
- if (!result) {
185
- pendingNext = next;
186
- return {
187
- type: "need-to-wait-for-it",
188
- waitPromise: async () => {
189
- const res = await next;
190
- return res.value;
191
- }
192
- };
193
- }
194
- if (result.value) {
195
- mostRecentTimestamp = Math.max(mostRecentTimestamp, result.value.timestamp + result.value.duration);
196
- pendingNext = iterator.next();
197
- return {
198
- type: "got-buffer",
199
- buffer: result.value
200
- };
201
- }
202
- return {
203
- type: "got-end",
204
- mostRecentTimestamp
205
- };
206
- };
207
- const tryToSatisfySeek = async (time, onBufferScheduled) => {
208
- if (time < startFromSecond) {
209
- return {
210
- type: "not-satisfied",
211
- reason: `time requested is before the start of the iterator`
212
- };
213
- }
214
- while (true) {
215
- const buffer = await getNextOrNullIfNotAvailable();
216
- if (buffer.type === "need-to-wait-for-it") {
217
- return {
218
- type: "not-satisfied",
219
- reason: "iterator did not have buffer ready"
220
- };
221
- }
222
- if (buffer.type === "got-end") {
223
- if (time >= mostRecentTimestamp) {
224
- return {
225
- type: "ended"
226
- };
227
- }
228
- return {
229
- type: "not-satisfied",
230
- reason: `iterator ended before the requested time`
231
- };
232
- }
233
- if (buffer.type === "got-buffer") {
234
- const bufferTimestamp = roundTo4Digits(buffer.buffer.timestamp);
235
- const bufferEndTimestamp = roundTo4Digits(buffer.buffer.timestamp + buffer.buffer.duration);
236
- const timestamp = roundTo4Digits(time);
237
- if (timestamp < bufferTimestamp) {
238
- return {
239
- type: "not-satisfied",
240
- reason: `iterator is too far, most recently returned ${bufferTimestamp}-${bufferEndTimestamp}, requested ${timestamp}`
241
- };
242
- }
243
- if (bufferTimestamp <= timestamp && bufferEndTimestamp >= timestamp) {
244
- onBufferScheduled(buffer.buffer);
245
- return {
246
- type: "satisfied"
247
- };
248
- }
249
- onBufferScheduled(buffer.buffer);
250
- continue;
251
- }
252
- throw new Error("Unreachable");
253
- }
254
- };
255
- const bufferAsFarAsPossible = async (onBufferScheduled, maxTimestamp) => {
256
- while (true) {
257
- if (mostRecentTimestamp >= maxTimestamp) {
258
- return { type: "max-reached" };
259
- }
260
- const buffer = await getNextOrNullIfNotAvailable();
261
- if (buffer.type === "need-to-wait-for-it") {
262
- return { type: "waiting" };
263
- }
264
- if (buffer.type === "got-end") {
265
- return { type: "ended" };
266
- }
267
- if (buffer.type === "got-buffer") {
268
- onBufferScheduled(buffer.buffer);
269
- continue;
270
- }
271
- throw new Error("Unreachable");
272
- }
273
- };
274
- const removeAndReturnAllQueuedAudioNodes = () => {
275
- const nodes = queuedAudioNodes.slice();
276
- for (const node of nodes) {
199
+ unscheduleAudioNode(node.node);
277
200
  try {
278
201
  node.node.stop();
279
202
  } catch {}
280
203
  }
281
204
  queuedAudioNodes.length = 0;
282
- return nodes;
283
205
  };
284
- const addChunkForAfterResuming = (buffer, timestamp) => {
285
- audioChunksForAfterResuming.push({
286
- buffer,
287
- timestamp
288
- });
289
- };
290
- const moveQueuedChunksToPauseQueue = () => {
291
- const toQueue = removeAndReturnAllQueuedAudioNodes();
292
- for (const chunk of toQueue) {
293
- addChunkForAfterResuming(chunk.buffer, chunk.timestamp);
206
+ const getNextFn = async () => {
207
+ const next = await iterator.next();
208
+ if (next.value) {
209
+ mostRecentTimestamp = Math.max(mostRecentTimestamp, next.value.timestamp + next.value.buffer.duration);
294
210
  }
295
- if (debugAudioScheduling && toQueue.length > 0) {
296
- 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)})`);
297
- }
298
- };
299
- const getNumberOfChunksAfterResuming = () => {
300
- return audioChunksForAfterResuming.length;
211
+ return next;
301
212
  };
302
213
  return {
303
- destroy: (audioContext) => {
304
- cleanupAudioQueue(audioContext);
214
+ destroy: () => {
215
+ cleanupAudioQueue();
305
216
  destroyed = true;
306
217
  iterator.return().catch(() => {
307
218
  return;
308
219
  });
309
- audioChunksForAfterResuming.length = 0;
310
- },
311
- getNext: async () => {
312
- const next = await iterator.next();
313
- if (next.value) {
314
- mostRecentTimestamp = Math.max(mostRecentTimestamp, next.value.timestamp + next.value.duration);
315
- }
316
- return next;
317
220
  },
221
+ getNextFn,
318
222
  isDestroyed: () => {
319
223
  return destroyed;
320
224
  },
@@ -323,7 +227,6 @@ var makeAudioIterator = ({
323
227
  timestamp,
324
228
  buffer,
325
229
  scheduledTime,
326
- playbackRate,
327
230
  scheduledAtAnchor
328
231
  }) => {
329
232
  queuedAudioNodes.push({
@@ -335,16 +238,8 @@ var makeAudioIterator = ({
335
238
  scheduledAtAnchor
336
239
  });
337
240
  },
338
- removeQueuedAudioNode: (node) => {
339
- const index = queuedAudioNodes.findIndex((n) => n.node === node);
340
- if (index !== -1) {
341
- queuedAudioNodes.splice(index, 1);
342
- }
343
- },
344
- getAndClearAudioChunksForAfterResuming: () => {
345
- const chunks = audioChunksForAfterResuming.slice();
346
- audioChunksForAfterResuming.length = 0;
347
- return chunks;
241
+ guessNextTimestamp: () => {
242
+ return !Number.isFinite(mostRecentTimestamp) ? startFromSecond : mostRecentTimestamp;
348
243
  },
349
244
  getQueuedPeriod: () => {
350
245
  let until = -Infinity;
@@ -353,10 +248,6 @@ var makeAudioIterator = ({
353
248
  until = Math.max(until, node.timestamp + node.buffer.duration);
354
249
  from = Math.min(from, node.timestamp);
355
250
  }
356
- for (const chunk of audioChunksForAfterResuming) {
357
- until = Math.max(until, chunk.timestamp + chunk.buffer.duration);
358
- from = Math.min(from, chunk.timestamp);
359
- }
360
251
  if (!Number.isFinite(from) || !Number.isFinite(until)) {
361
252
  return null;
362
253
  }
@@ -364,12 +255,7 @@ var makeAudioIterator = ({
364
255
  from,
365
256
  until
366
257
  };
367
- },
368
- tryToSatisfySeek,
369
- bufferAsFarAsPossible,
370
- addChunkForAfterResuming,
371
- moveQueuedChunksToPauseQueue,
372
- getNumberOfChunksAfterResuming
258
+ }
373
259
  };
374
260
  };
375
261
  var isAlreadyQueued = (time, queuedPeriod) => {
@@ -379,224 +265,183 @@ var isAlreadyQueued = (time, queuedPeriod) => {
379
265
  return time >= queuedPeriod.from && time < queuedPeriod.until;
380
266
  };
381
267
 
382
- // src/make-iterator-with-priming.ts
383
- var AUDIO_PRIMING_SECONDS = 0.5;
384
- var PREDECODE_AHEAD_SECONDS = 2;
385
- function makePredecodingIterator(inner) {
386
- const buffer = [];
387
- let consumerEndTime = 0;
388
- let innerDone = false;
389
- let returned = false;
390
- let fetching = false;
391
- let waiter = null;
392
- const prefetch = () => {
393
- if (fetching || returned || innerDone) {
394
- return;
395
- }
396
- const lastBuffered = buffer.length > 0 ? buffer[buffer.length - 1] : null;
397
- const bufferedEndTime = lastBuffered ? lastBuffered.timestamp + lastBuffered.duration : consumerEndTime;
398
- if (bufferedEndTime >= consumerEndTime + PREDECODE_AHEAD_SECONDS) {
399
- return;
400
- }
401
- fetching = true;
402
- inner.next().then((result) => {
403
- fetching = false;
404
- if (returned) {
405
- return;
406
- }
407
- if (result.done) {
408
- innerDone = true;
409
- if (waiter) {
410
- const w = waiter;
411
- waiter = null;
412
- w({ value: undefined, done: true });
413
- }
414
- return;
415
- }
416
- if (waiter) {
417
- const w = waiter;
418
- waiter = null;
419
- const buf = result.value;
420
- consumerEndTime = buf.timestamp + buf.duration;
421
- w({ value: buf, done: false });
422
- prefetch();
423
- return;
424
- }
425
- buffer.push(result.value);
426
- prefetch();
427
- }, () => {
428
- fetching = false;
429
- innerDone = true;
430
- if (waiter) {
431
- const w = waiter;
432
- waiter = null;
433
- w({ value: undefined, done: true });
434
- }
435
- });
436
- };
437
- prefetch();
438
- const _return = () => {
439
- returned = true;
440
- buffer.length = 0;
441
- if (waiter) {
442
- const w = waiter;
443
- waiter = null;
444
- w({ value: undefined, done: true });
445
- }
446
- inner.return(undefined);
447
- return Promise.resolve({ value: undefined, done: true });
448
- };
449
- const iterator = {
450
- next() {
451
- if (buffer.length > 0) {
452
- const buf = buffer.shift();
453
- consumerEndTime = buf.timestamp + buf.duration;
454
- prefetch();
455
- return Promise.resolve({ value: buf, done: false });
456
- }
457
- if (innerDone) {
458
- return Promise.resolve({
459
- value: undefined,
460
- done: true
461
- });
462
- }
463
- return new Promise((resolve) => {
464
- waiter = resolve;
465
- prefetch();
466
- });
467
- },
468
- return: _return,
469
- throw(e) {
470
- returned = true;
471
- buffer.length = 0;
472
- return inner.throw(e);
473
- },
474
- [Symbol.asyncIterator]() {
475
- return iterator;
476
- }
477
- };
478
- return iterator;
479
- }
480
- async function* makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp) {
481
- const primingStart = Math.max(0, timeToSeek - AUDIO_PRIMING_SECONDS);
482
- const iterator = audioSink.buffers(primingStart, maximumTimestamp);
483
- for await (const buffer of iterator) {
484
- if (buffer.timestamp + buffer.duration <= timeToSeek) {
485
- continue;
486
- }
487
- yield buffer;
488
- }
489
- }
490
- var makeIteratorWithPriming = ({
491
- audioSink,
492
- timeToSeek,
493
- maximumTimestamp
268
+ // src/audio/get-scheduled-time.ts
269
+ var getScheduledTime = ({
270
+ mediaTimestamp,
271
+ targetTime,
272
+ currentTime,
273
+ sequenceStartTime
494
274
  }) => {
495
- return makePredecodingIterator(makeIteratorWithPrimingInner(audioSink, timeToSeek, maximumTimestamp));
275
+ const needsTrimStart = mediaTimestamp < sequenceStartTime;
276
+ const offsetBecauseOfTrim = needsTrimStart ? sequenceStartTime - mediaTimestamp : 0;
277
+ const offsetBecauseOfTooLate = targetTime < 0 ? -targetTime : 0;
278
+ const offset = offsetBecauseOfTrim + offsetBecauseOfTooLate;
279
+ const scheduledTime = targetTime + currentTime + offset;
280
+ return scheduledTime;
496
281
  };
497
-
498
- // src/prewarm-iterator-for-looping.ts
499
- var makePrewarmedVideoIteratorCache = (videoSink) => {
500
- const prewarmedVideoIterators = new Map;
501
- const prewarmIteratorForLooping = ({ timeToSeek }) => {
502
- if (!prewarmedVideoIterators.has(timeToSeek)) {
503
- prewarmedVideoIterators.set(timeToSeek, videoSink.canvases(timeToSeek));
504
- }
505
- };
506
- const makeIteratorOrUsePrewarmed = (timeToSeek) => {
507
- const prewarmedIterator = prewarmedVideoIterators.get(timeToSeek);
508
- if (prewarmedIterator) {
509
- prewarmedVideoIterators.delete(timeToSeek);
510
- return prewarmedIterator;
511
- }
512
- const iterator = videoSink.canvases(timeToSeek);
513
- return iterator;
514
- };
515
- const destroy = () => {
516
- for (const iterator of prewarmedVideoIterators.values()) {
517
- iterator.return();
518
- }
519
- prewarmedVideoIterators.clear();
520
- };
521
- return {
522
- prewarmIteratorForLooping,
523
- makeIteratorOrUsePrewarmed,
524
- destroy
525
- };
282
+ var getDurationOfNode = ({
283
+ bufferDuration,
284
+ loopSegmentMediaEndTimestamp,
285
+ offset,
286
+ originalUnloopedMediaTimestamp
287
+ }) => {
288
+ const originalUnloopedMediaEndTime = originalUnloopedMediaTimestamp + bufferDuration;
289
+ const needsTrimEnd = originalUnloopedMediaEndTime > loopSegmentMediaEndTimestamp;
290
+ const durationMinusOffset = bufferDuration - offset;
291
+ const duration = needsTrimEnd ? durationMinusOffset - Math.max(0, originalUnloopedMediaEndTime - loopSegmentMediaEndTimestamp) : durationMinusOffset;
292
+ return duration;
526
293
  };
527
- var makeKey = (timeToSeek, maximumTimestamp) => {
528
- return `${timeToSeek}-${maximumTimestamp}`;
294
+ var getOffset = ({
295
+ mediaTimestamp,
296
+ targetTime,
297
+ sequenceStartTime
298
+ }) => {
299
+ const needsTrimStart = mediaTimestamp < sequenceStartTime;
300
+ const offsetBecauseOfTrim = needsTrimStart ? sequenceStartTime - mediaTimestamp : 0;
301
+ const offsetBecauseOfTooLate = targetTime < 0 ? -targetTime : 0;
302
+ const offset = offsetBecauseOfTrim + offsetBecauseOfTooLate;
303
+ return offset;
529
304
  };
530
- var makePrewarmedAudioIteratorCache = (audioSink) => {
531
- const prewarmedAudioIterators = new Map;
532
- const prewarmIteratorForLooping = ({
533
- timeToSeek,
534
- maximumTimestamp
535
- }) => {
536
- if (!prewarmedAudioIterators.has(makeKey(timeToSeek, maximumTimestamp))) {
537
- prewarmedAudioIterators.set(makeKey(timeToSeek, maximumTimestamp), makeIteratorWithPriming({ audioSink, timeToSeek, maximumTimestamp }));
305
+
306
+ // src/audio/sort-by-priority.ts
307
+ class StaleWaiterError extends Error {
308
+ constructor() {
309
+ super("Waiter became stale before it got its turn");
310
+ this.name = "StaleWaiterError";
311
+ }
312
+ }
313
+ var CONCURRENCY = 1;
314
+ var waiters = [];
315
+ var running = 0;
316
+ var processNext = () => {
317
+ if (running >= CONCURRENCY) {
318
+ return;
319
+ }
320
+ const staleWaiters = [];
321
+ for (let i = waiters.length - 1;i >= 0; i--) {
322
+ if (waiters[i].getPriority() === null) {
323
+ const [stale] = waiters.splice(i, 1);
324
+ staleWaiters.push(stale);
538
325
  }
539
- };
540
- const makeIteratorOrUsePrewarmed = (timeToSeek, maximumTimestamp) => {
541
- const prewarmedIterator = prewarmedAudioIterators.get(makeKey(timeToSeek, maximumTimestamp));
542
- if (prewarmedIterator) {
543
- prewarmedAudioIterators.delete(makeKey(timeToSeek, maximumTimestamp));
544
- return prewarmedIterator;
326
+ }
327
+ for (const stale of staleWaiters) {
328
+ stale.onError(new StaleWaiterError);
329
+ }
330
+ if (waiters.length === 0) {
331
+ return;
332
+ }
333
+ let bestIndex = 0;
334
+ let bestPriority = waiters[0].getPriority();
335
+ if (bestPriority === null) {
336
+ throw new Error("Stale waiter should have been removed");
337
+ }
338
+ for (let i = 1;i < waiters.length; i++) {
339
+ const priority = waiters[i].getPriority();
340
+ if (priority === null) {
341
+ throw new Error("Stale waiter should have been removed");
545
342
  }
546
- const iterator = makeIteratorWithPriming({
547
- audioSink,
548
- timeToSeek,
549
- maximumTimestamp
550
- });
551
- return iterator;
552
- };
553
- const destroy = () => {
554
- for (const iterator of prewarmedAudioIterators.values()) {
555
- iterator.return();
343
+ if (priority < bestPriority) {
344
+ bestPriority = priority;
345
+ bestIndex = i;
556
346
  }
557
- prewarmedAudioIterators.clear();
558
- };
559
- return {
560
- prewarmIteratorForLooping,
561
- makeIteratorOrUsePrewarmed,
562
- destroy
563
- };
347
+ }
348
+ if (bestPriority > 2) {
349
+ return;
350
+ }
351
+ const [next] = waiters.splice(bestIndex, 1);
352
+ running++;
353
+ next.fn().then((value) => {
354
+ running--;
355
+ next.onDone(value, processNext);
356
+ }, (err) => {
357
+ running--;
358
+ next.onError(err);
359
+ });
360
+ };
361
+ var waitForTurn = ({
362
+ getPriority,
363
+ fn,
364
+ onDone,
365
+ onError
366
+ }) => {
367
+ waiters.push({
368
+ getPriority,
369
+ fn,
370
+ onDone,
371
+ onError
372
+ });
373
+ processNext();
564
374
  };
565
375
 
566
376
  // src/audio-iterator-manager.ts
567
- var MAX_BUFFER_AHEAD_SECONDS = 2;
568
377
  var audioIteratorManager = ({
569
378
  audioTrack,
570
379
  delayPlaybackHandleIfNotPremounting,
571
380
  sharedAudioContext,
572
- getIsLooping,
573
- getEndTime,
381
+ getSequenceEndTimestamp,
382
+ getSequenceDurationInSeconds,
383
+ getMediaEndTimestamp,
574
384
  getStartTime,
575
385
  initialMuted,
576
- drawDebugOverlay
386
+ drawDebugOverlay,
387
+ initialPlaybackRate,
388
+ initialTrimBefore,
389
+ initialTrimAfter,
390
+ initialSequenceOffset,
391
+ initialSequenceDurationInFrames,
392
+ initialLoop,
393
+ initialFps
577
394
  }) => {
578
395
  let muted = initialMuted;
579
396
  let currentVolume = 1;
397
+ let currentSeek = {
398
+ time: -1,
399
+ playbackRate: initialPlaybackRate,
400
+ trimBefore: initialTrimBefore,
401
+ trimAfter: initialTrimAfter,
402
+ sequenceOffset: initialSequenceOffset,
403
+ sequenceDurationInFrames: initialSequenceDurationInFrames,
404
+ loop: initialLoop,
405
+ fps: initialFps
406
+ };
580
407
  const gainNode = sharedAudioContext.audioContext.createGain();
581
- gainNode.connect(sharedAudioContext.audioContext.destination);
408
+ gainNode.connect(sharedAudioContext.gainNode);
582
409
  const audioSink = new AudioBufferSink(audioTrack);
583
- const prewarmedAudioIteratorCache = makePrewarmedAudioIteratorCache(audioSink);
584
410
  let audioBufferIterator = null;
585
411
  let audioIteratorsCreated = 0;
412
+ let totalAudioScheduledInSeconds = 0;
586
413
  let currentDelayHandle = null;
414
+ const pendingScheduleWaiters = [];
415
+ const notifyNodeScheduled = () => {
416
+ for (let i = pendingScheduleWaiters.length - 1;i >= 0; i--) {
417
+ const waiter = pendingScheduleWaiters[i];
418
+ waiter.remaining--;
419
+ if (waiter.remaining <= 0) {
420
+ waiter.resolve();
421
+ pendingScheduleWaiters.splice(i, 1);
422
+ }
423
+ }
424
+ };
425
+ const waitForNScheduledNodes = (n) => {
426
+ if (n <= 0) {
427
+ return Promise.resolve();
428
+ }
429
+ return new Promise((resolve) => {
430
+ pendingScheduleWaiters.push({ remaining: n, resolve });
431
+ });
432
+ };
587
433
  const scheduleAudioChunk = ({
588
434
  buffer,
589
435
  mediaTimestamp,
436
+ originalUnloopedMediaTimestamp,
590
437
  playbackRate,
591
438
  scheduleAudioNode,
592
- debugAudioScheduling
439
+ logLevel,
440
+ currentTime
593
441
  }) => {
594
442
  if (!audioBufferIterator) {
595
443
  throw new Error("Audio buffer iterator not found");
596
444
  }
597
- if (sharedAudioContext.audioContext.state !== "running") {
598
- throw new Error("Tried to schedule node while audio context is not running");
599
- }
600
445
  if (muted) {
601
446
  return;
602
447
  }
@@ -604,252 +449,247 @@ var audioIteratorManager = ({
604
449
  node.buffer = buffer;
605
450
  node.playbackRate.value = playbackRate;
606
451
  node.connect(gainNode);
607
- const started = scheduleAudioNode(node, mediaTimestamp);
452
+ const started = scheduleAudioNode(node, mediaTimestamp, originalUnloopedMediaTimestamp, currentTime);
608
453
  if (started.type === "not-started") {
609
- if (debugAudioScheduling) {
610
- Internals4.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, "not started, disconnected: %s %s", mediaTimestamp.toFixed(3), buffer.duration.toFixed(3));
611
- }
454
+ Internals2.Log.verbose({ logLevel, tag: "audio-scheduling" }, "not started, disconnected: %s %s", mediaTimestamp.toFixed(3), buffer.duration.toFixed(3));
612
455
  node.disconnect();
613
456
  return;
614
457
  }
615
- const iterator = audioBufferIterator;
616
- iterator.addQueuedAudioNode({
458
+ audioBufferIterator.addQueuedAudioNode({
617
459
  node,
618
460
  timestamp: mediaTimestamp,
619
461
  buffer,
620
462
  scheduledTime: started.scheduledTime,
621
- playbackRate,
622
463
  scheduledAtAnchor: sharedAudioContext.audioSyncAnchor.value
623
464
  });
624
- node.onended = () => {
625
- setTimeout(() => {
626
- iterator.removeQueuedAudioNode(node);
627
- }, 30);
628
- };
629
- };
630
- const resumeScheduledAudioChunks = ({
631
- playbackRate,
632
- scheduleAudioNode,
633
- debugAudioScheduling
634
- }) => {
635
- if (muted) {
636
- return;
637
- }
638
- if (!audioBufferIterator) {
639
- return;
640
- }
641
- for (const chunk of audioBufferIterator.getAndClearAudioChunksForAfterResuming()) {
642
- scheduleAudioChunk({
643
- buffer: chunk.buffer,
644
- mediaTimestamp: chunk.timestamp,
645
- playbackRate,
646
- scheduleAudioNode,
647
- debugAudioScheduling
648
- });
649
- }
650
465
  };
651
466
  const onAudioChunk = ({
652
- getIsPlaying,
653
467
  buffer,
654
468
  playbackRate,
655
469
  scheduleAudioNode,
656
- debugAudioScheduling
470
+ logLevel,
471
+ currentTime
657
472
  }) => {
658
473
  if (muted) {
659
474
  return;
660
475
  }
661
476
  const startTime = getStartTime();
662
- const endTime = getEndTime();
663
- if (buffer.timestamp + buffer.duration <= startTime) {
664
- return;
665
- }
666
- if (buffer.timestamp >= endTime) {
667
- return;
668
- }
669
- if (getIsPlaying() && sharedAudioContext.audioContext.state === "running" && (sharedAudioContext.audioContext.getOutputTimestamp().contextTime ?? 0) > 0) {
670
- resumeScheduledAudioChunks({
671
- playbackRate,
672
- scheduleAudioNode,
673
- debugAudioScheduling
674
- });
675
- scheduleAudioChunk({
676
- buffer: buffer.buffer,
677
- mediaTimestamp: buffer.timestamp,
678
- playbackRate,
679
- scheduleAudioNode,
680
- debugAudioScheduling
681
- });
682
- } else {
683
- if (!audioBufferIterator) {
684
- throw new Error("Audio buffer iterator not found");
685
- }
686
- if (debugAudioScheduling) {
687
- Internals4.Log.info({ logLevel: "trace", tag: "audio-scheduling" }, "not ready, added to queue: %s %s", buffer.timestamp.toFixed(3), buffer.duration.toFixed(3));
688
- }
689
- audioBufferIterator.addChunkForAfterResuming(buffer.buffer, buffer.timestamp);
477
+ const sequenceEndTime = getSequenceEndTimestamp();
478
+ if (buffer.timestamp + buffer.buffer.duration <= startTime) {
479
+ return;
480
+ }
481
+ if (buffer.timestamp >= sequenceEndTime) {
482
+ return;
690
483
  }
484
+ const scheduledStart = Math.max(buffer.timestamp, startTime);
485
+ const scheduledEnd = Math.min(buffer.timestamp + buffer.buffer.duration, sequenceEndTime);
486
+ totalAudioScheduledInSeconds += Math.max(0, scheduledEnd - scheduledStart);
487
+ scheduleAudioChunk({
488
+ buffer: buffer.buffer.buffer,
489
+ mediaTimestamp: buffer.timestamp,
490
+ playbackRate,
491
+ scheduleAudioNode,
492
+ logLevel,
493
+ originalUnloopedMediaTimestamp: buffer.buffer.timestamp,
494
+ currentTime
495
+ });
691
496
  drawDebugOverlay();
692
497
  };
693
- const startAudioIterator = async ({
498
+ const proceedScheduling = ({
499
+ iterator,
694
500
  nonce,
501
+ getTargetTime,
695
502
  playbackRate,
696
- startFromSecond,
697
- getIsPlaying,
698
503
  scheduleAudioNode,
699
- debugAudioScheduling
504
+ onScheduled,
505
+ onDestroyed,
506
+ onDone,
507
+ logLevel,
508
+ currentTime,
509
+ getAudioContextCurrentTimeMockedInTest
700
510
  }) => {
701
- let __stack = [];
702
- try {
703
- if (muted) {
704
- return;
705
- }
706
- audioBufferIterator?.destroy(sharedAudioContext);
707
- const delayHandle = __using(__stack, delayPlaybackHandleIfNotPremounting(), 0);
708
- currentDelayHandle = delayHandle;
709
- const iterator = makeAudioIterator({
710
- startFromSecond,
711
- maximumTimestamp: getEndTime(),
712
- cache: prewarmedAudioIteratorCache,
713
- debugAudioScheduling
714
- });
715
- audioIteratorsCreated++;
716
- audioBufferIterator = iterator;
717
- try {
718
- for (let i = 0;i < 6; i++) {
719
- const result = await iterator.getNext();
720
- if (iterator.isDestroyed()) {
721
- return;
722
- }
723
- if (nonce.isStale()) {
724
- return;
725
- }
726
- if (!result.value) {
727
- return;
728
- }
729
- onAudioChunk({
730
- getIsPlaying,
731
- buffer: result.value,
732
- playbackRate,
733
- scheduleAudioNode,
734
- debugAudioScheduling
735
- });
511
+ waitForTurn({
512
+ getPriority: () => {
513
+ if (iterator.isDestroyed()) {
514
+ return null;
736
515
  }
737
- await iterator.bufferAsFarAsPossible((buffer) => {
738
- if (!nonce.isStale()) {
739
- onAudioChunk({
740
- getIsPlaying,
741
- buffer,
742
- playbackRate,
743
- scheduleAudioNode,
744
- debugAudioScheduling
745
- });
746
- }
747
- }, Math.min(startFromSecond + MAX_BUFFER_AHEAD_SECONDS, getEndTime()));
748
- } catch (e) {
516
+ const guessedNextTimestamp = iterator.guessNextTimestamp();
517
+ const targetTime = getTargetTime(guessedNextTimestamp, currentTime);
518
+ if (targetTime === null) {
519
+ return null;
520
+ }
521
+ const scheduledTime = getScheduledTime({
522
+ mediaTimestamp: guessedNextTimestamp,
523
+ targetTime,
524
+ currentTime,
525
+ sequenceStartTime: getStartTime()
526
+ });
527
+ return scheduledTime - getAudioContextCurrentTimeMockedInTest();
528
+ },
529
+ fn: () => iterator.getNextFn(),
530
+ onDone: (result, next) => {
531
+ if (iterator.isDestroyed()) {
532
+ next();
533
+ onDestroyed();
534
+ return;
535
+ }
536
+ if (!result.value) {
537
+ next();
538
+ return;
539
+ }
540
+ onScheduled(result.value.timestamp);
541
+ notifyNodeScheduled();
542
+ onAudioChunk({
543
+ buffer: result.value,
544
+ playbackRate,
545
+ scheduleAudioNode,
546
+ logLevel,
547
+ currentTime
548
+ });
549
+ proceedScheduling({
550
+ iterator,
551
+ nonce,
552
+ getTargetTime,
553
+ playbackRate,
554
+ scheduleAudioNode,
555
+ onScheduled,
556
+ onDestroyed,
557
+ onDone,
558
+ logLevel,
559
+ currentTime,
560
+ getAudioContextCurrentTimeMockedInTest
561
+ });
562
+ next();
563
+ },
564
+ onError: (e) => {
749
565
  if (e instanceof InputDisposedError) {
750
566
  return;
751
567
  }
568
+ if (e instanceof StaleWaiterError) {
569
+ return;
570
+ }
752
571
  throw e;
753
572
  }
754
- } catch (_catch) {
755
- var _err = _catch, _hasErr = 1;
756
- } finally {
757
- __callDispose(__stack, _err, _hasErr);
758
- }
573
+ });
759
574
  };
760
- const pausePlayback = () => {
761
- if (!audioBufferIterator) {
575
+ const startAudioIterator = ({
576
+ nonce,
577
+ playbackRate,
578
+ startFromSecond,
579
+ scheduleAudioNode,
580
+ getTargetTime,
581
+ logLevel,
582
+ loop,
583
+ unscheduleAudioNode,
584
+ getAudioContextCurrentTimeMockedInTest
585
+ }) => {
586
+ if (muted) {
587
+ return;
588
+ }
589
+ const maximumTimestamp = getMediaEndTimestamp();
590
+ if (startFromSecond >= maximumTimestamp) {
762
591
  return;
763
592
  }
764
- audioBufferIterator.moveQueuedChunksToPauseQueue();
593
+ audioBufferIterator?.destroy();
594
+ const delayHandle = delayPlaybackHandleIfNotPremounting();
595
+ currentDelayHandle = delayHandle;
596
+ const iterator = makeAudioIterator({
597
+ startFromSecond,
598
+ maximumTimestamp,
599
+ audioSink,
600
+ logLevel,
601
+ loop,
602
+ playbackRate,
603
+ sequenceDurationInSeconds: getSequenceDurationInSeconds(),
604
+ unscheduleAudioNode
605
+ });
606
+ audioIteratorsCreated++;
607
+ audioBufferIterator = iterator;
608
+ proceedScheduling({
609
+ iterator,
610
+ nonce,
611
+ getTargetTime,
612
+ playbackRate,
613
+ scheduleAudioNode,
614
+ onScheduled: () => {
615
+ delayHandle.unblock();
616
+ },
617
+ onDestroyed: () => {
618
+ delayHandle.unblock();
619
+ },
620
+ onDone: () => {
621
+ delayHandle.unblock();
622
+ },
623
+ logLevel,
624
+ currentTime: sharedAudioContext.audioContext.currentTime,
625
+ getAudioContextCurrentTimeMockedInTest
626
+ });
765
627
  };
766
- const seek = async ({
628
+ const seek = ({
767
629
  newTime,
768
630
  nonce,
769
631
  playbackRate,
770
- getIsPlaying,
771
632
  scheduleAudioNode,
772
- debugAudioScheduling
633
+ getTargetTime,
634
+ logLevel,
635
+ loop,
636
+ trimBefore,
637
+ trimAfter,
638
+ sequenceOffset,
639
+ sequenceDurationInFrames,
640
+ fps,
641
+ getAudioContextCurrentTimeMockedInTest
773
642
  }) => {
774
- if (muted) {
643
+ if (currentSeek.time === newTime && currentSeek.playbackRate === playbackRate && currentSeek.trimBefore === trimBefore && currentSeek.trimAfter === trimAfter && currentSeek.sequenceOffset === sequenceOffset && currentSeek.sequenceDurationInFrames === sequenceDurationInFrames && currentSeek.loop === loop && currentSeek.fps === fps) {
775
644
  return;
776
645
  }
777
- if (getIsLooping()) {
778
- if (getEndTime() - newTime < 1) {
779
- prewarmedAudioIteratorCache.prewarmIteratorForLooping({
780
- timeToSeek: getStartTime(),
781
- maximumTimestamp: getEndTime()
782
- });
783
- }
784
- }
785
- if (!audioBufferIterator) {
786
- await startAudioIterator({
787
- nonce,
788
- playbackRate,
789
- startFromSecond: newTime,
790
- getIsPlaying,
791
- scheduleAudioNode,
792
- debugAudioScheduling
793
- });
646
+ currentSeek = {
647
+ time: newTime,
648
+ playbackRate,
649
+ trimBefore,
650
+ trimAfter,
651
+ sequenceOffset,
652
+ sequenceDurationInFrames,
653
+ loop,
654
+ fps
655
+ };
656
+ if (muted) {
794
657
  return;
795
658
  }
796
- const queuedPeriod = audioBufferIterator.getQueuedPeriod();
797
- const queuedPeriodMinusLatency = queuedPeriod ? {
798
- from: queuedPeriod.from - ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT - sharedAudioContext.audioContext.baseLatency - sharedAudioContext.audioContext.outputLatency,
799
- until: queuedPeriod.until
800
- } : null;
801
- const currentTimeIsAlreadyQueued = isAlreadyQueued(newTime, queuedPeriodMinusLatency);
802
- if (!currentTimeIsAlreadyQueued) {
803
- const audioSatisfyResult = await audioBufferIterator.tryToSatisfySeek(newTime, (buffer) => {
804
- if (!nonce.isStale()) {
805
- onAudioChunk({
806
- getIsPlaying,
807
- buffer,
808
- playbackRate,
809
- scheduleAudioNode,
810
- debugAudioScheduling
811
- });
812
- }
813
- });
814
- if (nonce.isStale()) {
815
- return;
816
- }
817
- if (audioSatisfyResult.type === "ended") {
659
+ if (audioBufferIterator && !audioBufferIterator.isDestroyed()) {
660
+ const queuedPeriod = audioBufferIterator.getQueuedPeriod();
661
+ const queuedPeriodMinusLatency = queuedPeriod ? {
662
+ from: queuedPeriod.from - ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT - sharedAudioContext.audioContext.baseLatency - sharedAudioContext.audioContext.outputLatency,
663
+ until: queuedPeriod.until
664
+ } : null;
665
+ const currentTimeIsAlreadyQueued = isAlreadyQueued(newTime, queuedPeriodMinusLatency);
666
+ if (currentTimeIsAlreadyQueued) {
667
+ processNext();
818
668
  return;
819
669
  }
820
- if (audioSatisfyResult.type === "not-satisfied") {
821
- await startAudioIterator({
822
- nonce,
823
- playbackRate,
824
- startFromSecond: newTime,
825
- getIsPlaying,
826
- scheduleAudioNode,
827
- debugAudioScheduling
828
- });
670
+ const currentIteratorTimestamp = audioBufferIterator.guessNextTimestamp();
671
+ if (currentIteratorTimestamp < newTime && Math.abs(currentIteratorTimestamp - newTime) < 1) {
672
+ processNext();
829
673
  return;
830
674
  }
831
- if (audioSatisfyResult.type === "satisfied") {}
832
675
  }
833
- await audioBufferIterator.bufferAsFarAsPossible((buffer) => {
834
- if (!nonce.isStale()) {
835
- onAudioChunk({
836
- getIsPlaying,
837
- buffer,
838
- playbackRate,
839
- scheduleAudioNode,
840
- debugAudioScheduling
841
- });
842
- }
843
- }, Math.min(newTime + MAX_BUFFER_AHEAD_SECONDS, getEndTime()));
676
+ startAudioIterator({
677
+ nonce,
678
+ playbackRate,
679
+ startFromSecond: newTime,
680
+ scheduleAudioNode,
681
+ getTargetTime,
682
+ logLevel,
683
+ loop,
684
+ unscheduleAudioNode: sharedAudioContext.unscheduleAudioNode,
685
+ getAudioContextCurrentTimeMockedInTest
686
+ });
844
687
  };
845
688
  return {
846
689
  startAudioIterator,
847
- resumeScheduledAudioChunks,
848
- pausePlayback,
849
690
  getAudioBufferIterator: () => audioBufferIterator,
850
691
  destroyIterator: () => {
851
- prewarmedAudioIteratorCache.destroy();
852
- audioBufferIterator?.destroy(sharedAudioContext);
692
+ audioBufferIterator?.destroy();
853
693
  audioBufferIterator = null;
854
694
  if (currentDelayHandle) {
855
695
  currentDelayHandle.unblock();
@@ -858,6 +698,7 @@ var audioIteratorManager = ({
858
698
  },
859
699
  seek,
860
700
  getAudioIteratorsCreated: () => audioIteratorsCreated,
701
+ getTotalAudioScheduledInSeconds: () => totalAudioScheduledInSeconds,
861
702
  setMuted: (newMuted) => {
862
703
  muted = newMuted;
863
704
  gainNode.gain.value = muted ? 0 : currentVolume;
@@ -866,7 +707,8 @@ var audioIteratorManager = ({
866
707
  currentVolume = Math.max(0, volume);
867
708
  gainNode.gain.value = muted ? 0 : currentVolume;
868
709
  },
869
- scheduleAudioChunk
710
+ scheduleAudioChunk,
711
+ waitForNScheduledNodes
870
712
  };
871
713
  };
872
714
 
@@ -886,6 +728,7 @@ var drawPreviewOverlay = ({
886
728
  "Debug overlay",
887
729
  `Video iterators created: ${videoIteratorManager?.getVideoIteratorsCreated()}`,
888
730
  `Audio iterators created: ${audioIteratorManager2?.getAudioIteratorsCreated()}`,
731
+ `Audio scheduled: ${(audioIteratorManager2?.getTotalAudioScheduledInSeconds() ?? 0).toFixed(3)}s`,
889
732
  `Frames rendered: ${videoIteratorManager?.getFramesRendered()}`,
890
733
  `Audio context state: ${audioContextState}`,
891
734
  audioTime ? `Audio time: ${((audioTime - anchorValue) * playbackRate).toFixed(3)}s` : null
@@ -943,7 +786,42 @@ var makeNonceManager = () => {
943
786
 
944
787
  // src/video-iterator-manager.ts
945
788
  import { CanvasSink } from "mediabunny";
946
- import { Internals as Internals5 } from "remotion";
789
+ import { Internals as Internals3 } from "remotion";
790
+
791
+ // src/prewarm-iterator-for-looping.ts
792
+ var makePrewarmedVideoIteratorCache = (videoSink) => {
793
+ const prewarmedVideoIterators = new Map;
794
+ const prewarmIteratorForLooping = ({ timeToSeek }) => {
795
+ if (!prewarmedVideoIterators.has(timeToSeek)) {
796
+ prewarmedVideoIterators.set(timeToSeek, videoSink.canvases(timeToSeek));
797
+ }
798
+ };
799
+ const makeIteratorOrUsePrewarmed = (timeToSeek) => {
800
+ const prewarmedIterator = prewarmedVideoIterators.get(timeToSeek);
801
+ if (prewarmedIterator) {
802
+ prewarmedVideoIterators.delete(timeToSeek);
803
+ return prewarmedIterator;
804
+ }
805
+ const iterator = videoSink.canvases(timeToSeek);
806
+ return iterator;
807
+ };
808
+ const destroy = () => {
809
+ for (const iterator of prewarmedVideoIterators.values()) {
810
+ iterator.return();
811
+ }
812
+ prewarmedVideoIterators.clear();
813
+ };
814
+ return {
815
+ prewarmIteratorForLooping,
816
+ makeIteratorOrUsePrewarmed,
817
+ destroy
818
+ };
819
+ };
820
+
821
+ // src/helpers/round-to-4-digits.ts
822
+ var roundTo4Digits = (timestamp) => {
823
+ return Math.round(timestamp * 1000) / 1000;
824
+ };
947
825
 
948
826
  // src/video/video-preview-iterator.ts
949
827
  var createVideoIterator = async (timeToSeek, cache) => {
@@ -1084,7 +962,7 @@ var videoIteratorManager = ({
1084
962
  logLevel,
1085
963
  getOnVideoFrameCallback,
1086
964
  videoTrack,
1087
- getEndTime,
965
+ getLoopSegmentMediaEndTimestamp,
1088
966
  getStartTime,
1089
967
  getIsLooping
1090
968
  }) => {
@@ -1115,7 +993,7 @@ var videoIteratorManager = ({
1115
993
  if (callback) {
1116
994
  callback(frame.canvas);
1117
995
  }
1118
- Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew frame ${frame.timestamp.toFixed(3)}s`);
996
+ Internals3.Log.trace({ logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew frame ${frame.timestamp.toFixed(3)}s`);
1119
997
  };
1120
998
  const startVideoIterator = async (timeToSeek, nonce) => {
1121
999
  let __stack = [];
@@ -1150,7 +1028,7 @@ var videoIteratorManager = ({
1150
1028
  return;
1151
1029
  }
1152
1030
  if (getIsLooping()) {
1153
- if (getEndTime() - newTime < 1) {
1031
+ if (getLoopSegmentMediaEndTimestamp() - newTime < 1) {
1154
1032
  prewarmedVideoIteratorCache.prewarmIteratorForLooping({
1155
1033
  timeToSeek: getStartTime()
1156
1034
  });
@@ -1200,16 +1078,15 @@ class MediaPlayer {
1200
1078
  sharedAudioContext;
1201
1079
  audioIteratorManager = null;
1202
1080
  videoIteratorManager = null;
1203
- sequenceOffset;
1204
1081
  playing = false;
1205
1082
  loop = false;
1206
1083
  fps;
1207
1084
  trimBefore;
1208
1085
  trimAfter;
1209
- durationInFrames;
1086
+ sequenceDurationInFrames;
1087
+ sequenceOffset;
1210
1088
  totalDuration;
1211
1089
  debugOverlay = false;
1212
- debugAudioScheduling = false;
1213
1090
  nonceManager;
1214
1091
  onVideoFrameCallback = null;
1215
1092
  initializationPromise = null;
@@ -1230,7 +1107,6 @@ class MediaPlayer {
1230
1107
  audioStreamIndex,
1231
1108
  fps,
1232
1109
  debugOverlay,
1233
- debugAudioScheduling,
1234
1110
  bufferState,
1235
1111
  isPremounting,
1236
1112
  isPostmounting,
@@ -1252,11 +1128,10 @@ class MediaPlayer {
1252
1128
  this.audioStreamIndex = audioStreamIndex ?? 0;
1253
1129
  this.fps = fps;
1254
1130
  this.debugOverlay = debugOverlay;
1255
- this.debugAudioScheduling = debugAudioScheduling;
1256
1131
  this.bufferState = bufferState;
1257
1132
  this.isPremounting = isPremounting;
1258
1133
  this.isPostmounting = isPostmounting;
1259
- this.durationInFrames = durationInFrames;
1134
+ this.sequenceDurationInFrames = durationInFrames;
1260
1135
  this.nonceManager = makeNonceManager();
1261
1136
  this.onVideoFrameCallback = onVideoFrameCallback;
1262
1137
  this.playing = playing;
@@ -1293,8 +1168,14 @@ class MediaPlayer {
1293
1168
  getStartTime() {
1294
1169
  return (this.trimBefore ?? 0) / this.fps;
1295
1170
  }
1296
- getEndTime() {
1297
- const mediaEndTime = calculateEndTime({
1171
+ getSequenceEndTimestamp() {
1172
+ return this.sequenceDurationInFrames / this.fps * this.playbackRate + this.getStartTime();
1173
+ }
1174
+ getSequenceDurationInSeconds() {
1175
+ return this.sequenceDurationInFrames / this.fps;
1176
+ }
1177
+ getMediaEndTimestamp() {
1178
+ return calculateEndTime({
1298
1179
  mediaDurationInSeconds: this.totalDuration,
1299
1180
  ifNoMediaDuration: "fail",
1300
1181
  src: this.src,
@@ -1302,11 +1183,9 @@ class MediaPlayer {
1302
1183
  trimBefore: this.trimBefore,
1303
1184
  fps: this.fps
1304
1185
  });
1305
- if (this.loop) {
1306
- return mediaEndTime;
1307
- }
1308
- const sequenceEndMediaTime = this.durationInFrames / this.fps * this.playbackRate + (this.trimBefore ?? 0) / this.fps;
1309
- return Math.min(mediaEndTime, sequenceEndMediaTime);
1186
+ }
1187
+ getLoopSegmentMediaEndTimestamp() {
1188
+ return Math.min(this.getMediaEndTimestamp(), this.getSequenceEndTimestamp());
1310
1189
  }
1311
1190
  async _initialize(startTimeUnresolved, initialMuted) {
1312
1191
  let __stack = [];
@@ -1326,7 +1205,7 @@ class MediaPlayer {
1326
1205
  if (isNetworkError(err)) {
1327
1206
  throw error;
1328
1207
  }
1329
- Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
1208
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
1330
1209
  return { type: "unknown-container-format" };
1331
1210
  }
1332
1211
  const [durationInSeconds, videoTrack, audioTracks] = await Promise.all([
@@ -1358,7 +1237,7 @@ class MediaPlayer {
1358
1237
  getOnVideoFrameCallback: () => this.onVideoFrameCallback,
1359
1238
  logLevel: this.logLevel,
1360
1239
  drawDebugOverlay: this.drawDebugOverlay,
1361
- getEndTime: () => this.getEndTime(),
1240
+ getLoopSegmentMediaEndTimestamp: () => this.getLoopSegmentMediaEndTimestamp(),
1362
1241
  getStartTime: () => this.getStartTime(),
1363
1242
  getIsLooping: () => this.loop
1364
1243
  });
@@ -1379,11 +1258,19 @@ class MediaPlayer {
1379
1258
  audioTrack,
1380
1259
  delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
1381
1260
  sharedAudioContext: this.sharedAudioContext,
1382
- getIsLooping: () => this.loop,
1383
- getEndTime: () => this.getEndTime(),
1261
+ getMediaEndTimestamp: () => this.getMediaEndTimestamp(),
1262
+ getSequenceEndTimestamp: () => this.getSequenceEndTimestamp(),
1384
1263
  getStartTime: () => this.getStartTime(),
1385
1264
  initialMuted,
1386
- drawDebugOverlay: this.drawDebugOverlay
1265
+ drawDebugOverlay: this.drawDebugOverlay,
1266
+ initialPlaybackRate: this.playbackRate * this.globalPlaybackRate,
1267
+ getSequenceDurationInSeconds: () => this.getSequenceDurationInSeconds(),
1268
+ initialTrimBefore: this.trimBefore,
1269
+ initialTrimAfter: this.trimAfter,
1270
+ initialSequenceOffset: this.sequenceOffset,
1271
+ initialSequenceDurationInFrames: this.sequenceDurationInFrames,
1272
+ initialLoop: this.loop,
1273
+ initialFps: this.fps
1387
1274
  });
1388
1275
  }
1389
1276
  const nonce = this.nonceManager.createAsyncOperation();
@@ -1393,9 +1280,12 @@ class MediaPlayer {
1393
1280
  nonce,
1394
1281
  playbackRate: this.playbackRate * this.globalPlaybackRate,
1395
1282
  startFromSecond: startTime,
1396
- getIsPlaying: () => this.playing,
1397
1283
  scheduleAudioNode: this.scheduleAudioNode,
1398
- debugAudioScheduling: this.debugAudioScheduling
1284
+ getTargetTime: this.getTargetTime,
1285
+ logLevel: this.logLevel,
1286
+ loop: this.loop,
1287
+ unscheduleAudioNode: this.sharedAudioContext.unscheduleAudioNode,
1288
+ getAudioContextCurrentTimeMockedInTest: () => this.sharedAudioContext.audioContext.currentTime
1399
1289
  }) : Promise.resolve(),
1400
1290
  this.videoIteratorManager ? this.videoIteratorManager.startVideoIterator(startTime, nonce) : Promise.resolve()
1401
1291
  ]);
@@ -1403,16 +1293,16 @@ class MediaPlayer {
1403
1293
  if (this.isDisposalError()) {
1404
1294
  return { type: "disposed" };
1405
1295
  }
1406
- Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start audio and video iterators", error);
1296
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start audio and video iterators", error);
1407
1297
  }
1408
1298
  return { type: "success", durationInSeconds };
1409
1299
  } catch (error) {
1410
1300
  const err = error;
1411
1301
  if (isNetworkError(err)) {
1412
- Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
1302
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
1413
1303
  return { type: "network-error" };
1414
1304
  }
1415
- Internals6.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to initialize", error);
1305
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to initialize", error);
1416
1306
  throw error;
1417
1307
  }
1418
1308
  } catch (_catch) {
@@ -1438,21 +1328,27 @@ class MediaPlayer {
1438
1328
  if (nonce.isStale()) {
1439
1329
  return;
1440
1330
  }
1441
- const shouldSeekAudio = this.audioIteratorManager && this.getAudioPlaybackTime(this.sharedAudioContext?.audioContext.currentTime ?? 0) !== newTime;
1442
1331
  try {
1443
1332
  await Promise.all([
1444
1333
  this.videoIteratorManager?.seek({
1445
1334
  newTime,
1446
1335
  nonce
1447
1336
  }),
1448
- shouldSeekAudio ? this.audioIteratorManager?.seek({
1337
+ this.audioIteratorManager?.seek({
1449
1338
  newTime,
1450
1339
  nonce,
1451
1340
  playbackRate: this.playbackRate * this.globalPlaybackRate,
1452
- getIsPlaying: () => this.playing,
1341
+ getTargetTime: this.getTargetTime,
1342
+ logLevel: this.logLevel,
1343
+ loop: this.loop,
1344
+ trimBefore: this.trimBefore,
1345
+ trimAfter: this.trimAfter,
1346
+ sequenceOffset: this.sequenceOffset,
1347
+ sequenceDurationInFrames: this.sequenceDurationInFrames,
1348
+ fps: this.fps,
1453
1349
  scheduleAudioNode: this.scheduleAudioNode,
1454
- debugAudioScheduling: this.debugAudioScheduling
1455
- }) : null
1350
+ getAudioContextCurrentTimeMockedInTest: () => this.sharedAudioContext.audioContext.currentTime
1351
+ })
1456
1352
  ]);
1457
1353
  } catch (error) {
1458
1354
  if (this.isDisposalError()) {
@@ -1461,17 +1357,7 @@ class MediaPlayer {
1461
1357
  throw error;
1462
1358
  }
1463
1359
  }
1464
- playAudio() {
1465
- if (this.audioIteratorManager && this.sharedAudioContext?.audioContext.state === "running" && (this.sharedAudioContext?.audioContext?.getOutputTimestamp().contextTime ?? 0) > 0) {
1466
- this.audioIteratorManager.resumeScheduledAudioChunks({
1467
- playbackRate: this.playbackRate * this.globalPlaybackRate,
1468
- scheduleAudioNode: this.scheduleAudioNode,
1469
- debugAudioScheduling: this.debugAudioScheduling
1470
- });
1471
- }
1472
- }
1473
1360
  play() {
1474
- this.playAudio();
1475
1361
  if (this.playing) {
1476
1362
  return;
1477
1363
  }
@@ -1498,7 +1384,6 @@ class MediaPlayer {
1498
1384
  return;
1499
1385
  }
1500
1386
  this.playing = false;
1501
- this.audioIteratorManager?.pausePlayback();
1502
1387
  this.drawDebugOverlay();
1503
1388
  }
1504
1389
  setMuted(muted) {
@@ -1523,73 +1408,46 @@ class MediaPlayer {
1523
1408
  src: this.src
1524
1409
  });
1525
1410
  }
1526
- async updateAfterTrimChange(unloopedTimeInSeconds) {
1527
- if (!this.audioIteratorManager && !this.videoIteratorManager) {
1528
- return;
1529
- }
1530
- const newMediaTime = this.getTrimmedTime(unloopedTimeInSeconds);
1531
- this.audioIteratorManager?.destroyIterator();
1532
- if (newMediaTime !== null) {
1533
- if (!this.playing && this.videoIteratorManager) {
1534
- await this.seekToWithQueue(newMediaTime);
1535
- }
1536
- }
1537
- }
1538
1411
  async setTrimBefore(trimBefore, unloopedTimeInSeconds) {
1539
1412
  if (this.trimBefore !== trimBefore) {
1540
1413
  this.trimBefore = trimBefore;
1541
- await this.updateAfterTrimChange(unloopedTimeInSeconds);
1414
+ this.audioIteratorManager?.destroyIterator();
1415
+ await this.seekTo(unloopedTimeInSeconds);
1542
1416
  }
1543
1417
  }
1544
1418
  async setTrimAfter(trimAfter, unloopedTimeInSeconds) {
1545
1419
  if (this.trimAfter !== trimAfter) {
1546
1420
  this.trimAfter = trimAfter;
1547
- await this.updateAfterTrimChange(unloopedTimeInSeconds);
1421
+ this.audioIteratorManager?.destroyIterator();
1422
+ await this.seekTo(unloopedTimeInSeconds);
1548
1423
  }
1549
1424
  }
1550
1425
  setDebugOverlay(debugOverlay) {
1551
1426
  this.debugOverlay = debugOverlay;
1552
1427
  }
1553
- setDebugAudioScheduling(debugAudioScheduling) {
1554
- this.debugAudioScheduling = debugAudioScheduling;
1555
- }
1556
- rescheduleAudioChunks() {
1557
- if (!this.audioIteratorManager) {
1558
- return;
1559
- }
1560
- if (!this.sharedAudioContext) {
1561
- return;
1562
- }
1563
- const iterator = this.audioIteratorManager.getAudioBufferIterator();
1564
- if (!iterator) {
1565
- return;
1566
- }
1567
- iterator.moveQueuedChunksToPauseQueue();
1568
- if (this.playing && this.sharedAudioContext.audioContext.state === "running" && (this.sharedAudioContext.audioContext?.getOutputTimestamp().contextTime ?? 0) > 0) {
1569
- this.audioIteratorManager.resumeScheduledAudioChunks({
1570
- playbackRate: this.playbackRate * this.globalPlaybackRate,
1571
- scheduleAudioNode: this.scheduleAudioNode,
1572
- debugAudioScheduling: this.debugAudioScheduling
1573
- });
1574
- }
1575
- }
1576
1428
  async setPlaybackRate(rate, unloopedTimeInSeconds) {
1577
1429
  const previousRate = this.playbackRate;
1578
1430
  if (previousRate !== rate) {
1579
1431
  this.playbackRate = rate;
1580
- this.rescheduleAudioChunks();
1432
+ this.audioIteratorManager?.destroyIterator();
1581
1433
  await this.seekTo(unloopedTimeInSeconds);
1582
1434
  }
1583
1435
  }
1584
- setGlobalPlaybackRate(rate) {
1436
+ async setGlobalPlaybackRate(rate, unloopedTimeInSeconds) {
1585
1437
  const previousRate = this.globalPlaybackRate;
1586
1438
  if (previousRate !== rate) {
1587
1439
  this.globalPlaybackRate = rate;
1588
- this.rescheduleAudioChunks();
1440
+ this.audioIteratorManager?.destroyIterator();
1441
+ await this.seekTo(unloopedTimeInSeconds);
1589
1442
  }
1590
1443
  }
1591
- setFps(fps) {
1592
- this.fps = fps;
1444
+ async setFps(fps, unloopedTimeInSeconds) {
1445
+ const previousFps = this.fps;
1446
+ if (previousFps !== fps) {
1447
+ this.fps = fps;
1448
+ this.audioIteratorManager?.destroyIterator();
1449
+ await this.seekTo(unloopedTimeInSeconds);
1450
+ }
1593
1451
  }
1594
1452
  setIsPremounting(isPremounting) {
1595
1453
  this.isPremounting = isPremounting;
@@ -1597,14 +1455,28 @@ class MediaPlayer {
1597
1455
  setIsPostmounting(isPostmounting) {
1598
1456
  this.isPostmounting = isPostmounting;
1599
1457
  }
1600
- setLoop(loop) {
1601
- this.loop = loop;
1458
+ async setLoop(loop, unloopedTimeInSeconds) {
1459
+ const previousLoop = this.loop;
1460
+ if (previousLoop !== loop) {
1461
+ this.loop = loop;
1462
+ this.audioIteratorManager?.destroyIterator();
1463
+ await this.seekTo(unloopedTimeInSeconds);
1464
+ }
1602
1465
  }
1603
- setSequenceOffset(offset) {
1604
- this.sequenceOffset = offset;
1466
+ async setSequenceOffset(offset, unloopedTimeInSeconds) {
1467
+ const previousOffset = this.sequenceOffset;
1468
+ if (previousOffset !== offset) {
1469
+ this.sequenceOffset = offset;
1470
+ this.audioIteratorManager?.destroyIterator();
1471
+ await this.seekTo(unloopedTimeInSeconds);
1472
+ }
1605
1473
  }
1606
- setDurationInFrames(durationInFrames) {
1607
- this.durationInFrames = durationInFrames;
1474
+ async setSequenceDurationInFrames(sequenceDurationInFrames, unloopedTimeInSeconds) {
1475
+ const previousDuration = this.sequenceDurationInFrames;
1476
+ if (previousDuration !== sequenceDurationInFrames) {
1477
+ this.sequenceDurationInFrames = sequenceDurationInFrames;
1478
+ await this.seekTo(unloopedTimeInSeconds);
1479
+ }
1608
1480
  }
1609
1481
  async dispose() {
1610
1482
  if (this.initializationPromise) {
@@ -1617,41 +1489,59 @@ class MediaPlayer {
1617
1489
  this.audioIteratorManager?.destroyIterator();
1618
1490
  this.input.dispose();
1619
1491
  }
1620
- scheduleAudioNode = (node, mediaTimestamp) => {
1492
+ getTargetTime = (mediaTimestamp, currentTime) => {
1621
1493
  if (!this.sharedAudioContext) {
1622
1494
  throw new Error("Shared audio context not found");
1623
1495
  }
1624
- const { audioContext } = this.sharedAudioContext;
1625
- const { currentTime } = audioContext;
1626
1496
  const globalTime = (currentTime - this.sharedAudioContext.audioSyncAnchor.value) * this.globalPlaybackRate;
1627
1497
  const timeInSeconds = globalTime - this.sequenceOffset;
1628
1498
  const localTime = this.getTrimmedTime(timeInSeconds);
1629
1499
  if (localTime === null) {
1630
- return { type: "not-started" };
1500
+ return null;
1631
1501
  }
1632
1502
  const targetTime = (mediaTimestamp - localTime) / (this.playbackRate * this.globalPlaybackRate);
1503
+ return targetTime;
1504
+ };
1505
+ scheduleAudioNode = (node, mediaTimestamp, originalUnloopedMediaTimestamp, currentTime) => {
1506
+ if (!this.sharedAudioContext) {
1507
+ throw new Error("Shared audio context not found");
1508
+ }
1509
+ const targetTime = this.getTargetTime(mediaTimestamp, currentTime);
1510
+ if (targetTime === null) {
1511
+ return {
1512
+ type: "not-started",
1513
+ reason: "no target for" + mediaTimestamp.toFixed(3) + "," + currentTime.toFixed(3)
1514
+ };
1515
+ }
1516
+ const sequenceStartTime = this.getStartTime();
1517
+ const loopSegmentMediaEndTimestamp = this.getLoopSegmentMediaEndTimestamp();
1518
+ const offset = getOffset({
1519
+ mediaTimestamp,
1520
+ targetTime,
1521
+ sequenceStartTime
1522
+ });
1523
+ const duration = getDurationOfNode({
1524
+ bufferDuration: node.buffer?.duration ?? 0,
1525
+ loopSegmentMediaEndTimestamp,
1526
+ offset,
1527
+ originalUnloopedMediaTimestamp
1528
+ });
1529
+ const scheduledTime = getScheduledTime({
1530
+ mediaTimestamp,
1531
+ targetTime,
1532
+ currentTime,
1533
+ sequenceStartTime
1534
+ });
1633
1535
  return this.sharedAudioContext.scheduleAudioNode({
1634
1536
  node,
1635
1537
  mediaTimestamp,
1636
- targetTime,
1637
1538
  currentTime,
1638
- sequenceEndTime: this.getEndTime(),
1639
- sequenceStartTime: this.getStartTime(),
1640
- debugAudioScheduling: this.debugAudioScheduling
1539
+ scheduledTime,
1540
+ duration,
1541
+ offset,
1542
+ originalUnloopedMediaTimestamp
1641
1543
  });
1642
1544
  };
1643
- getAudioPlaybackTime(currentTime) {
1644
- if (!this.sharedAudioContext) {
1645
- throw new Error("Shared audio context not found");
1646
- }
1647
- const globalTime = (currentTime - this.sharedAudioContext.audioSyncAnchor.value) * this.globalPlaybackRate;
1648
- const localTime = globalTime - this.sequenceOffset;
1649
- const trimmedTime = this.getTrimmedTime(localTime);
1650
- if (trimmedTime !== null) {
1651
- return trimmedTime;
1652
- }
1653
- return localTime * this.playbackRate + (this.trimBefore ?? 0) / this.fps;
1654
- }
1655
1545
  setVideoFrameCallback(callback) {
1656
1546
  this.onVideoFrameCallback = callback;
1657
1547
  }
@@ -1671,6 +1561,12 @@ class MediaPlayer {
1671
1561
  });
1672
1562
  }
1673
1563
  };
1564
+ audioSyncAnchorChanged = () => {
1565
+ if (!this.audioIteratorManager) {
1566
+ return;
1567
+ }
1568
+ this.audioIteratorManager.destroyIterator();
1569
+ };
1674
1570
  }
1675
1571
 
1676
1572
  // src/on-error.ts
@@ -1696,7 +1592,7 @@ var callOnErrorAndResolve = ({
1696
1592
 
1697
1593
  // src/show-in-timeline.ts
1698
1594
  import { useMemo } from "react";
1699
- import { Internals as Internals7, useVideoConfig } from "remotion";
1595
+ import { Internals as Internals5, useVideoConfig } from "remotion";
1700
1596
  var useLoopDisplay = ({
1701
1597
  loop,
1702
1598
  mediaDurationInSeconds,
@@ -1709,7 +1605,7 @@ var useLoopDisplay = ({
1709
1605
  if (!loop || !mediaDurationInSeconds) {
1710
1606
  return;
1711
1607
  }
1712
- const durationInFrames = Internals7.calculateMediaDuration({
1608
+ const durationInFrames = Internals5.calculateMediaDuration({
1713
1609
  mediaDurationInFrames: mediaDurationInSeconds * fps,
1714
1610
  playbackRate,
1715
1611
  trimAfter,
@@ -1735,7 +1631,7 @@ var useLoopDisplay = ({
1735
1631
 
1736
1632
  // src/use-common-effects.ts
1737
1633
  import { useContext, useLayoutEffect } from "react";
1738
- import { Internals as Internals8 } from "remotion";
1634
+ import { Internals as Internals6 } from "remotion";
1739
1635
  var useCommonEffects = ({
1740
1636
  mediaPlayerRef,
1741
1637
  mediaPlayerReady,
@@ -1752,39 +1648,14 @@ var useCommonEffects = ({
1752
1648
  fps,
1753
1649
  sequenceOffset,
1754
1650
  loop,
1755
- debugAudioScheduling,
1756
1651
  durationInFrames,
1757
1652
  isPremounting,
1758
1653
  isPostmounting,
1759
1654
  currentTime,
1760
1655
  logLevel,
1761
- sharedAudioContext,
1762
1656
  label
1763
1657
  }) => {
1764
- const absoluteTime = Internals8.useAbsoluteTimelinePosition();
1765
- const { playing: playingWhilePremounting } = useContext(Internals8.PremountContext);
1766
- useLayoutEffect(() => {
1767
- if (sharedAudioContext?.audioContext && sharedAudioContext.audioSyncAnchor) {
1768
- setGlobalTimeAnchor({
1769
- audioContext: sharedAudioContext.audioContext,
1770
- audioSyncAnchor: sharedAudioContext.audioSyncAnchor,
1771
- absoluteTimeInSeconds: absoluteTime / fps,
1772
- globalPlaybackRate,
1773
- debugAudioScheduling,
1774
- logLevel
1775
- });
1776
- }
1777
- }, [
1778
- absoluteTime,
1779
- globalPlaybackRate,
1780
- sharedAudioContext,
1781
- fps,
1782
- debugAudioScheduling,
1783
- logLevel
1784
- ]);
1785
- if (playingWhilePremounting) {
1786
- mediaPlayerRef.current?.playAudio();
1787
- }
1658
+ const sharedAudioContext = useContext(Internals6.SharedAudioContext);
1788
1659
  useLayoutEffect(() => {
1789
1660
  const mediaPlayer = mediaPlayerRef.current;
1790
1661
  if (!mediaPlayer)
@@ -1802,6 +1673,18 @@ var useCommonEffects = ({
1802
1673
  frame,
1803
1674
  mediaPlayerRef
1804
1675
  ]);
1676
+ useLayoutEffect(() => {
1677
+ if (!sharedAudioContext)
1678
+ return;
1679
+ const { remove } = sharedAudioContext.audioSyncAnchorEmitter.subscribe((event) => {
1680
+ if (event === "changed") {
1681
+ mediaPlayerRef.current?.audioSyncAnchorChanged();
1682
+ }
1683
+ });
1684
+ return () => {
1685
+ remove();
1686
+ };
1687
+ }, [sharedAudioContext, mediaPlayerRef]);
1805
1688
  useLayoutEffect(() => {
1806
1689
  const mediaPlayer = mediaPlayerRef.current;
1807
1690
  if (!mediaPlayer || !mediaPlayerReady) {
@@ -1841,22 +1724,22 @@ var useCommonEffects = ({
1841
1724
  if (!mediaPlayer || !mediaPlayerReady) {
1842
1725
  return;
1843
1726
  }
1844
- mediaPlayer.setGlobalPlaybackRate(globalPlaybackRate);
1845
- }, [globalPlaybackRate, mediaPlayerReady, mediaPlayerRef]);
1727
+ mediaPlayer.setGlobalPlaybackRate(globalPlaybackRate, currentTimeRef.current);
1728
+ }, [globalPlaybackRate, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
1846
1729
  useLayoutEffect(() => {
1847
1730
  const mediaPlayer = mediaPlayerRef.current;
1848
1731
  if (!mediaPlayer || !mediaPlayerReady) {
1849
1732
  return;
1850
1733
  }
1851
- mediaPlayer.setLoop(loop);
1852
- }, [loop, mediaPlayerReady, mediaPlayerRef]);
1734
+ mediaPlayer.setLoop(loop, currentTimeRef.current);
1735
+ }, [loop, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
1853
1736
  useLayoutEffect(() => {
1854
1737
  const mediaPlayer = mediaPlayerRef.current;
1855
1738
  if (!mediaPlayer || !mediaPlayerReady) {
1856
1739
  return;
1857
1740
  }
1858
- mediaPlayer.setDurationInFrames(durationInFrames);
1859
- }, [durationInFrames, mediaPlayerReady, mediaPlayerRef]);
1741
+ mediaPlayer.setSequenceDurationInFrames(durationInFrames, currentTimeRef.current);
1742
+ }, [durationInFrames, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
1860
1743
  useLayoutEffect(() => {
1861
1744
  const mediaPlayer = mediaPlayerRef.current;
1862
1745
  if (!mediaPlayer || !mediaPlayerReady) {
@@ -1876,34 +1759,27 @@ var useCommonEffects = ({
1876
1759
  if (!mediaPlayer || !mediaPlayerReady) {
1877
1760
  return;
1878
1761
  }
1879
- mediaPlayer.setFps(fps);
1880
- }, [fps, mediaPlayerReady, mediaPlayerRef]);
1881
- useLayoutEffect(() => {
1882
- const mediaPlayer = mediaPlayerRef.current;
1883
- if (!mediaPlayer || !mediaPlayerReady) {
1884
- return;
1885
- }
1886
- mediaPlayer.setSequenceOffset(sequenceOffset);
1887
- }, [sequenceOffset, mediaPlayerReady, mediaPlayerRef]);
1762
+ mediaPlayer.setFps(fps, currentTimeRef.current);
1763
+ }, [fps, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
1888
1764
  useLayoutEffect(() => {
1889
1765
  const mediaPlayer = mediaPlayerRef.current;
1890
1766
  if (!mediaPlayer || !mediaPlayerReady) {
1891
1767
  return;
1892
1768
  }
1893
- mediaPlayer.setDebugAudioScheduling(debugAudioScheduling);
1894
- }, [debugAudioScheduling, mediaPlayerReady, mediaPlayerRef]);
1769
+ mediaPlayer.setSequenceOffset(sequenceOffset, currentTimeRef.current);
1770
+ }, [sequenceOffset, mediaPlayerReady, mediaPlayerRef, currentTimeRef]);
1895
1771
  useLayoutEffect(() => {
1896
1772
  const mediaPlayer = mediaPlayerRef.current;
1897
1773
  if (!mediaPlayer || !mediaPlayerReady)
1898
1774
  return;
1899
1775
  mediaPlayer.seekTo(currentTime).catch(() => {});
1900
- Internals8.Log.trace({ logLevel, tag: "@remotion/media" }, `[${label}] Updating target time to ${currentTime.toFixed(3)}s`);
1776
+ Internals6.Log.trace({ logLevel, tag: "@remotion/media" }, `[${label}] Updating target time to ${currentTime.toFixed(3)}s`);
1901
1777
  }, [currentTime, logLevel, mediaPlayerReady, label, mediaPlayerRef]);
1902
1778
  };
1903
1779
 
1904
1780
  // src/use-media-in-timeline.ts
1905
1781
  import { useContext as useContext2, useState, useEffect } from "react";
1906
- import { Internals as Internals9, useCurrentFrame } from "remotion";
1782
+ import { Internals as Internals7, useCurrentFrame } from "remotion";
1907
1783
  var useMediaInTimeline = ({
1908
1784
  volume,
1909
1785
  mediaVolume,
@@ -1920,9 +1796,9 @@ var useMediaInTimeline = ({
1920
1796
  trimAfter,
1921
1797
  controls
1922
1798
  }) => {
1923
- const parentSequence = useContext2(Internals9.SequenceContext);
1924
- const startsAt = Internals9.useMediaStartsAt();
1925
- const { registerSequence, unregisterSequence } = useContext2(Internals9.SequenceManager);
1799
+ const parentSequence = useContext2(Internals7.SequenceContext);
1800
+ const startsAt = Internals7.useMediaStartsAt();
1801
+ const { registerSequence, unregisterSequence } = useContext2(Internals7.SequenceManager);
1926
1802
  const [sequenceId] = useState(() => String(Math.random()));
1927
1803
  const [mediaId] = useState(() => String(Math.random()));
1928
1804
  const frame = useCurrentFrame();
@@ -1934,7 +1810,7 @@ var useMediaInTimeline = ({
1934
1810
  rootId,
1935
1811
  isStudio,
1936
1812
  finalDisplayName
1937
- } = Internals9.useBasicMediaInTimeline({
1813
+ } = Internals7.useBasicMediaInTimeline({
1938
1814
  volume,
1939
1815
  mediaVolume,
1940
1816
  mediaType,
@@ -2044,7 +1920,7 @@ var {
2044
1920
  warnAboutTooHighVolume,
2045
1921
  usePreload,
2046
1922
  SequenceContext
2047
- } = Internals10;
1923
+ } = Internals8;
2048
1924
  var AudioForPreviewAssertedShowing = ({
2049
1925
  src,
2050
1926
  playbackRate,
@@ -2062,7 +1938,6 @@ var AudioForPreviewAssertedShowing = ({
2062
1938
  toneFrequency,
2063
1939
  audioStreamIndex,
2064
1940
  fallbackHtml5AudioProps,
2065
- debugAudioScheduling,
2066
1941
  onError,
2067
1942
  credentials,
2068
1943
  controls
@@ -2075,7 +1950,7 @@ var AudioForPreviewAssertedShowing = ({
2075
1950
  const [mediaPlayerReady, setMediaPlayerReady] = useState2(false);
2076
1951
  const [shouldFallbackToNativeAudio, setShouldFallbackToNativeAudio] = useState2(false);
2077
1952
  const [playing] = Timeline.usePlayingState();
2078
- const timelineContext = Internals10.useTimelineContext();
1953
+ const timelineContext = Internals8.useTimelineContext();
2079
1954
  const globalPlaybackRate = timelineContext.playbackRate;
2080
1955
  const sharedAudioContext = useContext3(SharedAudioContext);
2081
1956
  const buffer = useBufferState();
@@ -2126,12 +2001,12 @@ var AudioForPreviewAssertedShowing = ({
2126
2001
  trimBefore,
2127
2002
  controls
2128
2003
  });
2129
- const bufferingContext = useContext3(Internals10.BufferingContextReact);
2004
+ const bufferingContext = useContext3(Internals8.BufferingContextReact);
2130
2005
  if (!bufferingContext) {
2131
2006
  throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
2132
2007
  }
2133
2008
  const effectiveMuted = muted || mediaMuted || userPreferredVolume <= 0;
2134
- const isPlayerBuffering = Internals10.useIsPlayerBuffering(bufferingContext);
2009
+ const isPlayerBuffering = Internals8.useIsPlayerBuffering(bufferingContext);
2135
2010
  const initialPlaying = useRef(playing && !isPlayerBuffering);
2136
2011
  const initialIsPremounting = useRef(isPremounting);
2137
2012
  const initialIsPostmounting = useRef(isPostmounting);
@@ -2156,13 +2031,11 @@ var AudioForPreviewAssertedShowing = ({
2156
2031
  fps: videoConfig.fps,
2157
2032
  sequenceOffset,
2158
2033
  loop,
2159
- debugAudioScheduling,
2160
2034
  durationInFrames: videoConfig.durationInFrames,
2161
2035
  isPremounting,
2162
2036
  isPostmounting,
2163
2037
  currentTime,
2164
2038
  logLevel,
2165
- sharedAudioContext,
2166
2039
  label: "AudioForPreview"
2167
2040
  });
2168
2041
  useEffect2(() => {
@@ -2170,12 +2043,27 @@ var AudioForPreviewAssertedShowing = ({
2170
2043
  return;
2171
2044
  if (!sharedAudioContext.audioContext)
2172
2045
  return;
2173
- const { audioContext, audioSyncAnchor, scheduleAudioNode } = sharedAudioContext;
2046
+ const {
2047
+ audioContext,
2048
+ gainNode,
2049
+ audioSyncAnchor,
2050
+ scheduleAudioNode,
2051
+ unscheduleAudioNode
2052
+ } = sharedAudioContext;
2053
+ if (!gainNode) {
2054
+ return;
2055
+ }
2174
2056
  try {
2175
2057
  const player = new MediaPlayer({
2176
2058
  src: preloadedSrc,
2177
2059
  logLevel,
2178
- sharedAudioContext: { audioContext, audioSyncAnchor, scheduleAudioNode },
2060
+ sharedAudioContext: {
2061
+ audioContext,
2062
+ gainNode,
2063
+ audioSyncAnchor,
2064
+ scheduleAudioNode,
2065
+ unscheduleAudioNode
2066
+ },
2179
2067
  loop,
2180
2068
  trimAfter: initialTrimAfterRef.current,
2181
2069
  trimBefore: initialTrimBeforeRef.current,
@@ -2184,7 +2072,6 @@ var AudioForPreviewAssertedShowing = ({
2184
2072
  playbackRate: initialPlaybackRate.current,
2185
2073
  audioStreamIndex: audioStreamIndex ?? 0,
2186
2074
  debugOverlay: false,
2187
- debugAudioScheduling,
2188
2075
  bufferState: buffer,
2189
2076
  isPostmounting: initialIsPostmounting.current,
2190
2077
  isPremounting: initialIsPremounting.current,
@@ -2211,7 +2098,7 @@ var AudioForPreviewAssertedShowing = ({
2211
2098
  if (action === "fail") {
2212
2099
  throw errorToUse;
2213
2100
  } else {
2214
- Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
2101
+ Internals8.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
2215
2102
  setShouldFallbackToNativeAudio(true);
2216
2103
  }
2217
2104
  };
@@ -2234,7 +2121,7 @@ var AudioForPreviewAssertedShowing = ({
2234
2121
  if (result.type === "success") {
2235
2122
  setMediaPlayerReady(true);
2236
2123
  setMediaDurationInSeconds(result.durationInSeconds);
2237
- Internals10.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] MediaPlayer initialized successfully`);
2124
+ Internals8.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] MediaPlayer initialized successfully`);
2238
2125
  }
2239
2126
  }).catch((error) => {
2240
2127
  const [action, errorToUse] = callOnErrorAndResolve({
@@ -2247,7 +2134,7 @@ var AudioForPreviewAssertedShowing = ({
2247
2134
  if (action === "fail") {
2248
2135
  throw errorToUse;
2249
2136
  } else {
2250
- Internals10.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] Failed to initialize MediaPlayer", error);
2137
+ Internals8.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] Failed to initialize MediaPlayer", error);
2251
2138
  setShouldFallbackToNativeAudio(true);
2252
2139
  }
2253
2140
  });
@@ -2262,12 +2149,12 @@ var AudioForPreviewAssertedShowing = ({
2262
2149
  if (action === "fail") {
2263
2150
  throw errorToUse;
2264
2151
  }
2265
- Internals10.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] MediaPlayer initialization failed", errorToUse);
2152
+ Internals8.Log.error({ logLevel, tag: "@remotion/media" }, "[AudioForPreview] MediaPlayer initialization failed", errorToUse);
2266
2153
  setShouldFallbackToNativeAudio(true);
2267
2154
  }
2268
2155
  return () => {
2269
2156
  if (mediaPlayerRef.current) {
2270
- Internals10.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] Disposing MediaPlayer`);
2157
+ Internals8.Log.trace({ logLevel, tag: "@remotion/media" }, `[AudioForPreview] Disposing MediaPlayer`);
2271
2158
  mediaPlayerRef.current.dispose();
2272
2159
  mediaPlayerRef.current = null;
2273
2160
  }
@@ -2282,7 +2169,6 @@ var AudioForPreviewAssertedShowing = ({
2282
2169
  videoConfig.fps,
2283
2170
  audioStreamIndex,
2284
2171
  disallowFallbackToHtml5Audio,
2285
- debugAudioScheduling,
2286
2172
  buffer,
2287
2173
  onError,
2288
2174
  credentials
@@ -2326,13 +2212,12 @@ var AudioForPreview = ({
2326
2212
  toneFrequency,
2327
2213
  audioStreamIndex,
2328
2214
  fallbackHtml5AudioProps,
2329
- debugAudioScheduling,
2330
2215
  onError,
2331
2216
  credentials,
2332
2217
  controls
2333
2218
  }) => {
2334
2219
  const preloadedSrc = usePreload(src);
2335
- const defaultLogLevel = Internals10.useLogLevel();
2220
+ const defaultLogLevel = Internals8.useLogLevel();
2336
2221
  const frame = useCurrentFrame2();
2337
2222
  const videoConfig = useVideoConfig2();
2338
2223
  const currentTime = frame / videoConfig.fps;
@@ -2376,7 +2261,6 @@ var AudioForPreview = ({
2376
2261
  stack,
2377
2262
  disallowFallbackToHtml5Audio: disallowFallbackToHtml5Audio ?? false,
2378
2263
  toneFrequency,
2379
- debugAudioScheduling: debugAudioScheduling ?? false,
2380
2264
  onError,
2381
2265
  credentials,
2382
2266
  fallbackHtml5AudioProps,
@@ -2389,7 +2273,7 @@ import { useContext as useContext4, useLayoutEffect as useLayoutEffect2, useMemo
2389
2273
  import {
2390
2274
  cancelRender as cancelRender2,
2391
2275
  Html5Audio,
2392
- Internals as Internals18,
2276
+ Internals as Internals16,
2393
2277
  random,
2394
2278
  useCurrentFrame as useCurrentFrame3,
2395
2279
  useDelayRender,
@@ -2398,13 +2282,13 @@ import {
2398
2282
 
2399
2283
  // src/caches.ts
2400
2284
  import React2 from "react";
2401
- import { cancelRender, Internals as Internals15 } from "remotion";
2285
+ import { cancelRender, Internals as Internals13 } from "remotion";
2402
2286
 
2403
2287
  // src/audio-extraction/audio-manager.ts
2404
- import { Internals as Internals12 } from "remotion";
2288
+ import { Internals as Internals10 } from "remotion";
2405
2289
 
2406
2290
  // src/audio-extraction/audio-iterator.ts
2407
- import { Internals as Internals11 } from "remotion";
2291
+ import { Internals as Internals9 } from "remotion";
2408
2292
 
2409
2293
  // src/audio-extraction/audio-cache.ts
2410
2294
  var makeAudioCache = () => {
@@ -2483,7 +2367,7 @@ var warnAboutMatroskaOnce = (src, logLevel) => {
2483
2367
  return;
2484
2368
  }
2485
2369
  warned[src] = true;
2486
- 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`);
2370
+ Internals9.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`);
2487
2371
  };
2488
2372
  var makeAudioIterator2 = ({
2489
2373
  audioSampleSink,
@@ -2551,7 +2435,7 @@ var makeAudioIterator2 = ({
2551
2435
  if (openTimestamps.length > 0) {
2552
2436
  const first = openTimestamps[0];
2553
2437
  const last = openTimestamps[openTimestamps.length - 1];
2554
- Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, "Open audio samples for src", src, `${first.toFixed(3)}...${last.toFixed(3)}`);
2438
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, "Open audio samples for src", src, `${first.toFixed(3)}...${last.toFixed(3)}`);
2555
2439
  }
2556
2440
  };
2557
2441
  const getCacheStats = () => {
@@ -2648,7 +2532,7 @@ var makeAudioManager = () => {
2648
2532
  if (seenKeys.has(key)) {
2649
2533
  iterator.prepareForDeletion();
2650
2534
  iterators.splice(iterators.indexOf(iterator), 1);
2651
- Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted duplicate iterator for ${iterator.src}`);
2535
+ Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted duplicate iterator for ${iterator.src}`);
2652
2536
  }
2653
2537
  seenKeys.add(key);
2654
2538
  }
@@ -2669,7 +2553,7 @@ var makeAudioManager = () => {
2669
2553
  attempts++;
2670
2554
  }
2671
2555
  if ((await getTotalCacheStats()).totalSize > maxCacheSize && attempts >= maxAttempts) {
2672
- 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.`);
2556
+ Internals10.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.`);
2673
2557
  }
2674
2558
  for (const iterator of iterators) {
2675
2559
  if (iterator.src === src && await iterator.waitForCompletion() && iterator.canSatisfyRequestedTime(timeInSeconds)) {
@@ -2738,7 +2622,7 @@ var makeAudioManager = () => {
2738
2622
  };
2739
2623
 
2740
2624
  // src/video-extraction/keyframe-manager.ts
2741
- import { Internals as Internals14 } from "remotion";
2625
+ import { Internals as Internals12 } from "remotion";
2742
2626
 
2743
2627
  // src/render-timestamp-range.ts
2744
2628
  var renderTimestampRange = (timestamps) => {
@@ -2752,7 +2636,7 @@ var renderTimestampRange = (timestamps) => {
2752
2636
  };
2753
2637
 
2754
2638
  // src/video-extraction/keyframe-bank.ts
2755
- import { Internals as Internals13 } from "remotion";
2639
+ import { Internals as Internals11 } from "remotion";
2756
2640
 
2757
2641
  // src/video-extraction/get-allocation-size.ts
2758
2642
  var getAllocationSize = (sample) => {
@@ -2815,7 +2699,7 @@ var makeKeyframeBank = async ({
2815
2699
  }
2816
2700
  }
2817
2701
  if (deletedTimestamps.length > 0) {
2818
- 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)}`);
2702
+ Internals11.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)}`);
2819
2703
  }
2820
2704
  };
2821
2705
  const hasDecodedEnoughForTimestamp = (timestamp) => {
@@ -2838,7 +2722,7 @@ var makeKeyframeBank = async ({
2838
2722
  frameTimestamps.push(frame.timestamp);
2839
2723
  allocationSize += getAllocationSize(frame);
2840
2724
  lastUsed = Date.now();
2841
- Internals13.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
2725
+ Internals11.Log.trace({ logLevel, tag: "@remotion/media" }, `Added frame at ${frame.timestamp}sec to bank`);
2842
2726
  };
2843
2727
  const ensureEnoughFramesForTimestamp = async (timestampInSeconds, logLevel, fps) => {
2844
2728
  while (!hasDecodedEnoughForTimestamp(timestampInSeconds)) {
@@ -2893,7 +2777,7 @@ var makeKeyframeBank = async ({
2893
2777
  throw new Error("No first frame found");
2894
2778
  }
2895
2779
  const startTimestampInSeconds = firstFrame.value.timestamp;
2896
- Internals13.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec`);
2780
+ Internals11.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec`);
2897
2781
  addFrame(firstFrame.value, parentLogLevel);
2898
2782
  const getRangeOfTimestamps = () => {
2899
2783
  if (frameTimestamps.length === 0) {
@@ -2911,7 +2795,7 @@ var makeKeyframeBank = async ({
2911
2795
  const prepareForDeletion = (logLevel, reason) => {
2912
2796
  const range = getRangeOfTimestamps();
2913
2797
  if (range) {
2914
- Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion (${reason}) of keyframe bank from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec`);
2798
+ Internals11.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion (${reason}) of keyframe bank from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec`);
2915
2799
  }
2916
2800
  let framesDeleted = 0;
2917
2801
  for (const frameTimestamp of frameTimestamps.slice()) {
@@ -2984,10 +2868,10 @@ var makeKeyframeManager = () => {
2984
2868
  if (size === 0) {
2985
2869
  continue;
2986
2870
  }
2987
- Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
2871
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
2988
2872
  }
2989
2873
  }
2990
- Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
2874
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
2991
2875
  };
2992
2876
  const getCacheStats = () => {
2993
2877
  let count = 0;
@@ -3041,7 +2925,7 @@ var makeKeyframeManager = () => {
3041
2925
  const { framesDeleted } = mostInThePastBank.prepareForDeletion(logLevel, "deleted oldest keyframe bank to stay under max cache size");
3042
2926
  sources[mostInThePastSrc].splice(mostInThePastIndex, 1);
3043
2927
  if (range) {
3044
- 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.`);
2928
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted ${framesDeleted} frames for src ${mostInThePastSrc} from ${range?.firstTimestamp}sec to ${range?.lastTimestamp}sec to free up memory.`);
3045
2929
  }
3046
2930
  }
3047
2931
  return { finish: false };
@@ -3055,12 +2939,12 @@ var makeKeyframeManager = () => {
3055
2939
  if (finish) {
3056
2940
  break;
3057
2941
  }
3058
- 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));
2942
+ Internals12.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));
3059
2943
  cacheStats = getTotalCacheStats();
3060
2944
  attempts++;
3061
2945
  }
3062
2946
  if (cacheStats.totalSize > maxCacheSize && attempts >= maxAttempts) {
3063
- 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.`);
2947
+ Internals12.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.`);
3064
2948
  }
3065
2949
  };
3066
2950
  const clearKeyframeBanksBeforeTime = ({
@@ -3081,7 +2965,7 @@ var makeKeyframeManager = () => {
3081
2965
  }
3082
2966
  if (range.lastTimestamp < threshold) {
3083
2967
  bank.prepareForDeletion(logLevel, "cleared before threshold " + threshold);
3084
- Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${range.firstTimestamp}sec to ${range.lastTimestamp}sec`);
2968
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${range.firstTimestamp}sec to ${range.lastTimestamp}sec`);
3085
2969
  const bankIndex = banks.indexOf(bank);
3086
2970
  delete sources[src][bankIndex];
3087
2971
  } else {
@@ -3103,7 +2987,7 @@ var makeKeyframeManager = () => {
3103
2987
  const existingBanks = sources[src] ?? [];
3104
2988
  const existingBank = existingBanks?.find((bank) => bank.canSatisfyTimestamp(timestamp));
3105
2989
  if (!existingBank) {
3106
- Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `Creating new keyframe bank for src ${src} at timestamp ${timestamp}`);
2990
+ Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, `Creating new keyframe bank for src ${src} at timestamp ${timestamp}`);
3107
2991
  const newKeyframeBank = await makeKeyframeBank({
3108
2992
  videoSampleSink,
3109
2993
  logLevel,
@@ -3114,10 +2998,10 @@ var makeKeyframeManager = () => {
3114
2998
  return newKeyframeBank;
3115
2999
  }
3116
3000
  if (existingBank.canSatisfyTimestamp(timestamp)) {
3117
- Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists and satisfies timestamp ${timestamp}`);
3001
+ Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists and satisfies timestamp ${timestamp}`);
3118
3002
  return existingBank;
3119
3003
  }
3120
- Internals14.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
3004
+ Internals12.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
3121
3005
  existingBank.prepareForDeletion(logLevel, "already existed but evicted");
3122
3006
  sources[src] = sources[src].filter((bank) => bank !== existingBank);
3123
3007
  const replacementKeybank = await makeKeyframeBank({
@@ -3208,20 +3092,20 @@ var getUncachedMaxCacheSize = (logLevel) => {
3208
3092
  if (window.remotion_mediaCacheSizeInBytes > 20000 * 1024 * 1024) {
3209
3093
  cancelRender(new Error(`The maximum value for the "mediaCacheSizeInBytes" prop is 20GB (${20000 * 1024 * 1024}), got: ${window.remotion_mediaCacheSizeInBytes}`));
3210
3094
  }
3211
- Internals15.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
3095
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
3212
3096
  return window.remotion_mediaCacheSizeInBytes;
3213
3097
  }
3214
3098
  if (typeof window !== "undefined" && window.remotion_initialMemoryAvailable !== undefined && window.remotion_initialMemoryAvailable !== null) {
3215
3099
  const value = window.remotion_initialMemoryAvailable / 2;
3216
3100
  if (value < 500 * 1024 * 1024) {
3217
- 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!)`);
3101
+ Internals13.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!)`);
3218
3102
  return 500 * 1024 * 1024;
3219
3103
  }
3220
3104
  if (value > 20000 * 1024 * 1024) {
3221
- 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)`);
3105
+ Internals13.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)`);
3222
3106
  return 20000 * 1024 * 1024;
3223
3107
  }
3224
- 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`);
3108
+ Internals13.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
3225
3109
  return value;
3226
3110
  }
3227
3111
  return 1000 * 1000 * 1000;
@@ -3235,7 +3119,7 @@ var getMaxVideoCacheSize = (logLevel) => {
3235
3119
  return cachedMaxCacheSize;
3236
3120
  };
3237
3121
  var useMaxMediaCacheSize = (logLevel) => {
3238
- const context = React2.useContext(Internals15.MaxMediaCacheSizeContext);
3122
+ const context = React2.useContext(Internals13.MaxMediaCacheSizeContext);
3239
3123
  if (context === null) {
3240
3124
  return getMaxVideoCacheSize(logLevel);
3241
3125
  }
@@ -3489,7 +3373,7 @@ var combineAudioDataAndClosePrevious = (audioDataArray) => {
3489
3373
  };
3490
3374
 
3491
3375
  // src/get-sink.ts
3492
- import { Internals as Internals16 } from "remotion";
3376
+ import { Internals as Internals14 } from "remotion";
3493
3377
 
3494
3378
  // src/video-extraction/get-frames-since-keyframe.ts
3495
3379
  import {
@@ -3644,7 +3528,7 @@ var getSink = (src, logLevel, credentials) => {
3644
3528
  const cacheKey = credentials ? `${src}::${credentials}` : src;
3645
3529
  let promise = sinkPromises[cacheKey];
3646
3530
  if (!promise) {
3647
- Internals16.Log.verbose({
3531
+ Internals14.Log.verbose({
3648
3532
  logLevel,
3649
3533
  tag: "@remotion/media"
3650
3534
  }, `Sink for ${src} was not found, creating new sink`);
@@ -3785,7 +3669,7 @@ var extractAudio = (params) => {
3785
3669
  };
3786
3670
 
3787
3671
  // src/video-extraction/extract-frame.ts
3788
- import { Internals as Internals17 } from "remotion";
3672
+ import { Internals as Internals15 } from "remotion";
3789
3673
  var extractFrameInternal = async ({
3790
3674
  src,
3791
3675
  timeInSeconds: unloopedTimeInSeconds,
@@ -3867,7 +3751,7 @@ var extractFrameInternal = async ({
3867
3751
  durationInSeconds: await sink.getDuration()
3868
3752
  };
3869
3753
  } catch (err) {
3870
- Internals17.Log.info({ logLevel, tag: "@remotion/media" }, `Error decoding ${src} at time ${timeInSeconds}: ${err}`, err);
3754
+ Internals15.Log.info({ logLevel, tag: "@remotion/media" }, `Error decoding ${src} at time ${timeInSeconds}: ${err}`, err);
3871
3755
  return { type: "cannot-decode", durationInSeconds: mediaDurationInSeconds };
3872
3756
  }
3873
3757
  };
@@ -4271,13 +4155,13 @@ var AudioForRendering = ({
4271
4155
  onError,
4272
4156
  credentials
4273
4157
  }) => {
4274
- const defaultLogLevel = Internals18.useLogLevel();
4158
+ const defaultLogLevel = Internals16.useLogLevel();
4275
4159
  const logLevel = overriddenLogLevel ?? defaultLogLevel;
4276
4160
  const frame = useCurrentFrame3();
4277
- const absoluteFrame = Internals18.useTimelinePosition();
4278
- const videoConfig = Internals18.useUnsafeVideoConfig();
4279
- const { registerRenderAsset, unregisterRenderAsset } = useContext4(Internals18.RenderAssetManager);
4280
- const startsAt = Internals18.useMediaStartsAt();
4161
+ const absoluteFrame = Internals16.useTimelinePosition();
4162
+ const videoConfig = Internals16.useUnsafeVideoConfig();
4163
+ const { registerRenderAsset, unregisterRenderAsset } = useContext4(Internals16.RenderAssetManager);
4164
+ const startsAt = Internals16.useMediaStartsAt();
4281
4165
  const environment = useRemotionEnvironment();
4282
4166
  if (!videoConfig) {
4283
4167
  throw new Error("No video config found");
@@ -4288,7 +4172,7 @@ var AudioForRendering = ({
4288
4172
  const { fps } = videoConfig;
4289
4173
  const { delayRender, continueRender } = useDelayRender();
4290
4174
  const [replaceWithHtml5Audio, setReplaceWithHtml5Audio] = useState3(false);
4291
- const sequenceContext = useContext4(Internals18.SequenceContext);
4175
+ const sequenceContext = useContext4(Internals16.SequenceContext);
4292
4176
  const id = useMemo3(() => `media-audio-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
4293
4177
  src,
4294
4178
  sequenceContext?.cumulatedFrom,
@@ -4296,7 +4180,7 @@ var AudioForRendering = ({
4296
4180
  sequenceContext?.durationInFrames
4297
4181
  ]);
4298
4182
  const maxCacheSize = useMaxMediaCacheSize(logLevel);
4299
- const audioEnabled = Internals18.useAudioEnabled();
4183
+ const audioEnabled = Internals16.useAudioEnabled();
4300
4184
  useLayoutEffect2(() => {
4301
4185
  const timestamp = frame / fps;
4302
4186
  const durationInSeconds = 1 / fps;
@@ -4347,7 +4231,7 @@ var AudioForRendering = ({
4347
4231
  if (action === "fail") {
4348
4232
  cancelRender2(errorToUse);
4349
4233
  }
4350
- Internals18.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
4234
+ Internals16.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
4351
4235
  setReplaceWithHtml5Audio(true);
4352
4236
  };
4353
4237
  if (result.type === "unknown-container-format") {
@@ -4374,12 +4258,12 @@ var AudioForRendering = ({
4374
4258
  frame,
4375
4259
  startsAt
4376
4260
  });
4377
- const volume = Internals18.evaluateVolume({
4261
+ const volume = Internals16.evaluateVolume({
4378
4262
  volume: volumeProp,
4379
4263
  frame: volumePropsFrame,
4380
4264
  mediaVolume: 1
4381
4265
  });
4382
- Internals18.warnAboutTooHighVolume(volume);
4266
+ Internals16.warnAboutTooHighVolume(volume);
4383
4267
  if (audio && volume > 0) {
4384
4268
  applyVolume(audio.data, volume);
4385
4269
  registerRenderAsset({
@@ -4456,7 +4340,7 @@ var AudioForRendering = ({
4456
4340
 
4457
4341
  // src/audio/audio.tsx
4458
4342
  import { jsx as jsx3 } from "react/jsx-runtime";
4459
- var { validateMediaProps } = Internals19;
4343
+ var { validateMediaProps } = Internals17;
4460
4344
  var audioSchema = {
4461
4345
  volume: {
4462
4346
  type: "number",
@@ -4505,11 +4389,11 @@ var AudioInner = (props) => {
4505
4389
  })
4506
4390
  });
4507
4391
  };
4508
- var Audio = Internals19.wrapInSchema(AudioInner, audioSchema);
4509
- Internals19.addSequenceStackTraces(Audio);
4392
+ var Audio = Internals17.wrapInSchema(AudioInner, audioSchema);
4393
+ Internals17.addSequenceStackTraces(Audio);
4510
4394
 
4511
4395
  // src/video/video.tsx
4512
- import { Internals as Internals23, Sequence as Sequence2, useRemotionEnvironment as useRemotionEnvironment4 } from "remotion";
4396
+ import { Internals as Internals21, Sequence as Sequence2, useRemotionEnvironment as useRemotionEnvironment4 } from "remotion";
4513
4397
 
4514
4398
  // src/video/video-for-preview.tsx
4515
4399
  import {
@@ -4522,7 +4406,7 @@ import {
4522
4406
  } from "react";
4523
4407
  import {
4524
4408
  Html5Video,
4525
- Internals as Internals21,
4409
+ Internals as Internals19,
4526
4410
  useBufferState as useBufferState2,
4527
4411
  useCurrentFrame as useCurrentFrame4,
4528
4412
  useVideoConfig as useVideoConfig3
@@ -4552,7 +4436,7 @@ var getCachedVideoFrame = (src) => {
4552
4436
  };
4553
4437
 
4554
4438
  // src/video/warn-object-fit-css.ts
4555
- import { Internals as Internals20 } from "remotion";
4439
+ import { Internals as Internals18 } from "remotion";
4556
4440
  var OBJECT_FIT_CLASS_PATTERN = /\bobject-(contain|cover|fill|none|scale-down)\b/;
4557
4441
  var warnedStyle = false;
4558
4442
  var warnedClassName = false;
@@ -4563,11 +4447,11 @@ var warnAboutObjectFitInStyleOrClassName = ({
4563
4447
  }) => {
4564
4448
  if (!warnedStyle && style?.objectFit) {
4565
4449
  warnedStyle = true;
4566
- Internals20.Log.warn({ logLevel, tag: "@remotion/media" }, "Use the `objectFit` prop instead of the `style` prop.");
4450
+ Internals18.Log.warn({ logLevel, tag: "@remotion/media" }, "Use the `objectFit` prop instead of the `style` prop.");
4567
4451
  }
4568
4452
  if (!warnedClassName && className && OBJECT_FIT_CLASS_PATTERN.test(className)) {
4569
4453
  warnedClassName = true;
4570
- Internals20.Log.warn({ logLevel, tag: "@remotion/media" }, "Use the `objectFit` prop instead of `object-*` CSS class names.");
4454
+ Internals18.Log.warn({ logLevel, tag: "@remotion/media" }, "Use the `objectFit` prop instead of `object-*` CSS class names.");
4571
4455
  }
4572
4456
  };
4573
4457
 
@@ -4585,7 +4469,7 @@ var {
4585
4469
  usePreload: usePreload2,
4586
4470
  SequenceContext: SequenceContext2,
4587
4471
  SequenceVisibilityToggleContext
4588
- } = Internals21;
4472
+ } = Internals19;
4589
4473
  var VideoForPreviewAssertedShowing = ({
4590
4474
  src: unpreloadedSrc,
4591
4475
  style,
@@ -4606,7 +4490,6 @@ var VideoForPreviewAssertedShowing = ({
4606
4490
  fallbackOffthreadVideoProps,
4607
4491
  audioStreamIndex,
4608
4492
  debugOverlay,
4609
- debugAudioScheduling,
4610
4493
  headless,
4611
4494
  onError,
4612
4495
  credentials,
@@ -4625,7 +4508,7 @@ var VideoForPreviewAssertedShowing = ({
4625
4508
  const [mediaPlayerReady, setMediaPlayerReady] = useState4(false);
4626
4509
  const [shouldFallbackToNativeVideo, setShouldFallbackToNativeVideo] = useState4(false);
4627
4510
  const [playing] = Timeline2.usePlayingState();
4628
- const timelineContext = Internals21.useTimelineContext();
4511
+ const timelineContext = Internals19.useTimelineContext();
4629
4512
  const globalPlaybackRate = timelineContext.playbackRate;
4630
4513
  const sharedAudioContext = useContext5(SharedAudioContext2);
4631
4514
  const buffer = useBufferState2();
@@ -4675,19 +4558,19 @@ var VideoForPreviewAssertedShowing = ({
4675
4558
  const currentTimeRef = useRef2(currentTime);
4676
4559
  currentTimeRef.current = currentTime;
4677
4560
  const preloadedSrc = usePreload2(src);
4678
- const buffering = useContext5(Internals21.BufferingContextReact);
4561
+ const buffering = useContext5(Internals19.BufferingContextReact);
4679
4562
  if (!buffering) {
4680
4563
  throw new Error("useMediaPlayback must be used inside a <BufferingContext>");
4681
4564
  }
4682
4565
  const effectiveMuted = isSequenceHidden || muted || mediaMuted || userPreferredVolume <= 0;
4683
- const isPlayerBuffering = Internals21.useIsPlayerBuffering(buffering);
4566
+ const isPlayerBuffering = Internals19.useIsPlayerBuffering(buffering);
4684
4567
  const initialPlaying = useRef2(playing && !isPlayerBuffering);
4685
4568
  const initialIsPremounting = useRef2(isPremounting);
4686
4569
  const initialIsPostmounting = useRef2(isPostmounting);
4687
4570
  const initialGlobalPlaybackRate = useRef2(globalPlaybackRate);
4688
4571
  const initialPlaybackRate = useRef2(playbackRate);
4689
4572
  const initialMuted = useRef2(effectiveMuted);
4690
- const initialDurationInFrames = useRef2(videoConfig.durationInFrames);
4573
+ const initialSequenceDuration = useRef2(videoConfig.durationInFrames);
4691
4574
  const initialSequenceOffset = useRef2(sequenceOffset);
4692
4575
  const hasDrawnRealFrameRef = useRef2(false);
4693
4576
  const isPremountingRef = useRef2(isPremounting);
@@ -4732,13 +4615,28 @@ var VideoForPreviewAssertedShowing = ({
4732
4615
  return;
4733
4616
  if (!sharedAudioContext.audioContext)
4734
4617
  return;
4735
- const { audioContext, audioSyncAnchor, scheduleAudioNode } = sharedAudioContext;
4618
+ const {
4619
+ audioContext,
4620
+ gainNode,
4621
+ audioSyncAnchor,
4622
+ scheduleAudioNode,
4623
+ unscheduleAudioNode
4624
+ } = sharedAudioContext;
4625
+ if (!gainNode) {
4626
+ return;
4627
+ }
4736
4628
  try {
4737
4629
  const player = new MediaPlayer({
4738
4630
  canvas: canvasRef.current,
4739
4631
  src: preloadedSrc,
4740
4632
  logLevel,
4741
- sharedAudioContext: { audioContext, audioSyncAnchor, scheduleAudioNode },
4633
+ sharedAudioContext: {
4634
+ audioContext,
4635
+ gainNode,
4636
+ audioSyncAnchor,
4637
+ scheduleAudioNode,
4638
+ unscheduleAudioNode
4639
+ },
4742
4640
  loop,
4743
4641
  trimAfter: initialTrimAfterRef.current,
4744
4642
  trimBefore: initialTrimBeforeRef.current,
@@ -4746,12 +4644,11 @@ var VideoForPreviewAssertedShowing = ({
4746
4644
  playbackRate: initialPlaybackRate.current,
4747
4645
  audioStreamIndex,
4748
4646
  debugOverlay,
4749
- debugAudioScheduling,
4750
4647
  bufferState: buffer,
4751
4648
  isPremounting: initialIsPremounting.current,
4752
4649
  isPostmounting: initialIsPostmounting.current,
4753
4650
  globalPlaybackRate: initialGlobalPlaybackRate.current,
4754
- durationInFrames: initialDurationInFrames.current,
4651
+ durationInFrames: initialSequenceDuration.current,
4755
4652
  onVideoFrameCallback: initialOnVideoFrameRef.current ?? null,
4756
4653
  playing: initialPlaying.current,
4757
4654
  sequenceOffset: initialSequenceOffset.current,
@@ -4773,7 +4670,7 @@ var VideoForPreviewAssertedShowing = ({
4773
4670
  if (action === "fail") {
4774
4671
  throw errorToUse;
4775
4672
  }
4776
- Internals21.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
4673
+ Internals19.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
4777
4674
  setShouldFallbackToNativeVideo(true);
4778
4675
  };
4779
4676
  if (result.type === "unknown-container-format") {
@@ -4808,7 +4705,7 @@ var VideoForPreviewAssertedShowing = ({
4808
4705
  if (action === "fail") {
4809
4706
  throw errorToUse;
4810
4707
  }
4811
- Internals21.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] Failed to initialize MediaPlayer", errorToUse);
4708
+ Internals19.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] Failed to initialize MediaPlayer", errorToUse);
4812
4709
  setShouldFallbackToNativeVideo(true);
4813
4710
  });
4814
4711
  } catch (error) {
@@ -4822,12 +4719,12 @@ var VideoForPreviewAssertedShowing = ({
4822
4719
  if (action === "fail") {
4823
4720
  throw errorToUse;
4824
4721
  }
4825
- Internals21.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] MediaPlayer initialization failed", errorToUse);
4722
+ Internals19.Log.error({ logLevel, tag: "@remotion/media" }, "[VideoForPreview] MediaPlayer initialization failed", errorToUse);
4826
4723
  setShouldFallbackToNativeVideo(true);
4827
4724
  }
4828
4725
  return () => {
4829
4726
  if (mediaPlayerRef.current) {
4830
- Internals21.Log.trace({ logLevel, tag: "@remotion/media" }, `[VideoForPreview] Disposing MediaPlayer`);
4727
+ Internals19.Log.trace({ logLevel, tag: "@remotion/media" }, `[VideoForPreview] Disposing MediaPlayer`);
4831
4728
  mediaPlayerRef.current.dispose();
4832
4729
  mediaPlayerRef.current = null;
4833
4730
  }
@@ -4839,7 +4736,6 @@ var VideoForPreviewAssertedShowing = ({
4839
4736
  audioStreamIndex,
4840
4737
  buffer,
4841
4738
  debugOverlay,
4842
- debugAudioScheduling,
4843
4739
  disallowFallbackToOffthreadVideo,
4844
4740
  logLevel,
4845
4741
  loop,
@@ -4851,7 +4747,7 @@ var VideoForPreviewAssertedShowing = ({
4851
4747
  ]);
4852
4748
  warnAboutObjectFitInStyleOrClassName({ style, className, logLevel });
4853
4749
  const classNameValue = useMemo4(() => {
4854
- return [Internals21.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals21.truthy).join(" ");
4750
+ return [Internals19.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals19.truthy).join(" ");
4855
4751
  }, [className]);
4856
4752
  useCommonEffects({
4857
4753
  mediaPlayerRef,
@@ -4869,13 +4765,11 @@ var VideoForPreviewAssertedShowing = ({
4869
4765
  fps: videoConfig.fps,
4870
4766
  sequenceOffset,
4871
4767
  loop,
4872
- debugAudioScheduling,
4873
4768
  durationInFrames: videoConfig.durationInFrames,
4874
4769
  isPremounting,
4875
4770
  isPostmounting,
4876
4771
  currentTime,
4877
4772
  logLevel,
4878
- sharedAudioContext,
4879
4773
  label: "VideoForPreview"
4880
4774
  });
4881
4775
  useLayoutEffect3(() => {
@@ -4969,7 +4863,7 @@ import {
4969
4863
  useState as useState5
4970
4864
  } from "react";
4971
4865
  import {
4972
- Internals as Internals22,
4866
+ Internals as Internals20,
4973
4867
  Loop,
4974
4868
  random as random2,
4975
4869
  useCurrentFrame as useCurrentFrame5,
@@ -5008,11 +4902,11 @@ var VideoForRendering = ({
5008
4902
  throw new TypeError("No `src` was passed to <Video>.");
5009
4903
  }
5010
4904
  const frame = useCurrentFrame5();
5011
- const absoluteFrame = Internals22.useTimelinePosition();
4905
+ const absoluteFrame = Internals20.useTimelinePosition();
5012
4906
  const { fps } = useVideoConfig4();
5013
- const { registerRenderAsset, unregisterRenderAsset } = useContext6(Internals22.RenderAssetManager);
5014
- const startsAt = Internals22.useMediaStartsAt();
5015
- const sequenceContext = useContext6(Internals22.SequenceContext);
4907
+ const { registerRenderAsset, unregisterRenderAsset } = useContext6(Internals20.RenderAssetManager);
4908
+ const startsAt = Internals20.useMediaStartsAt();
4909
+ const sequenceContext = useContext6(Internals20.SequenceContext);
5016
4910
  const id = useMemo5(() => `media-video-${random2(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
5017
4911
  src,
5018
4912
  sequenceContext?.cumulatedFrom,
@@ -5023,8 +4917,8 @@ var VideoForRendering = ({
5023
4917
  const { delayRender, continueRender, cancelRender: cancelRender3 } = useDelayRender2();
5024
4918
  const canvasRef = useRef3(null);
5025
4919
  const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState5(false);
5026
- const audioEnabled = Internals22.useAudioEnabled();
5027
- const videoEnabled = Internals22.useVideoEnabled();
4920
+ const audioEnabled = Internals20.useAudioEnabled();
4921
+ const videoEnabled = Internals20.useVideoEnabled();
5028
4922
  const maxCacheSize = useMaxMediaCacheSize(logLevel);
5029
4923
  const [error, setError] = useState5(null);
5030
4924
  if (error) {
@@ -5089,7 +4983,7 @@ var VideoForRendering = ({
5089
4983
  return;
5090
4984
  }
5091
4985
  if (window.remotion_isMainTab) {
5092
- Internals22.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
4986
+ Internals20.Log.warn({ logLevel, tag: "@remotion/media" }, fallbackMessage);
5093
4987
  }
5094
4988
  setReplaceWithOffthreadVideo({
5095
4989
  durationInSeconds: mediaDurationInSeconds
@@ -5144,12 +5038,12 @@ var VideoForRendering = ({
5144
5038
  frame,
5145
5039
  startsAt
5146
5040
  });
5147
- const volume = Internals22.evaluateVolume({
5041
+ const volume = Internals20.evaluateVolume({
5148
5042
  volume: volumeProp,
5149
5043
  frame: volumePropsFrame,
5150
5044
  mediaVolume: 1
5151
5045
  });
5152
- Internals22.warnAboutTooHighVolume(volume);
5046
+ Internals20.warnAboutTooHighVolume(volume);
5153
5047
  if (audio && volume > 0) {
5154
5048
  applyVolume(audio.data, volume);
5155
5049
  registerRenderAsset({
@@ -5207,7 +5101,7 @@ var VideoForRendering = ({
5207
5101
  ]);
5208
5102
  warnAboutObjectFitInStyleOrClassName({ style, className, logLevel });
5209
5103
  const classNameValue = useMemo5(() => {
5210
- return [Internals22.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals22.truthy).join(" ");
5104
+ return [Internals20.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals20.truthy).join(" ");
5211
5105
  }, [className]);
5212
5106
  const styleWithObjectFit = useMemo5(() => {
5213
5107
  return {
@@ -5216,7 +5110,7 @@ var VideoForRendering = ({
5216
5110
  };
5217
5111
  }, [objectFitProp, style]);
5218
5112
  if (replaceWithOffthreadVideo) {
5219
- const fallback = /* @__PURE__ */ jsx5(Internals22.InnerOffthreadVideo, {
5113
+ const fallback = /* @__PURE__ */ jsx5(Internals20.InnerOffthreadVideo, {
5220
5114
  src,
5221
5115
  playbackRate: playbackRate ?? 1,
5222
5116
  muted: muted ?? false,
@@ -5256,7 +5150,7 @@ var VideoForRendering = ({
5256
5150
  }
5257
5151
  return /* @__PURE__ */ jsx5(Loop, {
5258
5152
  layout: "none",
5259
- durationInFrames: Internals22.calculateMediaDuration({
5153
+ durationInFrames: Internals20.calculateMediaDuration({
5260
5154
  trimAfter: trimAfterValue,
5261
5155
  mediaDurationInFrames: replaceWithOffthreadVideo.durationInSeconds * fps,
5262
5156
  playbackRate,
@@ -5279,7 +5173,7 @@ var VideoForRendering = ({
5279
5173
 
5280
5174
  // src/video/video.tsx
5281
5175
  import { jsx as jsx6 } from "react/jsx-runtime";
5282
- var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } = Internals23;
5176
+ var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } = Internals21;
5283
5177
  var videoSchema = {
5284
5178
  volume: {
5285
5179
  type: "number",
@@ -5349,7 +5243,6 @@ var InnerVideo = ({
5349
5243
  toneFrequency,
5350
5244
  showInTimeline,
5351
5245
  debugOverlay,
5352
- debugAudioScheduling,
5353
5246
  headless,
5354
5247
  onError,
5355
5248
  credentials,
@@ -5422,7 +5315,6 @@ var InnerVideo = ({
5422
5315
  disallowFallbackToOffthreadVideo,
5423
5316
  fallbackOffthreadVideoProps,
5424
5317
  debugOverlay: debugOverlay ?? false,
5425
- debugAudioScheduling: debugAudioScheduling ?? false,
5426
5318
  headless: headless ?? false,
5427
5319
  onError,
5428
5320
  credentials,
@@ -5454,7 +5346,6 @@ var VideoInner = ({
5454
5346
  stack,
5455
5347
  toneFrequency,
5456
5348
  debugOverlay,
5457
- debugAudioScheduling,
5458
5349
  headless,
5459
5350
  onError,
5460
5351
  credentials,
@@ -5464,7 +5355,7 @@ var VideoInner = ({
5464
5355
  from,
5465
5356
  durationInFrames
5466
5357
  }) => {
5467
- const fallbackLogLevel = Internals23.useLogLevel();
5358
+ const fallbackLogLevel = Internals21.useLogLevel();
5468
5359
  return /* @__PURE__ */ jsx6(Sequence2, {
5469
5360
  layout: "none",
5470
5361
  from: from ?? 0,
@@ -5493,7 +5384,6 @@ var VideoInner = ({
5493
5384
  toneFrequency: toneFrequency ?? 1,
5494
5385
  stack,
5495
5386
  debugOverlay: debugOverlay ?? false,
5496
- debugAudioScheduling: debugAudioScheduling ?? false,
5497
5387
  headless: headless ?? false,
5498
5388
  onError,
5499
5389
  credentials,
@@ -5503,8 +5393,8 @@ var VideoInner = ({
5503
5393
  })
5504
5394
  });
5505
5395
  };
5506
- var Video = Internals23.wrapInSchema(VideoInner, videoSchema);
5507
- Internals23.addSequenceStackTraces(Video);
5396
+ var Video = Internals21.wrapInSchema(VideoInner, videoSchema);
5397
+ Internals21.addSequenceStackTraces(Video);
5508
5398
 
5509
5399
  // src/index.ts
5510
5400
  var experimental_Audio = Audio;