@remotion/media 4.0.370 → 4.0.372

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