@remotion/media 4.0.357 → 4.0.361

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.
Files changed (38) hide show
  1. package/dist/audio/audio-for-preview.js +29 -13
  2. package/dist/audio/audio-for-rendering.js +8 -6
  3. package/dist/audio-extraction/extract-audio.js +1 -0
  4. package/dist/browser-can-use-webgl2.d.ts +1 -0
  5. package/dist/browser-can-use-webgl2.js +13 -0
  6. package/dist/caches.d.ts +1 -1
  7. package/dist/caches.js +3 -3
  8. package/dist/esm/index.mjs +568 -327
  9. package/dist/extract-frame-and-audio.js +6 -0
  10. package/dist/get-time-in-seconds.d.ts +2 -1
  11. package/dist/get-time-in-seconds.js +10 -10
  12. package/dist/show-in-timeline.d.ts +8 -0
  13. package/dist/show-in-timeline.js +31 -0
  14. package/dist/use-media-in-timeline.d.ts +19 -0
  15. package/dist/use-media-in-timeline.js +103 -0
  16. package/dist/video/media-player.d.ts +11 -5
  17. package/dist/video/media-player.js +74 -36
  18. package/dist/video/video-for-preview.d.ts +9 -9
  19. package/dist/video/video-for-preview.js +43 -20
  20. package/dist/video/video-for-rendering.js +21 -5
  21. package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +3 -0
  22. package/dist/video-extraction/extract-frame-via-broadcast-channel.js +17 -0
  23. package/dist/video-extraction/extract-frame.d.ts +3 -0
  24. package/dist/video-extraction/extract-frame.js +7 -0
  25. package/dist/video-extraction/keyframe-manager.d.ts +1 -1
  26. package/dist/video-extraction/keyframe-manager.js +5 -0
  27. package/package.json +54 -54
  28. package/LICENSE.md +0 -49
  29. package/dist/convert-audiodata/apply-tonefrequency.d.ts +0 -2
  30. package/dist/convert-audiodata/apply-tonefrequency.js +0 -43
  31. package/dist/convert-audiodata/wsola.d.ts +0 -13
  32. package/dist/convert-audiodata/wsola.js +0 -197
  33. package/dist/get-sink-weak.d.ts +0 -13
  34. package/dist/get-sink-weak.js +0 -15
  35. package/dist/log.d.ts +0 -10
  36. package/dist/log.js +0 -33
  37. package/dist/video/resolve-playback-time.d.ts +0 -8
  38. package/dist/video/resolve-playback-time.js +0 -22
@@ -1,15 +1,179 @@
1
1
  // src/audio/audio.tsx
2
- import { Internals as Internals11, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
2
+ import { Internals as Internals13, useRemotionEnvironment as useRemotionEnvironment2 } from "remotion";
3
3
 
4
4
  // src/audio/audio-for-preview.tsx
5
- import { useContext, useEffect, useMemo, useRef, useState } from "react";
5
+ import { useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
6
6
  import {
7
- Internals as Internals2,
7
+ Internals as Internals5,
8
8
  Audio as RemotionAudio,
9
9
  useBufferState,
10
- useCurrentFrame
10
+ useCurrentFrame as useCurrentFrame2
11
11
  } from "remotion";
12
12
 
13
+ // src/show-in-timeline.ts
14
+ import { useMemo } from "react";
15
+ import { Internals, useVideoConfig } from "remotion";
16
+ var useLoopDisplay = ({
17
+ loop,
18
+ mediaDurationInSeconds,
19
+ playbackRate,
20
+ trimAfter,
21
+ trimBefore
22
+ }) => {
23
+ const { durationInFrames: compDuration, fps } = useVideoConfig();
24
+ const loopDisplay = useMemo(() => {
25
+ if (!loop || !mediaDurationInSeconds) {
26
+ return;
27
+ }
28
+ const durationInFrames = Internals.calculateMediaDuration({
29
+ mediaDurationInFrames: mediaDurationInSeconds * fps,
30
+ playbackRate,
31
+ trimAfter,
32
+ trimBefore
33
+ });
34
+ const maxTimes = compDuration / durationInFrames;
35
+ return {
36
+ numberOfTimes: maxTimes,
37
+ startOffset: 0,
38
+ durationInFrames
39
+ };
40
+ }, [
41
+ compDuration,
42
+ fps,
43
+ loop,
44
+ mediaDurationInSeconds,
45
+ playbackRate,
46
+ trimAfter,
47
+ trimBefore
48
+ ]);
49
+ return loopDisplay;
50
+ };
51
+
52
+ // src/use-media-in-timeline.ts
53
+ import { useContext, useEffect, useState } from "react";
54
+ import { Internals as Internals2, useCurrentFrame } from "remotion";
55
+ var useMediaInTimeline = ({
56
+ volume,
57
+ mediaVolume,
58
+ src,
59
+ mediaType,
60
+ playbackRate,
61
+ displayName,
62
+ stack,
63
+ showInTimeline,
64
+ premountDisplay,
65
+ postmountDisplay,
66
+ loopDisplay,
67
+ trimBefore,
68
+ trimAfter
69
+ }) => {
70
+ const parentSequence = useContext(Internals2.SequenceContext);
71
+ const startsAt = Internals2.useMediaStartsAt();
72
+ const { registerSequence, unregisterSequence } = useContext(Internals2.SequenceManager);
73
+ const [sequenceId] = useState(() => String(Math.random()));
74
+ const [mediaId] = useState(() => String(Math.random()));
75
+ const frame = useCurrentFrame();
76
+ const {
77
+ volumes,
78
+ duration,
79
+ doesVolumeChange,
80
+ nonce,
81
+ rootId,
82
+ isStudio,
83
+ finalDisplayName
84
+ } = Internals2.useBasicMediaInTimeline({
85
+ volume,
86
+ mediaVolume,
87
+ mediaType,
88
+ src,
89
+ displayName,
90
+ trimBefore,
91
+ trimAfter,
92
+ playbackRate
93
+ });
94
+ useEffect(() => {
95
+ if (!src) {
96
+ throw new Error("No src passed");
97
+ }
98
+ if (!isStudio && window.process?.env?.NODE_ENV !== "test") {
99
+ return;
100
+ }
101
+ if (!showInTimeline) {
102
+ return;
103
+ }
104
+ const loopIteration = loopDisplay ? Math.floor(frame / loopDisplay.durationInFrames) : 0;
105
+ if (loopDisplay) {
106
+ registerSequence({
107
+ type: "sequence",
108
+ premountDisplay,
109
+ postmountDisplay,
110
+ parent: parentSequence?.id ?? null,
111
+ displayName: finalDisplayName,
112
+ rootId,
113
+ showInTimeline: true,
114
+ nonce,
115
+ loopDisplay,
116
+ stack,
117
+ from: 0,
118
+ duration,
119
+ id: sequenceId
120
+ });
121
+ }
122
+ registerSequence({
123
+ type: mediaType,
124
+ src,
125
+ id: mediaId,
126
+ duration: loopDisplay?.durationInFrames ?? duration,
127
+ from: loopDisplay ? loopIteration * loopDisplay.durationInFrames : 0,
128
+ parent: loopDisplay ? sequenceId : parentSequence?.id ?? null,
129
+ displayName: finalDisplayName,
130
+ rootId,
131
+ volume: volumes,
132
+ showInTimeline: true,
133
+ nonce,
134
+ startMediaFrom: 0 - startsAt,
135
+ doesVolumeChange,
136
+ loopDisplay: undefined,
137
+ playbackRate,
138
+ stack,
139
+ premountDisplay: null,
140
+ postmountDisplay: null
141
+ });
142
+ return () => {
143
+ if (loopDisplay) {
144
+ unregisterSequence(sequenceId);
145
+ }
146
+ unregisterSequence(mediaId);
147
+ };
148
+ }, [
149
+ doesVolumeChange,
150
+ duration,
151
+ finalDisplayName,
152
+ isStudio,
153
+ loopDisplay,
154
+ mediaId,
155
+ mediaType,
156
+ nonce,
157
+ parentSequence?.id,
158
+ playbackRate,
159
+ postmountDisplay,
160
+ premountDisplay,
161
+ registerSequence,
162
+ rootId,
163
+ sequenceId,
164
+ showInTimeline,
165
+ src,
166
+ stack,
167
+ startsAt,
168
+ unregisterSequence,
169
+ volumes,
170
+ frame
171
+ ]);
172
+ return {
173
+ id: mediaId
174
+ };
175
+ };
176
+
13
177
  // src/video/media-player.ts
14
178
  import {
15
179
  ALL_FORMATS,
@@ -18,7 +182,39 @@ import {
18
182
  Input,
19
183
  UrlSource
20
184
  } from "mediabunny";
21
- import { Internals } from "remotion";
185
+ import { Internals as Internals4 } from "remotion";
186
+
187
+ // src/get-time-in-seconds.ts
188
+ import { Internals as Internals3 } from "remotion";
189
+ var getTimeInSeconds = ({
190
+ loop,
191
+ mediaDurationInSeconds,
192
+ unloopedTimeInSeconds,
193
+ src,
194
+ trimAfter,
195
+ trimBefore,
196
+ fps,
197
+ playbackRate,
198
+ ifNoMediaDuration
199
+ }) => {
200
+ if (mediaDurationInSeconds === null && loop && ifNoMediaDuration === "fail") {
201
+ throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
202
+ }
203
+ const loopDuration = loop ? Internals3.calculateMediaDuration({
204
+ trimAfter,
205
+ mediaDurationInFrames: mediaDurationInSeconds ? mediaDurationInSeconds * fps : Infinity,
206
+ playbackRate: 1,
207
+ trimBefore
208
+ }) / fps : Infinity;
209
+ const timeInSeconds = unloopedTimeInSeconds * playbackRate % loopDuration;
210
+ if ((trimAfter ?? null) !== null && !loop) {
211
+ const time = (trimAfter - (trimBefore ?? 0)) / fps;
212
+ if (timeInSeconds >= time) {
213
+ return null;
214
+ }
215
+ }
216
+ return timeInSeconds + (trimBefore ?? 0) / fps;
217
+ };
22
218
 
23
219
  // src/is-network-error.ts
24
220
  function isNetworkError(error) {
@@ -28,34 +224,6 @@ function isNetworkError(error) {
28
224
  return false;
29
225
  }
30
226
 
31
- // src/video/resolve-playback-time.ts
32
- var resolvePlaybackTime = ({
33
- absolutePlaybackTimeInSeconds,
34
- playbackRate,
35
- loop,
36
- trimBeforeInSeconds,
37
- trimAfterInSeconds,
38
- mediaDurationInSeconds
39
- }) => {
40
- const loopAfterPreliminary = loop ? Math.min(trimAfterInSeconds ?? Infinity, mediaDurationInSeconds ?? Infinity) : Infinity;
41
- const loopAfterConsideringTrimBefore = loopAfterPreliminary - (trimBeforeInSeconds ?? 0);
42
- const loopAfterConsideringPlaybackRate = loopAfterConsideringTrimBefore / playbackRate;
43
- const timeConsideringLoop = absolutePlaybackTimeInSeconds % loopAfterConsideringPlaybackRate;
44
- const time = timeConsideringLoop * playbackRate + (trimBeforeInSeconds ?? 0);
45
- if (Number.isNaN(time)) {
46
- console.log({
47
- absolutePlaybackTimeInSeconds,
48
- playbackRate,
49
- loop,
50
- trimBeforeInSeconds,
51
- trimAfterInSeconds,
52
- mediaDurationInSeconds
53
- });
54
- throw new Error("Time is NaN");
55
- }
56
- return time;
57
- };
58
-
59
227
  // src/video/timeout-utils.ts
60
228
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
61
229
  function withTimeout(promise, timeoutMs, errorMessage = "Operation timed out") {
@@ -93,13 +261,15 @@ class MediaPlayer {
93
261
  audioBufferIterator = null;
94
262
  queuedAudioNodes = new Set;
95
263
  gainNode = null;
264
+ currentVolume = 1;
96
265
  sharedAudioContext;
97
266
  audioSyncAnchor = 0;
98
267
  playing = false;
99
268
  muted = false;
100
269
  loop = false;
101
- trimBeforeSeconds;
102
- trimAfterSeconds;
270
+ fps;
271
+ trimBefore;
272
+ trimAfter;
103
273
  animationFrameId = null;
104
274
  videoAsyncId = 0;
105
275
  audioAsyncId = 0;
@@ -117,10 +287,11 @@ class MediaPlayer {
117
287
  logLevel,
118
288
  sharedAudioContext,
119
289
  loop,
120
- trimBeforeSeconds,
121
- trimAfterSeconds,
290
+ trimBefore,
291
+ trimAfter,
122
292
  playbackRate,
123
- audioStreamIndex
293
+ audioStreamIndex,
294
+ fps
124
295
  }) {
125
296
  this.canvas = canvas ?? null;
126
297
  this.src = src;
@@ -128,12 +299,13 @@ class MediaPlayer {
128
299
  this.sharedAudioContext = sharedAudioContext;
129
300
  this.playbackRate = playbackRate;
130
301
  this.loop = loop;
131
- this.trimBeforeSeconds = trimBeforeSeconds;
132
- this.trimAfterSeconds = trimAfterSeconds;
302
+ this.trimBefore = trimBefore;
303
+ this.trimAfter = trimAfter;
133
304
  this.audioStreamIndex = audioStreamIndex ?? 0;
305
+ this.fps = fps;
134
306
  if (canvas) {
135
307
  const context = canvas.getContext("2d", {
136
- alpha: false,
308
+ alpha: true,
137
309
  desynchronized: true
138
310
  });
139
311
  if (!context) {
@@ -169,15 +341,15 @@ class MediaPlayer {
169
341
  if (isNetworkError(err)) {
170
342
  throw error;
171
343
  }
172
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
344
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Failed to recognize format for ${this.src}`, error);
173
345
  return { type: "unknown-container-format" };
174
346
  }
175
- const [duration, videoTrack, audioTracks] = await Promise.all([
347
+ const [durationInSeconds, videoTrack, audioTracks] = await Promise.all([
176
348
  input.computeDuration(),
177
349
  input.getPrimaryVideoTrack(),
178
350
  input.getAudioTracks()
179
351
  ]);
180
- this.totalDuration = duration;
352
+ this.totalDuration = durationInSeconds;
181
353
  const audioTrack = audioTracks[this.audioStreamIndex] ?? null;
182
354
  if (!videoTrack && !audioTrack) {
183
355
  return { type: "no-tracks" };
@@ -189,7 +361,8 @@ class MediaPlayer {
189
361
  }
190
362
  this.canvasSink = new CanvasSink(videoTrack, {
191
363
  poolSize: 2,
192
- fit: "contain"
364
+ fit: "contain",
365
+ alpha: true
193
366
  });
194
367
  this.canvas.width = videoTrack.displayWidth;
195
368
  this.canvas.height = videoTrack.displayHeight;
@@ -199,14 +372,21 @@ class MediaPlayer {
199
372
  this.gainNode = this.sharedAudioContext.createGain();
200
373
  this.gainNode.connect(this.sharedAudioContext.destination);
201
374
  }
202
- const startTime = resolvePlaybackTime({
203
- absolutePlaybackTimeInSeconds: startTimeUnresolved,
375
+ const startTime = getTimeInSeconds({
376
+ unloopedTimeInSeconds: startTimeUnresolved,
204
377
  playbackRate: this.playbackRate,
205
378
  loop: this.loop,
206
- trimBeforeInSeconds: this.trimBeforeSeconds,
207
- trimAfterInSeconds: this.trimAfterSeconds,
208
- mediaDurationInSeconds: this.totalDuration
379
+ trimBefore: this.trimBefore,
380
+ trimAfter: this.trimAfter,
381
+ mediaDurationInSeconds: this.totalDuration,
382
+ fps: this.fps,
383
+ ifNoMediaDuration: "infinity",
384
+ src: this.src
209
385
  });
386
+ if (startTime === null) {
387
+ this.clearCanvas();
388
+ return { type: "success", durationInSeconds: this.totalDuration };
389
+ }
210
390
  if (this.sharedAudioContext) {
211
391
  this.audioSyncAnchor = this.sharedAudioContext.currentTime - startTime;
212
392
  }
@@ -216,17 +396,22 @@ class MediaPlayer {
216
396
  this.startVideoIterator(startTime)
217
397
  ]);
218
398
  this.startRenderLoop();
219
- return { type: "success" };
399
+ return { type: "success", durationInSeconds };
220
400
  } catch (error) {
221
401
  const err = error;
222
402
  if (isNetworkError(err)) {
223
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
403
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Network/CORS error for ${this.src}`, err);
224
404
  return { type: "network-error" };
225
405
  }
226
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to initialize", error);
406
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to initialize", error);
227
407
  throw error;
228
408
  }
229
409
  }
410
+ clearCanvas() {
411
+ if (this.context && this.canvas) {
412
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
413
+ }
414
+ }
230
415
  cleanupAudioQueue() {
231
416
  for (const node of this.queuedAudioNodes) {
232
417
  node.stop();
@@ -243,16 +428,24 @@ class MediaPlayer {
243
428
  async seekTo(time) {
244
429
  if (!this.isReady())
245
430
  return;
246
- const newTime = resolvePlaybackTime({
247
- absolutePlaybackTimeInSeconds: time,
431
+ const newTime = getTimeInSeconds({
432
+ unloopedTimeInSeconds: time,
248
433
  playbackRate: this.playbackRate,
249
434
  loop: this.loop,
250
- trimBeforeInSeconds: this.trimBeforeSeconds,
251
- trimAfterInSeconds: this.trimAfterSeconds,
252
- mediaDurationInSeconds: this.totalDuration
435
+ trimBefore: this.trimBefore,
436
+ trimAfter: this.trimAfter,
437
+ mediaDurationInSeconds: this.totalDuration ?? null,
438
+ fps: this.fps,
439
+ ifNoMediaDuration: "infinity",
440
+ src: this.src
253
441
  });
442
+ if (newTime === null) {
443
+ this.clearCanvas();
444
+ await this.cleanAudioIteratorAndNodes();
445
+ return;
446
+ }
254
447
  const currentPlaybackTime = this.getPlaybackTime();
255
- const isSignificantSeek = Math.abs(newTime - currentPlaybackTime) > SEEK_THRESHOLD;
448
+ const isSignificantSeek = currentPlaybackTime === null || Math.abs(newTime - currentPlaybackTime) > SEEK_THRESHOLD;
256
449
  if (isSignificantSeek) {
257
450
  this.nextFrame = null;
258
451
  this.audioSyncAnchor = this.sharedAudioContext.currentTime - newTime;
@@ -286,8 +479,8 @@ class MediaPlayer {
286
479
  }
287
480
  setMuted(muted) {
288
481
  this.muted = muted;
289
- if (muted) {
290
- this.cleanupAudioQueue();
482
+ if (this.gainNode) {
483
+ this.gainNode.gain.value = muted ? 0 : this.currentVolume;
291
484
  }
292
485
  }
293
486
  setVolume(volume) {
@@ -295,11 +488,17 @@ class MediaPlayer {
295
488
  return;
296
489
  }
297
490
  const appliedVolume = Math.max(0, volume);
298
- this.gainNode.gain.value = appliedVolume;
491
+ this.currentVolume = appliedVolume;
492
+ if (!this.muted) {
493
+ this.gainNode.gain.value = appliedVolume;
494
+ }
299
495
  }
300
496
  setPlaybackRate(rate) {
301
497
  this.playbackRate = rate;
302
498
  }
499
+ setFps(fps) {
500
+ this.fps = fps;
501
+ }
303
502
  setLoop(loop) {
304
503
  this.loop = loop;
305
504
  }
@@ -311,15 +510,7 @@ class MediaPlayer {
311
510
  this.videoAsyncId++;
312
511
  }
313
512
  getPlaybackTime() {
314
- const absoluteTime = this.sharedAudioContext.currentTime - this.audioSyncAnchor;
315
- return resolvePlaybackTime({
316
- absolutePlaybackTimeInSeconds: absoluteTime,
317
- playbackRate: this.playbackRate,
318
- loop: this.loop,
319
- trimBeforeInSeconds: this.trimBeforeSeconds,
320
- trimAfterInSeconds: this.trimAfterSeconds,
321
- mediaDurationInSeconds: this.totalDuration
322
- });
513
+ return this.sharedAudioContext.currentTime - this.audioSyncAnchor;
323
514
  }
324
515
  scheduleAudioChunk(buffer, mediaTimestamp) {
325
516
  const targetTime = mediaTimestamp + this.audioSyncAnchor;
@@ -384,10 +575,15 @@ class MediaPlayer {
384
575
  }
385
576
  };
386
577
  shouldRenderFrame() {
387
- return !this.isBuffering && this.canRenderVideo() && this.nextFrame !== null && this.nextFrame.timestamp <= this.getPlaybackTime();
578
+ const playbackTime = this.getPlaybackTime();
579
+ if (playbackTime === null) {
580
+ return false;
581
+ }
582
+ return !this.isBuffering && this.canRenderVideo() && this.nextFrame !== null && this.nextFrame.timestamp <= playbackTime;
388
583
  }
389
584
  drawCurrentFrame() {
390
585
  if (this.context && this.nextFrame) {
586
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
391
587
  this.context.drawImage(this.nextFrame.canvas, 0, 0);
392
588
  }
393
589
  if (this.onVideoFrameCallback && this.canvas) {
@@ -408,7 +604,7 @@ class MediaPlayer {
408
604
  this.audioBufferIterator = this.audioSink.buffers(startFromSecond);
409
605
  this.runAudioIterator(startFromSecond, currentAsyncId);
410
606
  } catch (error) {
411
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start audio iterator", error);
607
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start audio iterator", error);
412
608
  }
413
609
  };
414
610
  startVideoIterator = async (timeToSeek) => {
@@ -428,7 +624,7 @@ class MediaPlayer {
428
624
  return;
429
625
  }
430
626
  if (firstFrame && this.context) {
431
- Internals.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew initial frame ${firstFrame.timestamp.toFixed(3)}s`);
627
+ Internals4.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Drew initial frame ${firstFrame.timestamp.toFixed(3)}s`);
432
628
  this.context.drawImage(firstFrame.canvas, 0, 0);
433
629
  if (this.onVideoFrameCallback && this.canvas) {
434
630
  this.onVideoFrameCallback(this.canvas);
@@ -436,10 +632,10 @@ class MediaPlayer {
436
632
  }
437
633
  this.nextFrame = secondFrame ?? null;
438
634
  if (secondFrame) {
439
- Internals.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Buffered next frame ${secondFrame.timestamp.toFixed(3)}s`);
635
+ Internals4.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Buffered next frame ${secondFrame.timestamp.toFixed(3)}s`);
440
636
  }
441
637
  } catch (error) {
442
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start video iterator", error);
638
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to start video iterator", error);
443
639
  }
444
640
  };
445
641
  updateNextFrame = async () => {
@@ -452,16 +648,20 @@ class MediaPlayer {
452
648
  if (!newNextFrame) {
453
649
  break;
454
650
  }
455
- if (newNextFrame.timestamp <= this.getPlaybackTime()) {
651
+ const playbackTime = this.getPlaybackTime();
652
+ if (playbackTime === null) {
653
+ continue;
654
+ }
655
+ if (newNextFrame.timestamp <= playbackTime) {
456
656
  continue;
457
657
  } else {
458
658
  this.nextFrame = newNextFrame;
459
- Internals.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Buffered next frame ${newNextFrame.timestamp.toFixed(3)}s`);
659
+ Internals4.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Buffered next frame ${newNextFrame.timestamp.toFixed(3)}s`);
460
660
  break;
461
661
  }
462
662
  }
463
663
  } catch (error) {
464
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to update next frame", error);
664
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to update next frame", error);
465
665
  }
466
666
  };
467
667
  bufferingStartedAtMs = null;
@@ -486,7 +686,7 @@ class MediaPlayer {
486
686
  const minTimeElapsed = bufferingDuration >= this.minBufferingTimeoutMs;
487
687
  const bufferHealthy = currentBufferDuration >= this.HEALTHY_BUFER_THRESHOLD_SECONDS;
488
688
  if (minTimeElapsed && bufferHealthy) {
489
- Internals.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Resuming from buffering after ${bufferingDuration}ms - buffer recovered`);
689
+ Internals4.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Resuming from buffering after ${bufferingDuration}ms - buffer recovered`);
490
690
  this.setBufferingState(false);
491
691
  }
492
692
  }
@@ -497,7 +697,7 @@ class MediaPlayer {
497
697
  const bufferingDuration = now - this.bufferingStartedAtMs;
498
698
  const forceTimeout = bufferingDuration > this.minBufferingTimeoutMs * 10;
499
699
  if (forceTimeout) {
500
- Internals.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Force resuming from buffering after ${bufferingDuration}ms`);
700
+ Internals4.Log.trace({ logLevel: this.logLevel, tag: "@remotion/media" }, `[MediaPlayer] Force resuming from buffering after ${bufferingDuration}ms`);
501
701
  this.setBufferingState(false);
502
702
  }
503
703
  }
@@ -528,7 +728,7 @@ class MediaPlayer {
528
728
  totalBufferDuration += duration;
529
729
  this.audioBufferHealth = Math.max(0, totalBufferDuration / this.playbackRate);
530
730
  this.maybeResumeFromBuffering(totalBufferDuration / this.playbackRate);
531
- if (this.playing && !this.muted) {
731
+ if (this.playing) {
532
732
  if (isFirstBuffer) {
533
733
  this.audioSyncAnchor = this.sharedAudioContext.currentTime - timestamp;
534
734
  isFirstBuffer = false;
@@ -538,10 +738,15 @@ class MediaPlayer {
538
738
  }
539
739
  this.scheduleAudioChunk(buffer, timestamp);
540
740
  }
541
- if (timestamp - this.getPlaybackTime() >= 1) {
741
+ const playbackTime = this.getPlaybackTime();
742
+ if (playbackTime === null) {
743
+ continue;
744
+ }
745
+ if (timestamp - playbackTime >= 1) {
542
746
  await new Promise((resolve) => {
543
747
  const check = () => {
544
- if (timestamp - this.getPlaybackTime() < 1) {
748
+ const currentPlaybackTime = this.getPlaybackTime();
749
+ if (currentPlaybackTime !== null && timestamp - currentPlaybackTime < 1) {
545
750
  resolve();
546
751
  } else {
547
752
  requestAnimationFrame(check);
@@ -552,7 +757,7 @@ class MediaPlayer {
552
757
  }
553
758
  }
554
759
  } catch (error) {
555
- Internals.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to run audio iterator", error);
760
+ Internals4.Log.error({ logLevel: this.logLevel, tag: "@remotion/media" }, "[MediaPlayer] Failed to run audio iterator", error);
556
761
  }
557
762
  };
558
763
  }
@@ -569,9 +774,8 @@ var {
569
774
  evaluateVolume,
570
775
  warnAboutTooHighVolume,
571
776
  usePreload,
572
- useMediaInTimeline,
573
777
  SequenceContext
574
- } = Internals2;
778
+ } = Internals5;
575
779
  var NewAudioForPreview = ({
576
780
  src,
577
781
  playbackRate,
@@ -591,14 +795,14 @@ var NewAudioForPreview = ({
591
795
  fallbackHtml5AudioProps
592
796
  }) => {
593
797
  const videoConfig = useUnsafeVideoConfig();
594
- const frame = useCurrentFrame();
798
+ const frame = useCurrentFrame2();
595
799
  const mediaPlayerRef = useRef(null);
596
- const [mediaPlayerReady, setMediaPlayerReady] = useState(false);
597
- const [shouldFallbackToNativeAudio, setShouldFallbackToNativeAudio] = useState(false);
800
+ const [mediaPlayerReady, setMediaPlayerReady] = useState2(false);
801
+ const [shouldFallbackToNativeAudio, setShouldFallbackToNativeAudio] = useState2(false);
598
802
  const [playing] = Timeline.usePlayingState();
599
- const timelineContext = useContext(Timeline.TimelineContext);
803
+ const timelineContext = useContext2(Timeline.TimelineContext);
600
804
  const globalPlaybackRate = timelineContext.playbackRate;
601
- const sharedAudioContext = useContext(SharedAudioContext);
805
+ const sharedAudioContext = useContext2(SharedAudioContext);
602
806
  const buffer = useBufferState();
603
807
  const delayHandleRef = useRef(null);
604
808
  const [mediaMuted] = useMediaMutedState();
@@ -620,8 +824,14 @@ var NewAudioForPreview = ({
620
824
  const currentTimeRef = useRef(currentTime);
621
825
  currentTimeRef.current = currentTime;
622
826
  const preloadedSrc = usePreload(src);
623
- const [timelineId] = useState(() => String(Math.random()));
624
- const parentSequence = useContext(SequenceContext);
827
+ const parentSequence = useContext2(SequenceContext);
828
+ const loopDisplay = useLoopDisplay({
829
+ loop,
830
+ mediaDurationInSeconds: videoConfig.durationInFrames,
831
+ playbackRate,
832
+ trimAfter,
833
+ trimBefore
834
+ });
625
835
  useMediaInTimeline({
626
836
  volume,
627
837
  mediaVolume,
@@ -629,13 +839,15 @@ var NewAudioForPreview = ({
629
839
  src,
630
840
  playbackRate,
631
841
  displayName: name ?? null,
632
- id: timelineId,
633
842
  stack,
634
843
  showInTimeline,
635
844
  premountDisplay: parentSequence?.premountDisplay ?? null,
636
- postmountDisplay: parentSequence?.postmountDisplay ?? null
845
+ postmountDisplay: parentSequence?.postmountDisplay ?? null,
846
+ loopDisplay,
847
+ trimAfter,
848
+ trimBefore
637
849
  });
638
- useEffect(() => {
850
+ useEffect2(() => {
639
851
  if (!sharedAudioContext)
640
852
  return;
641
853
  if (!sharedAudioContext.audioContext)
@@ -646,8 +858,9 @@ var NewAudioForPreview = ({
646
858
  logLevel,
647
859
  sharedAudioContext: sharedAudioContext.audioContext,
648
860
  loop,
649
- trimAfterSeconds: trimAfter ? trimAfter / videoConfig.fps : undefined,
650
- trimBeforeSeconds: trimBefore ? trimBefore / videoConfig.fps : undefined,
861
+ trimAfter,
862
+ trimBefore,
863
+ fps: videoConfig.fps,
651
864
  canvas: null,
652
865
  playbackRate,
653
866
  audioStreamIndex: audioStreamIndex ?? 0
@@ -658,7 +871,7 @@ var NewAudioForPreview = ({
658
871
  if (disallowFallbackToHtml5Audio) {
659
872
  throw new Error(`Unknown container format ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
660
873
  }
661
- Internals2.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Audio>`);
874
+ Internals5.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
662
875
  setShouldFallbackToNativeAudio(true);
663
876
  return;
664
877
  }
@@ -666,7 +879,7 @@ var NewAudioForPreview = ({
666
879
  if (disallowFallbackToHtml5Audio) {
667
880
  throw new Error(`Network error fetching ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
668
881
  }
669
- Internals2.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <Audio>`);
882
+ Internals5.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <Html5Audio>`);
670
883
  setShouldFallbackToNativeAudio(true);
671
884
  return;
672
885
  }
@@ -674,7 +887,7 @@ var NewAudioForPreview = ({
674
887
  if (disallowFallbackToHtml5Audio) {
675
888
  throw new Error(`Cannot decode ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
676
889
  }
677
- Internals2.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <Audio>`);
890
+ Internals5.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <Html5Audio>`);
678
891
  setShouldFallbackToNativeAudio(true);
679
892
  return;
680
893
  }
@@ -682,20 +895,20 @@ var NewAudioForPreview = ({
682
895
  if (disallowFallbackToHtml5Audio) {
683
896
  throw new Error(`No video or audio tracks found for ${preloadedSrc}, and 'disallowFallbackToHtml5Audio' was set.`);
684
897
  }
685
- Internals2.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <Audio>`);
898
+ Internals5.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <Html5Audio>`);
686
899
  setShouldFallbackToNativeAudio(true);
687
900
  return;
688
901
  }
689
902
  if (result.type === "success") {
690
903
  setMediaPlayerReady(true);
691
- Internals2.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] MediaPlayer initialized successfully`);
904
+ Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] MediaPlayer initialized successfully`);
692
905
  }
693
906
  }).catch((error) => {
694
- Internals2.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] Failed to initialize MediaPlayer", error);
907
+ Internals5.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] Failed to initialize MediaPlayer", error);
695
908
  setShouldFallbackToNativeAudio(true);
696
909
  });
697
910
  } catch (error) {
698
- Internals2.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer initialization failed", error);
911
+ Internals5.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer initialization failed", error);
699
912
  setShouldFallbackToNativeAudio(true);
700
913
  }
701
914
  return () => {
@@ -704,7 +917,7 @@ var NewAudioForPreview = ({
704
917
  delayHandleRef.current = null;
705
918
  }
706
919
  if (mediaPlayerRef.current) {
707
- Internals2.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] Disposing MediaPlayer`);
920
+ Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] Disposing MediaPlayer`);
708
921
  mediaPlayerRef.current.dispose();
709
922
  mediaPlayerRef.current = null;
710
923
  }
@@ -724,62 +937,69 @@ var NewAudioForPreview = ({
724
937
  audioStreamIndex,
725
938
  disallowFallbackToHtml5Audio
726
939
  ]);
727
- useEffect(() => {
940
+ useEffect2(() => {
728
941
  const audioPlayer = mediaPlayerRef.current;
729
942
  if (!audioPlayer)
730
943
  return;
731
944
  if (playing) {
732
945
  audioPlayer.play().catch((error) => {
733
- Internals2.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] Failed to play", error);
946
+ Internals5.Log.error({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] Failed to play", error);
734
947
  });
735
948
  } else {
736
949
  audioPlayer.pause();
737
950
  }
738
951
  }, [playing, logLevel, mediaPlayerReady]);
739
- useEffect(() => {
952
+ useEffect2(() => {
740
953
  const audioPlayer = mediaPlayerRef.current;
741
954
  if (!audioPlayer || !mediaPlayerReady)
742
955
  return;
743
956
  audioPlayer.seekTo(currentTime);
744
- Internals2.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
957
+ Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewAudioForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
745
958
  }, [currentTime, logLevel, mediaPlayerReady]);
746
- useEffect(() => {
959
+ useEffect2(() => {
747
960
  const audioPlayer = mediaPlayerRef.current;
748
961
  if (!audioPlayer || !mediaPlayerReady)
749
962
  return;
750
963
  audioPlayer.onBufferingChange((newBufferingState) => {
751
964
  if (newBufferingState && !delayHandleRef.current) {
752
965
  delayHandleRef.current = buffer.delayPlayback();
753
- Internals2.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer buffering - blocking Remotion playback");
966
+ Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer buffering - blocking Remotion playback");
754
967
  } else if (!newBufferingState && delayHandleRef.current) {
755
968
  delayHandleRef.current.unblock();
756
969
  delayHandleRef.current = null;
757
- Internals2.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer unbuffering - unblocking Remotion playback");
970
+ Internals5.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewAudioForPreview] MediaPlayer unbuffering - unblocking Remotion playback");
758
971
  }
759
972
  });
760
973
  }, [mediaPlayerReady, buffer, logLevel]);
761
974
  const effectiveMuted = muted || mediaMuted || userPreferredVolume <= 0;
762
- useEffect(() => {
975
+ useEffect2(() => {
763
976
  const audioPlayer = mediaPlayerRef.current;
764
977
  if (!audioPlayer || !mediaPlayerReady)
765
978
  return;
766
979
  audioPlayer.setMuted(effectiveMuted);
767
980
  }, [effectiveMuted, mediaPlayerReady]);
768
- useEffect(() => {
981
+ useEffect2(() => {
769
982
  const audioPlayer = mediaPlayerRef.current;
770
983
  if (!audioPlayer || !mediaPlayerReady) {
771
984
  return;
772
985
  }
773
986
  audioPlayer.setVolume(userPreferredVolume);
774
- }, [userPreferredVolume, mediaPlayerReady, logLevel]);
775
- const effectivePlaybackRate = useMemo(() => playbackRate * globalPlaybackRate, [playbackRate, globalPlaybackRate]);
776
- useEffect(() => {
987
+ }, [userPreferredVolume, mediaPlayerReady]);
988
+ const effectivePlaybackRate = useMemo2(() => playbackRate * globalPlaybackRate, [playbackRate, globalPlaybackRate]);
989
+ useEffect2(() => {
777
990
  const audioPlayer = mediaPlayerRef.current;
778
991
  if (!audioPlayer || !mediaPlayerReady) {
779
992
  return;
780
993
  }
781
994
  audioPlayer.setPlaybackRate(effectivePlaybackRate);
782
- }, [effectivePlaybackRate, mediaPlayerReady, logLevel]);
995
+ }, [effectivePlaybackRate, mediaPlayerReady]);
996
+ useEffect2(() => {
997
+ const audioPlayer = mediaPlayerRef.current;
998
+ if (!audioPlayer || !mediaPlayerReady) {
999
+ return;
1000
+ }
1001
+ audioPlayer.setFps(videoConfig.fps);
1002
+ }, [videoConfig.fps, mediaPlayerReady]);
783
1003
  if (shouldFallbackToNativeAudio && !disallowFallbackToHtml5Audio) {
784
1004
  return /* @__PURE__ */ jsx(RemotionAudio, {
785
1005
  src,
@@ -841,13 +1061,13 @@ var AudioForPreview = ({
841
1061
  };
842
1062
 
843
1063
  // src/audio/audio-for-rendering.tsx
844
- import { useContext as useContext2, useLayoutEffect, useMemo as useMemo2, useState as useState2 } from "react";
1064
+ import { useContext as useContext3, useLayoutEffect, useMemo as useMemo3, useState as useState3 } from "react";
845
1065
  import {
846
- Audio,
847
1066
  cancelRender as cancelRender2,
848
- Internals as Internals10,
1067
+ Html5Audio,
1068
+ Internals as Internals12,
849
1069
  random,
850
- useCurrentFrame as useCurrentFrame2,
1070
+ useCurrentFrame as useCurrentFrame3,
851
1071
  useDelayRender,
852
1072
  useRemotionEnvironment
853
1073
  } from "remotion";
@@ -976,13 +1196,13 @@ var frameForVolumeProp = ({
976
1196
  };
977
1197
 
978
1198
  // src/caches.ts
979
- import { cancelRender, Internals as Internals7 } from "remotion";
1199
+ import { cancelRender, Internals as Internals10 } from "remotion";
980
1200
 
981
1201
  // src/audio-extraction/audio-manager.ts
982
- import { Internals as Internals4 } from "remotion";
1202
+ import { Internals as Internals7 } from "remotion";
983
1203
 
984
1204
  // src/audio-extraction/audio-iterator.ts
985
- import { Internals as Internals3 } from "remotion";
1205
+ import { Internals as Internals6 } from "remotion";
986
1206
 
987
1207
  // src/audio-extraction/audio-cache.ts
988
1208
  var makeAudioCache = () => {
@@ -1060,7 +1280,7 @@ var warnAboutMatroskaOnce = (src, logLevel) => {
1060
1280
  return;
1061
1281
  }
1062
1282
  warned[src] = true;
1063
- Internals3.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`);
1283
+ Internals6.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`);
1064
1284
  };
1065
1285
  var makeAudioIterator = ({
1066
1286
  audioSampleSink,
@@ -1128,7 +1348,7 @@ var makeAudioIterator = ({
1128
1348
  if (openTimestamps.length > 0) {
1129
1349
  const first = openTimestamps[0];
1130
1350
  const last = openTimestamps[openTimestamps.length - 1];
1131
- Internals3.Log.verbose({ logLevel, tag: "@remotion/media" }, "Open audio samples for src", src, `${first.toFixed(3)}...${last.toFixed(3)}`);
1351
+ Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, "Open audio samples for src", src, `${first.toFixed(3)}...${last.toFixed(3)}`);
1132
1352
  }
1133
1353
  };
1134
1354
  const getCacheStats = () => {
@@ -1225,7 +1445,7 @@ var makeAudioManager = () => {
1225
1445
  if (seenKeys.has(key)) {
1226
1446
  iterator.prepareForDeletion();
1227
1447
  iterators.splice(iterators.indexOf(iterator), 1);
1228
- Internals4.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted duplicate iterator for ${iterator.src}`);
1448
+ Internals7.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted duplicate iterator for ${iterator.src}`);
1229
1449
  }
1230
1450
  seenKeys.add(key);
1231
1451
  }
@@ -1307,7 +1527,22 @@ var makeAudioManager = () => {
1307
1527
  };
1308
1528
 
1309
1529
  // src/video-extraction/keyframe-manager.ts
1310
- import { Internals as Internals6 } from "remotion";
1530
+ import { Internals as Internals9 } from "remotion";
1531
+
1532
+ // src/browser-can-use-webgl2.ts
1533
+ var browserCanUseWebGl2 = null;
1534
+ var browserCanUseWebGl2Uncached = () => {
1535
+ const canvas = new OffscreenCanvas(1, 1);
1536
+ const context = canvas.getContext("webgl2");
1537
+ return context !== null;
1538
+ };
1539
+ var canBrowserUseWebGl2 = () => {
1540
+ if (browserCanUseWebGl2 !== null) {
1541
+ return browserCanUseWebGl2;
1542
+ }
1543
+ browserCanUseWebGl2 = browserCanUseWebGl2Uncached();
1544
+ return browserCanUseWebGl2;
1545
+ };
1311
1546
 
1312
1547
  // src/render-timestamp-range.ts
1313
1548
  var renderTimestampRange = (timestamps) => {
@@ -1333,7 +1568,7 @@ import {
1333
1568
  } from "mediabunny";
1334
1569
 
1335
1570
  // src/video-extraction/keyframe-bank.ts
1336
- import { Internals as Internals5 } from "remotion";
1571
+ import { Internals as Internals8 } from "remotion";
1337
1572
  var roundTo4Digits = (timestamp) => {
1338
1573
  return Math.round(timestamp * 1000) / 1000;
1339
1574
  };
@@ -1343,7 +1578,7 @@ var makeKeyframeBank = ({
1343
1578
  sampleIterator,
1344
1579
  logLevel: parentLogLevel
1345
1580
  }) => {
1346
- Internals5.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1581
+ Internals8.Log.verbose({ logLevel: parentLogLevel, tag: "@remotion/media" }, `Creating keyframe bank from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1347
1582
  const frames = {};
1348
1583
  const frameTimestamps = [];
1349
1584
  let lastUsed = Date.now();
@@ -1401,7 +1636,7 @@ var makeKeyframeBank = ({
1401
1636
  return await getFrameFromTimestamp(timestamp) !== null;
1402
1637
  };
1403
1638
  const prepareForDeletion = (logLevel) => {
1404
- Internals5.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion of keyframe bank from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1639
+ Internals8.Log.verbose({ logLevel, tag: "@remotion/media" }, `Preparing for deletion of keyframe bank from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1405
1640
  sampleIterator.return().then((result) => {
1406
1641
  if (result.value) {
1407
1642
  result.value.close();
@@ -1441,7 +1676,7 @@ var makeKeyframeBank = ({
1441
1676
  }
1442
1677
  }
1443
1678
  if (deletedTimestamps.length > 0) {
1444
- Internals5.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)}`);
1679
+ Internals8.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)}`);
1445
1680
  }
1446
1681
  };
1447
1682
  const getOpenFrameCount = () => {
@@ -1617,10 +1852,10 @@ var makeKeyframeManager = () => {
1617
1852
  if (size === 0) {
1618
1853
  continue;
1619
1854
  }
1620
- Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
1855
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, `Open frames for src ${src}: ${renderTimestampRange(timestamps)}`);
1621
1856
  }
1622
1857
  }
1623
- Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
1858
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, `Video cache stats: ${count} open frames, ${totalSize} bytes`);
1624
1859
  };
1625
1860
  const getCacheStats = async () => {
1626
1861
  let count = 0;
@@ -1661,7 +1896,7 @@ var makeKeyframeManager = () => {
1661
1896
  if (mostInThePastBank) {
1662
1897
  await mostInThePastBank.prepareForDeletion(logLevel);
1663
1898
  delete sources[mostInThePastSrc][mostInThePastBank.startTimestampInSeconds];
1664
- Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted frames for src ${mostInThePastSrc} from ${mostInThePastBank.startTimestampInSeconds}sec to ${mostInThePastBank.endTimestampInSeconds}sec to free up memory.`);
1899
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, `Deleted frames for src ${mostInThePastSrc} from ${mostInThePastBank.startTimestampInSeconds}sec to ${mostInThePastBank.endTimestampInSeconds}sec to free up memory.`);
1665
1900
  }
1666
1901
  };
1667
1902
  const ensureToStayUnderMaxCacheSize = async (logLevel) => {
@@ -1687,7 +1922,7 @@ var makeKeyframeManager = () => {
1687
1922
  const { endTimestampInSeconds, startTimestampInSeconds } = bank;
1688
1923
  if (endTimestampInSeconds < threshold) {
1689
1924
  await bank.prepareForDeletion(logLevel);
1690
- Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1925
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, `[Video] Cleared frames for src ${src} from ${startTimestampInSeconds}sec to ${endTimestampInSeconds}sec`);
1691
1926
  delete sources[src][startTimeInSeconds];
1692
1927
  } else {
1693
1928
  bank.deleteFramesBeforeTimestamp({
@@ -1709,6 +1944,10 @@ var makeKeyframeManager = () => {
1709
1944
  const startPacket = await packetSink.getKeyPacket(timestamp, {
1710
1945
  verifyKeyPackets: true
1711
1946
  });
1947
+ const hasAlpha = startPacket?.sideData.alpha;
1948
+ if (hasAlpha && !canBrowserUseWebGl2()) {
1949
+ return "has-alpha";
1950
+ }
1712
1951
  if (!startPacket) {
1713
1952
  return null;
1714
1953
  }
@@ -1727,7 +1966,7 @@ var makeKeyframeManager = () => {
1727
1966
  if (await (await existingBank).hasTimestampInSecond(timestamp)) {
1728
1967
  return existingBank;
1729
1968
  }
1730
- Internals6.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
1969
+ Internals9.Log.verbose({ logLevel, tag: "@remotion/media" }, `Keyframe bank exists but frame at time ${timestamp} does not exist anymore.`);
1731
1970
  await (await existingBank).prepareForDeletion(logLevel);
1732
1971
  delete sources[src][startTimestampInSeconds];
1733
1972
  const replacementKeybank = getFramesSinceKeyframe({
@@ -1815,20 +2054,20 @@ var getUncachedMaxCacheSize = (logLevel) => {
1815
2054
  if (window.remotion_mediaCacheSizeInBytes > 20000 * 1024 * 1024) {
1816
2055
  cancelRender(new Error(`The maximum value for the "mediaCacheSizeInBytes" prop is 20GB (${20000 * 1024 * 1024}), got: ${window.remotion_mediaCacheSizeInBytes}`));
1817
2056
  }
1818
- Internals7.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
2057
+ Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set using "mediaCacheSizeInBytes": ${(window.remotion_mediaCacheSizeInBytes / 1024 / 1024).toFixed(1)} MB`);
1819
2058
  return window.remotion_mediaCacheSizeInBytes;
1820
2059
  }
1821
2060
  if (window.remotion_initialMemoryAvailable !== undefined && window.remotion_initialMemoryAvailable !== null) {
1822
2061
  const value = window.remotion_initialMemoryAvailable / 2;
1823
- if (value < 240 * 1024 * 1024) {
1824
- Internals7.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on minimum value of 240MB (which is more than half of the available system memory!)`);
1825
- return 240 * 1024 * 1024;
2062
+ if (value < 500 * 1024 * 1024) {
2063
+ Internals10.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!)`);
2064
+ return 500 * 1024 * 1024;
1826
2065
  }
1827
2066
  if (value > 20000 * 1024 * 1024) {
1828
- Internals7.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)`);
2067
+ Internals10.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)`);
1829
2068
  return 20000 * 1024 * 1024;
1830
2069
  }
1831
- Internals7.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
2070
+ Internals10.Log.verbose({ logLevel, tag: "@remotion/media" }, `Using cache size set based on available memory (50% of available memory): ${(value / 1024 / 1024).toFixed(1)} MB`);
1832
2071
  return value;
1833
2072
  }
1834
2073
  return 1000 * 1000 * 1000;
@@ -1915,12 +2154,12 @@ var convertAudioData = ({
1915
2154
  };
1916
2155
 
1917
2156
  // src/get-sink.ts
1918
- import { Internals as Internals8 } from "remotion";
2157
+ import { Internals as Internals11 } from "remotion";
1919
2158
  var sinkPromises = {};
1920
2159
  var getSink = (src, logLevel) => {
1921
2160
  let promise = sinkPromises[src];
1922
2161
  if (!promise) {
1923
- Internals8.Log.verbose({
2162
+ Internals11.Log.verbose({
1924
2163
  logLevel,
1925
2164
  tag: "@remotion/media"
1926
2165
  }, `Sink for ${src} was not found, creating new sink`);
@@ -1930,39 +2169,6 @@ var getSink = (src, logLevel) => {
1930
2169
  return promise;
1931
2170
  };
1932
2171
 
1933
- // src/get-time-in-seconds.ts
1934
- import { Internals as Internals9 } from "remotion";
1935
- var getTimeInSeconds = ({
1936
- loop,
1937
- mediaDurationInSeconds,
1938
- unloopedTimeInSeconds,
1939
- src,
1940
- trimAfter,
1941
- trimBefore,
1942
- fps,
1943
- playbackRate
1944
- }) => {
1945
- if (mediaDurationInSeconds === null && loop) {
1946
- throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
1947
- }
1948
- const loopDuration = loop ? Internals9.calculateLoopDuration({
1949
- trimAfter,
1950
- mediaDurationInFrames: mediaDurationInSeconds * fps,
1951
- playbackRate: 1,
1952
- trimBefore
1953
- }) / fps : Infinity;
1954
- const timeInSeconds = unloopedTimeInSeconds * playbackRate % loopDuration;
1955
- if ((trimAfter ?? null) !== null) {
1956
- if (!loop) {
1957
- const time = (trimAfter - (trimBefore ?? 0)) / fps;
1958
- if (timeInSeconds >= time) {
1959
- return null;
1960
- }
1961
- }
1962
- }
1963
- return timeInSeconds + (trimBefore ?? 0) / fps;
1964
- };
1965
-
1966
2172
  // src/audio-extraction/extract-audio.ts
1967
2173
  var extractAudioInternal = async ({
1968
2174
  src,
@@ -1999,7 +2205,8 @@ var extractAudioInternal = async ({
1999
2205
  trimAfter,
2000
2206
  playbackRate,
2001
2207
  trimBefore,
2002
- fps
2208
+ fps,
2209
+ ifNoMediaDuration: "fail"
2003
2210
  });
2004
2211
  if (timeInSeconds === null) {
2005
2212
  return { data: null, durationInSeconds: mediaDurationInSeconds };
@@ -2099,7 +2306,8 @@ var extractFrameInternal = async ({
2099
2306
  trimAfter,
2100
2307
  playbackRate,
2101
2308
  trimBefore,
2102
- fps
2309
+ fps,
2310
+ ifNoMediaDuration: "fail"
2103
2311
  });
2104
2312
  if (timeInSeconds === null) {
2105
2313
  return {
@@ -2115,6 +2323,12 @@ var extractFrameInternal = async ({
2115
2323
  src,
2116
2324
  logLevel
2117
2325
  });
2326
+ if (keyframeBank === "has-alpha") {
2327
+ return {
2328
+ type: "cannot-decode-alpha",
2329
+ durationInSeconds: await sink.getDuration()
2330
+ };
2331
+ }
2118
2332
  if (!keyframeBank) {
2119
2333
  return {
2120
2334
  type: "success",
@@ -2180,6 +2394,12 @@ var extractFrameAndAudio = async ({
2180
2394
  if (frame?.type === "unknown-container-format") {
2181
2395
  return { type: "unknown-container-format" };
2182
2396
  }
2397
+ if (frame?.type === "cannot-decode-alpha") {
2398
+ return {
2399
+ type: "cannot-decode-alpha",
2400
+ durationInSeconds: frame.durationInSeconds
2401
+ };
2402
+ }
2183
2403
  if (audio === "unknown-container-format") {
2184
2404
  if (frame !== null) {
2185
2405
  frame?.frame?.close();
@@ -2239,6 +2459,15 @@ if (window.remotion_broadcastChannel && window.remotion_isMainTab) {
2239
2459
  window.remotion_broadcastChannel.postMessage(cannotDecodeResponse);
2240
2460
  return;
2241
2461
  }
2462
+ if (result.type === "cannot-decode-alpha") {
2463
+ const cannotDecodeAlphaResponse = {
2464
+ type: "response-cannot-decode-alpha",
2465
+ id: data.id,
2466
+ durationInSeconds: result.durationInSeconds
2467
+ };
2468
+ window.remotion_broadcastChannel.postMessage(cannotDecodeAlphaResponse);
2469
+ return;
2470
+ }
2242
2471
  if (result.type === "network-error") {
2243
2472
  const networkErrorResponse = {
2244
2473
  type: "response-network-error",
@@ -2357,6 +2586,14 @@ var extractFrameViaBroadcastChannel = ({
2357
2586
  window.remotion_broadcastChannel.removeEventListener("message", onMessage);
2358
2587
  return;
2359
2588
  }
2589
+ if (data.type === "response-cannot-decode-alpha") {
2590
+ resolve({
2591
+ type: "cannot-decode-alpha",
2592
+ durationInSeconds: data.durationInSeconds
2593
+ });
2594
+ window.remotion_broadcastChannel.removeEventListener("message", onMessage);
2595
+ return;
2596
+ }
2360
2597
  throw new Error(`Invalid message: ${JSON.stringify(data)}`);
2361
2598
  };
2362
2599
  window.remotion_broadcastChannel.addEventListener("message", onMessage);
@@ -2414,11 +2651,11 @@ var AudioForRendering = ({
2414
2651
  trimAfter,
2415
2652
  trimBefore
2416
2653
  }) => {
2417
- const frame = useCurrentFrame2();
2418
- const absoluteFrame = Internals10.useTimelinePosition();
2419
- const videoConfig = Internals10.useUnsafeVideoConfig();
2420
- const { registerRenderAsset, unregisterRenderAsset } = useContext2(Internals10.RenderAssetManager);
2421
- const startsAt = Internals10.useMediaStartsAt();
2654
+ const frame = useCurrentFrame3();
2655
+ const absoluteFrame = Internals12.useTimelinePosition();
2656
+ const videoConfig = Internals12.useUnsafeVideoConfig();
2657
+ const { registerRenderAsset, unregisterRenderAsset } = useContext3(Internals12.RenderAssetManager);
2658
+ const startsAt = Internals12.useMediaStartsAt();
2422
2659
  const environment = useRemotionEnvironment();
2423
2660
  if (!videoConfig) {
2424
2661
  throw new Error("No video config found");
@@ -2428,9 +2665,9 @@ var AudioForRendering = ({
2428
2665
  }
2429
2666
  const { fps } = videoConfig;
2430
2667
  const { delayRender, continueRender } = useDelayRender();
2431
- const [replaceWithHtml5Audio, setReplaceWithHtml5Audio] = useState2(false);
2432
- const sequenceContext = useContext2(Internals10.SequenceContext);
2433
- const id = useMemo2(() => `media-video-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
2668
+ const [replaceWithHtml5Audio, setReplaceWithHtml5Audio] = useState3(false);
2669
+ const sequenceContext = useContext3(Internals12.SequenceContext);
2670
+ const id = useMemo3(() => `media-video-${random(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
2434
2671
  src,
2435
2672
  sequenceContext?.cumulatedFrom,
2436
2673
  sequenceContext?.relativeFrom,
@@ -2474,7 +2711,7 @@ var AudioForRendering = ({
2474
2711
  if (disallowFallbackToHtml5Audio) {
2475
2712
  cancelRender2(new Error(`Unknown container format ${src}, and 'disallowFallbackToHtml5Audio' was set. Failing the render.`));
2476
2713
  }
2477
- Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Audio>`);
2714
+ Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <Html5Audio>`);
2478
2715
  setReplaceWithHtml5Audio(true);
2479
2716
  return;
2480
2717
  }
@@ -2482,15 +2719,18 @@ var AudioForRendering = ({
2482
2719
  if (disallowFallbackToHtml5Audio) {
2483
2720
  cancelRender2(new Error(`Cannot decode ${src}, and 'disallowFallbackToHtml5Audio' was set. Failing the render.`));
2484
2721
  }
2485
- Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${src}, falling back to <Audio>`);
2722
+ Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${src}, falling back to <Html5Audio>`);
2486
2723
  setReplaceWithHtml5Audio(true);
2487
2724
  return;
2488
2725
  }
2726
+ if (result.type === "cannot-decode-alpha") {
2727
+ throw new Error(`Cannot decode alpha component for ${src}, and 'disallowFallbackToHtml5Audio' was set. But this should never happen, since you used the <Audio> tag. Please report this as a bug.`);
2728
+ }
2489
2729
  if (result.type === "network-error") {
2490
2730
  if (disallowFallbackToHtml5Audio) {
2491
2731
  cancelRender2(new Error(`Cannot decode ${src}, and 'disallowFallbackToHtml5Audio' was set. Failing the render.`));
2492
2732
  }
2493
- Internals10.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${src}, falling back to <Audio>`);
2733
+ Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${src}, falling back to <Html5Audio>`);
2494
2734
  setReplaceWithHtml5Audio(true);
2495
2735
  return;
2496
2736
  }
@@ -2503,12 +2743,12 @@ var AudioForRendering = ({
2503
2743
  frame,
2504
2744
  startsAt
2505
2745
  });
2506
- const volume = Internals10.evaluateVolume({
2746
+ const volume = Internals12.evaluateVolume({
2507
2747
  volume: volumeProp,
2508
2748
  frame: volumePropsFrame,
2509
2749
  mediaVolume: 1
2510
2750
  });
2511
- Internals10.warnAboutTooHighVolume(volume);
2751
+ Internals12.warnAboutTooHighVolume(volume);
2512
2752
  if (audio && volume > 0) {
2513
2753
  applyVolume(audio.data, volume);
2514
2754
  registerRenderAsset({
@@ -2557,7 +2797,7 @@ var AudioForRendering = ({
2557
2797
  replaceWithHtml5Audio
2558
2798
  ]);
2559
2799
  if (replaceWithHtml5Audio) {
2560
- return /* @__PURE__ */ jsx2(Audio, {
2800
+ return /* @__PURE__ */ jsx2(Html5Audio, {
2561
2801
  src,
2562
2802
  playbackRate,
2563
2803
  muted,
@@ -2581,8 +2821,8 @@ var AudioForRendering = ({
2581
2821
 
2582
2822
  // src/audio/audio.tsx
2583
2823
  import { jsx as jsx3 } from "react/jsx-runtime";
2584
- var { validateMediaProps } = Internals11;
2585
- var Audio2 = (props) => {
2824
+ var { validateMediaProps } = Internals13;
2825
+ var Audio = (props) => {
2586
2826
  const { name, stack, showInTimeline, ...otherProps } = props;
2587
2827
  const environment = useRemotionEnvironment2();
2588
2828
  if (typeof props.src !== "string") {
@@ -2600,14 +2840,14 @@ var Audio2 = (props) => {
2600
2840
  stack: stack ?? null
2601
2841
  });
2602
2842
  };
2603
- Internals11.addSequenceStackTraces(Audio2);
2843
+ Internals13.addSequenceStackTraces(Audio);
2604
2844
 
2605
2845
  // src/video/video.tsx
2606
- import { Internals as Internals14, useRemotionEnvironment as useRemotionEnvironment4 } from "remotion";
2846
+ import { Internals as Internals16, useRemotionEnvironment as useRemotionEnvironment4 } from "remotion";
2607
2847
 
2608
2848
  // src/video/video-for-preview.tsx
2609
- import { useContext as useContext3, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState as useState3 } from "react";
2610
- import { Internals as Internals12, useBufferState as useBufferState2, useCurrentFrame as useCurrentFrame3, Video } from "remotion";
2849
+ import { useContext as useContext4, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef2, useState as useState4 } from "react";
2850
+ import { Html5Video, Internals as Internals14, useBufferState as useBufferState2, useCurrentFrame as useCurrentFrame4 } from "remotion";
2611
2851
  import { jsx as jsx4 } from "react/jsx-runtime";
2612
2852
  var {
2613
2853
  useUnsafeVideoConfig: useUnsafeVideoConfig2,
@@ -2619,11 +2859,11 @@ var {
2619
2859
  evaluateVolume: evaluateVolume2,
2620
2860
  warnAboutTooHighVolume: warnAboutTooHighVolume2,
2621
2861
  usePreload: usePreload2,
2622
- useMediaInTimeline: useMediaInTimeline2,
2623
- SequenceContext: SequenceContext2
2624
- } = Internals12;
2625
- var NewVideoForPreview = ({
2626
- src,
2862
+ SequenceContext: SequenceContext2,
2863
+ SequenceVisibilityToggleContext
2864
+ } = Internals14;
2865
+ var VideoForPreview = ({
2866
+ src: unpreloadedSrc,
2627
2867
  style,
2628
2868
  playbackRate,
2629
2869
  logLevel,
@@ -2642,19 +2882,22 @@ var NewVideoForPreview = ({
2642
2882
  fallbackOffthreadVideoProps,
2643
2883
  audioStreamIndex
2644
2884
  }) => {
2885
+ const src = usePreload2(unpreloadedSrc);
2645
2886
  const canvasRef = useRef2(null);
2646
2887
  const videoConfig = useUnsafeVideoConfig2();
2647
- const frame = useCurrentFrame3();
2888
+ const frame = useCurrentFrame4();
2648
2889
  const mediaPlayerRef = useRef2(null);
2649
- const [mediaPlayerReady, setMediaPlayerReady] = useState3(false);
2650
- const [shouldFallbackToNativeVideo, setShouldFallbackToNativeVideo] = useState3(false);
2890
+ const [mediaPlayerReady, setMediaPlayerReady] = useState4(false);
2891
+ const [shouldFallbackToNativeVideo, setShouldFallbackToNativeVideo] = useState4(false);
2651
2892
  const [playing] = Timeline2.usePlayingState();
2652
- const timelineContext = useContext3(Timeline2.TimelineContext);
2893
+ const timelineContext = useContext4(Timeline2.TimelineContext);
2653
2894
  const globalPlaybackRate = timelineContext.playbackRate;
2654
- const sharedAudioContext = useContext3(SharedAudioContext2);
2895
+ const sharedAudioContext = useContext4(SharedAudioContext2);
2655
2896
  const buffer = useBufferState2();
2656
2897
  const [mediaMuted] = useMediaMutedState2();
2657
2898
  const [mediaVolume] = useMediaVolumeState2();
2899
+ const [mediaDurationInSeconds, setMediaDurationInSeconds] = useState4(null);
2900
+ const { hidden } = useContext4(SequenceVisibilityToggleContext);
2658
2901
  const volumePropFrame = useFrameForVolumeProp2(loopVolumeCurveBehavior);
2659
2902
  const userPreferredVolume = evaluateVolume2({
2660
2903
  frame: volumePropFrame,
@@ -2662,21 +2905,30 @@ var NewVideoForPreview = ({
2662
2905
  mediaVolume
2663
2906
  });
2664
2907
  warnAboutTooHighVolume2(userPreferredVolume);
2665
- const [timelineId] = useState3(() => String(Math.random()));
2666
- const parentSequence = useContext3(SequenceContext2);
2667
- useMediaInTimeline2({
2908
+ const parentSequence = useContext4(SequenceContext2);
2909
+ const loopDisplay = useLoopDisplay({
2910
+ loop,
2911
+ mediaDurationInSeconds,
2912
+ playbackRate,
2913
+ trimAfter,
2914
+ trimBefore
2915
+ });
2916
+ const { id: timelineId } = useMediaInTimeline({
2668
2917
  volume,
2669
- mediaVolume,
2670
2918
  mediaType: "video",
2671
2919
  src,
2672
2920
  playbackRate,
2673
2921
  displayName: name ?? null,
2674
- id: timelineId,
2675
2922
  stack,
2676
2923
  showInTimeline,
2677
2924
  premountDisplay: parentSequence?.premountDisplay ?? null,
2678
- postmountDisplay: parentSequence?.postmountDisplay ?? null
2925
+ postmountDisplay: parentSequence?.postmountDisplay ?? null,
2926
+ loopDisplay,
2927
+ mediaVolume,
2928
+ trimAfter,
2929
+ trimBefore
2679
2930
  });
2931
+ const isSequenceHidden = hidden[timelineId] ?? false;
2680
2932
  if (!videoConfig) {
2681
2933
  throw new Error("No video config found");
2682
2934
  }
@@ -2687,7 +2939,7 @@ var NewVideoForPreview = ({
2687
2939
  const currentTimeRef = useRef2(currentTime);
2688
2940
  currentTimeRef.current = currentTime;
2689
2941
  const preloadedSrc = usePreload2(src);
2690
- useEffect2(() => {
2942
+ useEffect3(() => {
2691
2943
  if (!canvasRef.current)
2692
2944
  return;
2693
2945
  if (!sharedAudioContext)
@@ -2701,8 +2953,9 @@ var NewVideoForPreview = ({
2701
2953
  logLevel,
2702
2954
  sharedAudioContext: sharedAudioContext.audioContext,
2703
2955
  loop,
2704
- trimAfterSeconds: trimAfter ? trimAfter / videoConfig.fps : undefined,
2705
- trimBeforeSeconds: trimBefore ? trimBefore / videoConfig.fps : undefined,
2956
+ trimAfter,
2957
+ trimBefore,
2958
+ fps: videoConfig.fps,
2706
2959
  playbackRate,
2707
2960
  audioStreamIndex
2708
2961
  });
@@ -2712,7 +2965,7 @@ var NewVideoForPreview = ({
2712
2965
  if (disallowFallbackToOffthreadVideo) {
2713
2966
  throw new Error(`Unknown container format ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
2714
2967
  }
2715
- Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
2968
+ Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${preloadedSrc} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
2716
2969
  setShouldFallbackToNativeVideo(true);
2717
2970
  return;
2718
2971
  }
@@ -2720,7 +2973,7 @@ var NewVideoForPreview = ({
2720
2973
  if (disallowFallbackToOffthreadVideo) {
2721
2974
  throw new Error(`Network error fetching ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
2722
2975
  }
2723
- Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <OffthreadVideo>`);
2976
+ Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, `Network error fetching ${preloadedSrc}, falling back to <OffthreadVideo>`);
2724
2977
  setShouldFallbackToNativeVideo(true);
2725
2978
  return;
2726
2979
  }
@@ -2728,7 +2981,7 @@ var NewVideoForPreview = ({
2728
2981
  if (disallowFallbackToOffthreadVideo) {
2729
2982
  throw new Error(`Cannot decode ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
2730
2983
  }
2731
- Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <OffthreadVideo>`);
2984
+ Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, `Cannot decode ${preloadedSrc}, falling back to <OffthreadVideo>`);
2732
2985
  setShouldFallbackToNativeVideo(true);
2733
2986
  return;
2734
2987
  }
@@ -2736,24 +2989,25 @@ var NewVideoForPreview = ({
2736
2989
  if (disallowFallbackToOffthreadVideo) {
2737
2990
  throw new Error(`No video or audio tracks found for ${preloadedSrc}, and 'disallowFallbackToOffthreadVideo' was set.`);
2738
2991
  }
2739
- Internals12.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <OffthreadVideo>`);
2992
+ Internals14.Log.warn({ logLevel, tag: "@remotion/media" }, `No video or audio tracks found for ${preloadedSrc}, falling back to <OffthreadVideo>`);
2740
2993
  setShouldFallbackToNativeVideo(true);
2741
2994
  return;
2742
2995
  }
2743
2996
  if (result.type === "success") {
2744
2997
  setMediaPlayerReady(true);
2998
+ setMediaDurationInSeconds(result.durationInSeconds);
2745
2999
  }
2746
3000
  }).catch((error) => {
2747
- Internals12.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] Failed to initialize MediaPlayer", error);
3001
+ Internals14.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] Failed to initialize MediaPlayer", error);
2748
3002
  setShouldFallbackToNativeVideo(true);
2749
3003
  });
2750
3004
  } catch (error) {
2751
- Internals12.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer initialization failed", error);
3005
+ Internals14.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer initialization failed", error);
2752
3006
  setShouldFallbackToNativeVideo(true);
2753
3007
  }
2754
3008
  return () => {
2755
3009
  if (mediaPlayerRef.current) {
2756
- Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewVideoForPreview] Disposing MediaPlayer`);
3010
+ Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewVideoForPreview] Disposing MediaPlayer`);
2757
3011
  mediaPlayerRef.current.dispose();
2758
3012
  mediaPlayerRef.current = null;
2759
3013
  }
@@ -2772,29 +3026,29 @@ var NewVideoForPreview = ({
2772
3026
  disallowFallbackToOffthreadVideo,
2773
3027
  audioStreamIndex
2774
3028
  ]);
2775
- const classNameValue = useMemo3(() => {
2776
- return [Internals12.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals12.truthy).join(" ");
3029
+ const classNameValue = useMemo4(() => {
3030
+ return [Internals14.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals14.truthy).join(" ");
2777
3031
  }, [className]);
2778
- useEffect2(() => {
3032
+ useEffect3(() => {
2779
3033
  const mediaPlayer = mediaPlayerRef.current;
2780
3034
  if (!mediaPlayer)
2781
3035
  return;
2782
3036
  if (playing) {
2783
3037
  mediaPlayer.play().catch((error) => {
2784
- Internals12.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] Failed to play", error);
3038
+ Internals14.Log.error({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] Failed to play", error);
2785
3039
  });
2786
3040
  } else {
2787
3041
  mediaPlayer.pause();
2788
3042
  }
2789
3043
  }, [playing, logLevel, mediaPlayerReady]);
2790
- useEffect2(() => {
3044
+ useEffect3(() => {
2791
3045
  const mediaPlayer = mediaPlayerRef.current;
2792
3046
  if (!mediaPlayer || !mediaPlayerReady)
2793
3047
  return;
2794
3048
  mediaPlayer.seekTo(currentTime);
2795
- Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewVideoForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
3049
+ Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, `[NewVideoForPreview] Updating target time to ${currentTime.toFixed(3)}s`);
2796
3050
  }, [currentTime, logLevel, mediaPlayerReady]);
2797
- useEffect2(() => {
3051
+ useEffect3(() => {
2798
3052
  const mediaPlayer = mediaPlayerRef.current;
2799
3053
  if (!mediaPlayer || !mediaPlayerReady)
2800
3054
  return;
@@ -2802,11 +3056,11 @@ var NewVideoForPreview = ({
2802
3056
  const unsubscribe = mediaPlayer.onBufferingChange((newBufferingState) => {
2803
3057
  if (newBufferingState && !currentBlock) {
2804
3058
  currentBlock = buffer.delayPlayback();
2805
- Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer buffering - blocking Remotion playback");
3059
+ Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer buffering - blocking Remotion playback");
2806
3060
  } else if (!newBufferingState && currentBlock) {
2807
3061
  currentBlock.unblock();
2808
3062
  currentBlock = null;
2809
- Internals12.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer unbuffering - unblocking Remotion playback");
3063
+ Internals14.Log.trace({ logLevel, tag: "@remotion/media" }, "[NewVideoForPreview] MediaPlayer unbuffering - unblocking Remotion playback");
2810
3064
  }
2811
3065
  });
2812
3066
  return () => {
@@ -2817,36 +3071,43 @@ var NewVideoForPreview = ({
2817
3071
  }
2818
3072
  };
2819
3073
  }, [mediaPlayerReady, buffer, logLevel]);
2820
- const effectiveMuted = muted || mediaMuted || userPreferredVolume <= 0;
2821
- useEffect2(() => {
3074
+ const effectiveMuted = isSequenceHidden || muted || mediaMuted || userPreferredVolume <= 0;
3075
+ useEffect3(() => {
2822
3076
  const mediaPlayer = mediaPlayerRef.current;
2823
3077
  if (!mediaPlayer || !mediaPlayerReady)
2824
3078
  return;
2825
3079
  mediaPlayer.setMuted(effectiveMuted);
2826
3080
  }, [effectiveMuted, mediaPlayerReady]);
2827
- useEffect2(() => {
3081
+ useEffect3(() => {
2828
3082
  const mediaPlayer = mediaPlayerRef.current;
2829
3083
  if (!mediaPlayer || !mediaPlayerReady) {
2830
3084
  return;
2831
3085
  }
2832
3086
  mediaPlayer.setVolume(userPreferredVolume);
2833
- }, [userPreferredVolume, mediaPlayerReady, logLevel]);
2834
- const effectivePlaybackRate = useMemo3(() => playbackRate * globalPlaybackRate, [playbackRate, globalPlaybackRate]);
2835
- useEffect2(() => {
3087
+ }, [userPreferredVolume, mediaPlayerReady]);
3088
+ const effectivePlaybackRate = useMemo4(() => playbackRate * globalPlaybackRate, [playbackRate, globalPlaybackRate]);
3089
+ useEffect3(() => {
2836
3090
  const mediaPlayer = mediaPlayerRef.current;
2837
3091
  if (!mediaPlayer || !mediaPlayerReady) {
2838
3092
  return;
2839
3093
  }
2840
3094
  mediaPlayer.setPlaybackRate(effectivePlaybackRate);
2841
- }, [effectivePlaybackRate, mediaPlayerReady, logLevel]);
2842
- useEffect2(() => {
3095
+ }, [effectivePlaybackRate, mediaPlayerReady]);
3096
+ useEffect3(() => {
2843
3097
  const mediaPlayer = mediaPlayerRef.current;
2844
3098
  if (!mediaPlayer || !mediaPlayerReady) {
2845
3099
  return;
2846
3100
  }
2847
3101
  mediaPlayer.setLoop(loop);
2848
3102
  }, [loop, mediaPlayerReady]);
2849
- useEffect2(() => {
3103
+ useEffect3(() => {
3104
+ const mediaPlayer = mediaPlayerRef.current;
3105
+ if (!mediaPlayer || !mediaPlayerReady) {
3106
+ return;
3107
+ }
3108
+ mediaPlayer.setFps(videoConfig.fps);
3109
+ }, [videoConfig.fps, mediaPlayerReady]);
3110
+ useEffect3(() => {
2850
3111
  const mediaPlayer = mediaPlayerRef.current;
2851
3112
  if (!mediaPlayer || !mediaPlayerReady || !onVideoFrame) {
2852
3113
  return;
@@ -2856,10 +3117,16 @@ var NewVideoForPreview = ({
2856
3117
  unsubscribe();
2857
3118
  };
2858
3119
  }, [onVideoFrame, mediaPlayerReady]);
3120
+ const actualStyle = useMemo4(() => {
3121
+ return {
3122
+ ...style,
3123
+ opacity: isSequenceHidden ? 0 : style?.opacity ?? 1
3124
+ };
3125
+ }, [isSequenceHidden, style]);
2859
3126
  if (shouldFallbackToNativeVideo && !disallowFallbackToOffthreadVideo) {
2860
- return /* @__PURE__ */ jsx4(Video, {
3127
+ return /* @__PURE__ */ jsx4(Html5Video, {
2861
3128
  src,
2862
- style,
3129
+ style: actualStyle,
2863
3130
  className,
2864
3131
  muted,
2865
3132
  volume,
@@ -2878,74 +3145,32 @@ var NewVideoForPreview = ({
2878
3145
  ref: canvasRef,
2879
3146
  width: videoConfig.width,
2880
3147
  height: videoConfig.height,
2881
- style,
3148
+ style: actualStyle,
2882
3149
  className: classNameValue
2883
3150
  });
2884
3151
  };
2885
- var VideoForPreview = ({
2886
- className,
2887
- loop,
2888
- src,
2889
- logLevel,
2890
- muted,
2891
- name,
2892
- volume,
2893
- loopVolumeCurveBehavior,
2894
- onVideoFrame,
2895
- playbackRate,
2896
- style,
2897
- showInTimeline,
2898
- trimAfter,
2899
- trimBefore,
2900
- stack,
2901
- disallowFallbackToOffthreadVideo,
2902
- fallbackOffthreadVideoProps,
2903
- audioStreamIndex
2904
- }) => {
2905
- const preloadedSrc = usePreload2(src);
2906
- return /* @__PURE__ */ jsx4(NewVideoForPreview, {
2907
- className,
2908
- logLevel,
2909
- muted,
2910
- onVideoFrame,
2911
- playbackRate,
2912
- src: preloadedSrc,
2913
- style,
2914
- volume,
2915
- name,
2916
- trimAfter,
2917
- trimBefore,
2918
- loop,
2919
- loopVolumeCurveBehavior,
2920
- showInTimeline,
2921
- stack,
2922
- disallowFallbackToOffthreadVideo,
2923
- fallbackOffthreadVideoProps,
2924
- audioStreamIndex
2925
- });
2926
- };
2927
3152
 
2928
3153
  // src/video/video-for-rendering.tsx
2929
3154
  import {
2930
- useContext as useContext4,
3155
+ useContext as useContext5,
2931
3156
  useLayoutEffect as useLayoutEffect2,
2932
- useMemo as useMemo4,
3157
+ useMemo as useMemo5,
2933
3158
  useRef as useRef3,
2934
- useState as useState4
3159
+ useState as useState5
2935
3160
  } from "react";
2936
3161
  import {
2937
3162
  cancelRender as cancelRender3,
2938
- Internals as Internals13,
3163
+ Internals as Internals15,
2939
3164
  Loop,
2940
3165
  random as random2,
2941
- useCurrentFrame as useCurrentFrame4,
3166
+ useCurrentFrame as useCurrentFrame5,
2942
3167
  useDelayRender as useDelayRender2,
2943
3168
  useRemotionEnvironment as useRemotionEnvironment3,
2944
- useVideoConfig
3169
+ useVideoConfig as useVideoConfig2
2945
3170
  } from "remotion";
2946
3171
 
2947
- // ../core/src/calculate-loop.ts
2948
- var calculateLoopDuration = ({
3172
+ // ../core/src/calculate-media-duration.ts
3173
+ var calculateMediaDuration = ({
2949
3174
  trimAfter,
2950
3175
  mediaDurationInFrames,
2951
3176
  playbackRate,
@@ -2989,13 +3214,13 @@ var VideoForRendering = ({
2989
3214
  if (!src) {
2990
3215
  throw new TypeError("No `src` was passed to <Video>.");
2991
3216
  }
2992
- const frame = useCurrentFrame4();
2993
- const absoluteFrame = Internals13.useTimelinePosition();
2994
- const { fps } = useVideoConfig();
2995
- const { registerRenderAsset, unregisterRenderAsset } = useContext4(Internals13.RenderAssetManager);
2996
- const startsAt = Internals13.useMediaStartsAt();
2997
- const sequenceContext = useContext4(Internals13.SequenceContext);
2998
- const id = useMemo4(() => `media-video-${random2(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
3217
+ const frame = useCurrentFrame5();
3218
+ const absoluteFrame = Internals15.useTimelinePosition();
3219
+ const { fps } = useVideoConfig2();
3220
+ const { registerRenderAsset, unregisterRenderAsset } = useContext5(Internals15.RenderAssetManager);
3221
+ const startsAt = Internals15.useMediaStartsAt();
3222
+ const sequenceContext = useContext5(Internals15.SequenceContext);
3223
+ const id = useMemo5(() => `media-video-${random2(src)}-${sequenceContext?.cumulatedFrom}-${sequenceContext?.relativeFrom}-${sequenceContext?.durationInFrames}`, [
2999
3224
  src,
3000
3225
  sequenceContext?.cumulatedFrom,
3001
3226
  sequenceContext?.relativeFrom,
@@ -3004,7 +3229,7 @@ var VideoForRendering = ({
3004
3229
  const environment = useRemotionEnvironment3();
3005
3230
  const { delayRender, continueRender } = useDelayRender2();
3006
3231
  const canvasRef = useRef3(null);
3007
- const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState4(false);
3232
+ const [replaceWithOffthreadVideo, setReplaceWithOffthreadVideo] = useState5(false);
3008
3233
  useLayoutEffect2(() => {
3009
3234
  if (!canvasRef.current) {
3010
3235
  return;
@@ -3047,7 +3272,7 @@ var VideoForRendering = ({
3047
3272
  cancelRender3(new Error(`Unknown container format ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
3048
3273
  }
3049
3274
  if (window.remotion_isMainTab) {
3050
- Internals13.Log.info({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
3275
+ Internals15.Log.info({ logLevel, tag: "@remotion/media" }, `Unknown container format for ${src} (Supported formats: https://www.remotion.dev/docs/mediabunny/formats), falling back to <OffthreadVideo>`);
3051
3276
  }
3052
3277
  setReplaceWithOffthreadVideo({ durationInSeconds: null });
3053
3278
  return;
@@ -3057,7 +3282,19 @@ var VideoForRendering = ({
3057
3282
  cancelRender3(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
3058
3283
  }
3059
3284
  if (window.remotion_isMainTab) {
3060
- Internals13.Log.info({ logLevel, tag: "@remotion/media" }, `Cannot decode ${src}, falling back to <OffthreadVideo>`);
3285
+ Internals15.Log.info({ logLevel, tag: "@remotion/media" }, `Cannot decode ${src}, falling back to <OffthreadVideo>`);
3286
+ }
3287
+ setReplaceWithOffthreadVideo({
3288
+ durationInSeconds: result.durationInSeconds
3289
+ });
3290
+ return;
3291
+ }
3292
+ if (result.type === "cannot-decode-alpha") {
3293
+ if (disallowFallbackToOffthreadVideo) {
3294
+ cancelRender3(new Error(`Cannot decode alpha component for ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
3295
+ }
3296
+ if (window.remotion_isMainTab) {
3297
+ Internals15.Log.info({ logLevel, tag: "@remotion/media" }, `Cannot decode alpha component for ${src}, falling back to <OffthreadVideo>`);
3061
3298
  }
3062
3299
  setReplaceWithOffthreadVideo({
3063
3300
  durationInSeconds: result.durationInSeconds
@@ -3069,7 +3306,7 @@ var VideoForRendering = ({
3069
3306
  cancelRender3(new Error(`Cannot decode ${src}, and 'disallowFallbackToOffthreadVideo' was set. Failing the render.`));
3070
3307
  }
3071
3308
  if (window.remotion_isMainTab) {
3072
- Internals13.Log.info({ logLevel, tag: "@remotion/media" }, `Network error fetching ${src}, falling back to <OffthreadVideo>`);
3309
+ Internals15.Log.info({ logLevel, tag: "@remotion/media" }, `Network error fetching ${src}, falling back to <OffthreadVideo>`);
3073
3310
  }
3074
3311
  setReplaceWithOffthreadVideo({ durationInSeconds: null });
3075
3312
  return;
@@ -3081,7 +3318,9 @@ var VideoForRendering = ({
3081
3318
  } = result;
3082
3319
  if (imageBitmap) {
3083
3320
  onVideoFrame?.(imageBitmap);
3084
- const context = canvasRef.current?.getContext("2d");
3321
+ const context = canvasRef.current?.getContext("2d", {
3322
+ alpha: true
3323
+ });
3085
3324
  if (!context) {
3086
3325
  return;
3087
3326
  }
@@ -3091,7 +3330,9 @@ var VideoForRendering = ({
3091
3330
  context.drawImage(imageBitmap, 0, 0);
3092
3331
  imageBitmap.close();
3093
3332
  } else if (window.remotion_videoEnabled) {
3094
- const context = canvasRef.current?.getContext("2d");
3333
+ const context = canvasRef.current?.getContext("2d", {
3334
+ alpha: true
3335
+ });
3095
3336
  if (context) {
3096
3337
  context.clearRect(0, 0, context.canvas.width, context.canvas.height);
3097
3338
  }
@@ -3104,12 +3345,12 @@ var VideoForRendering = ({
3104
3345
  frame,
3105
3346
  startsAt
3106
3347
  });
3107
- const volume = Internals13.evaluateVolume({
3348
+ const volume = Internals15.evaluateVolume({
3108
3349
  volume: volumeProp,
3109
3350
  frame: volumePropsFrame,
3110
3351
  mediaVolume: 1
3111
3352
  });
3112
- Internals13.warnAboutTooHighVolume(volume);
3353
+ Internals15.warnAboutTooHighVolume(volume);
3113
3354
  if (audio && volume > 0) {
3114
3355
  applyVolume(audio.data, volume);
3115
3356
  registerRenderAsset({
@@ -3158,11 +3399,11 @@ var VideoForRendering = ({
3158
3399
  trimAfterValue,
3159
3400
  trimBeforeValue
3160
3401
  ]);
3161
- const classNameValue = useMemo4(() => {
3162
- return [Internals13.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals13.truthy).join(" ");
3402
+ const classNameValue = useMemo5(() => {
3403
+ return [Internals15.OBJECTFIT_CONTAIN_CLASS_NAME, className].filter(Internals15.truthy).join(" ");
3163
3404
  }, [className]);
3164
3405
  if (replaceWithOffthreadVideo) {
3165
- const fallback = /* @__PURE__ */ jsx5(Internals13.InnerOffthreadVideo, {
3406
+ const fallback = /* @__PURE__ */ jsx5(Internals15.InnerOffthreadVideo, {
3166
3407
  src,
3167
3408
  playbackRate: playbackRate ?? 1,
3168
3409
  muted: muted ?? false,
@@ -3172,7 +3413,7 @@ var VideoForRendering = ({
3172
3413
  delayRenderTimeoutInMilliseconds: delayRenderTimeoutInMilliseconds ?? undefined,
3173
3414
  style,
3174
3415
  allowAmplificationDuringRender: true,
3175
- transparent: fallbackOffthreadVideoProps?.transparent ?? false,
3416
+ transparent: fallbackOffthreadVideoProps?.transparent ?? true,
3176
3417
  toneMapped: fallbackOffthreadVideoProps?.toneMapped ?? true,
3177
3418
  audioStreamIndex: audioStreamIndex ?? 0,
3178
3419
  name,
@@ -3202,7 +3443,7 @@ var VideoForRendering = ({
3202
3443
  }
3203
3444
  return /* @__PURE__ */ jsx5(Loop, {
3204
3445
  layout: "none",
3205
- durationInFrames: calculateLoopDuration({
3446
+ durationInFrames: calculateMediaDuration({
3206
3447
  trimAfter: trimAfterValue,
3207
3448
  mediaDurationInFrames: replaceWithOffthreadVideo.durationInSeconds * fps,
3208
3449
  playbackRate,
@@ -3222,7 +3463,7 @@ var VideoForRendering = ({
3222
3463
 
3223
3464
  // src/video/video.tsx
3224
3465
  import { jsx as jsx6 } from "react/jsx-runtime";
3225
- var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } = Internals14;
3466
+ var { validateMediaTrimProps, resolveTrimProps, validateMediaProps: validateMediaProps2 } = Internals16;
3226
3467
  var InnerVideo = ({
3227
3468
  src,
3228
3469
  audioStreamIndex,
@@ -3308,7 +3549,7 @@ var InnerVideo = ({
3308
3549
  fallbackOffthreadVideoProps
3309
3550
  });
3310
3551
  };
3311
- var Video2 = ({
3552
+ var Video = ({
3312
3553
  src,
3313
3554
  audioStreamIndex,
3314
3555
  className,
@@ -3355,14 +3596,14 @@ var Video2 = ({
3355
3596
  stack
3356
3597
  });
3357
3598
  };
3358
- Internals14.addSequenceStackTraces(Video2);
3599
+ Internals16.addSequenceStackTraces(Video);
3359
3600
  // src/index.ts
3360
- var experimental_Audio = Audio2;
3361
- var experimental_Video = Video2;
3601
+ var experimental_Audio = Audio;
3602
+ var experimental_Video = Video;
3362
3603
  export {
3363
3604
  experimental_Video,
3364
3605
  experimental_Audio,
3365
- Video2 as Video,
3606
+ Video,
3366
3607
  AudioForPreview,
3367
- Audio2 as Audio
3608
+ Audio
3368
3609
  };