@remotion/media 4.0.452 → 4.0.454

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.
@@ -7,7 +7,7 @@ type ExtractAudioParams = {
7
7
  logLevel: LogLevel;
8
8
  loop: boolean;
9
9
  playbackRate: number;
10
- audioStreamIndex: number;
10
+ audioStreamIndex: number | null;
11
11
  trimBefore: number | undefined;
12
12
  trimAfter: number | undefined;
13
13
  fps: number;
@@ -0,0 +1,13 @@
1
+ import type { CanvasSink, WrappedCanvas } from 'mediabunny';
2
+ export type CanvasAheadOfTimeNext = {
3
+ type: 'ready';
4
+ frame: WrappedCanvas | null;
5
+ } | {
6
+ type: 'pending';
7
+ wait: () => Promise<WrappedCanvas | null>;
8
+ };
9
+ export declare const canvasesAheadOfTime: (videoSink: CanvasSink, startTimestamp?: number | undefined) => {
10
+ next: () => CanvasAheadOfTimeNext;
11
+ closeIterator: () => Promise<void>;
12
+ };
13
+ export type CanvasAheadOfTimeIterator = ReturnType<typeof canvasesAheadOfTime>;
@@ -78,13 +78,13 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
78
78
  destroy: () => void;
79
79
  initialFrame: import("mediabunny").WrappedCanvas | null;
80
80
  isDestroyed: () => boolean;
81
- tryToSatisfySeek: (time: number) => Promise<{
81
+ tryToSatisfySeek: (time: number) => {
82
82
  type: "not-satisfied";
83
83
  reason: string;
84
84
  } | {
85
85
  type: "satisfied";
86
86
  frame: import("mediabunny").WrappedCanvas;
87
- }>;
87
+ };
88
88
  } | null;
89
89
  drawFrame: (frame: import("mediabunny").WrappedCanvas) => void;
90
90
  getFramesRendered: () => number;
@@ -45,7 +45,7 @@ import {
45
45
  Internals as Internals8,
46
46
  Audio as RemotionAudio,
47
47
  useBufferState,
48
- useCurrentFrame as useCurrentFrame2,
48
+ useCurrentFrame,
49
49
  useVideoConfig as useVideoConfig2
50
50
  } from "remotion";
51
51
 
@@ -758,6 +758,13 @@ var drawPreviewOverlay = ({
758
758
  }
759
759
  };
760
760
 
761
+ // src/get-duration-or-compute.ts
762
+ var getDurationOrCompute = async (input) => {
763
+ return await input.getDurationFromMetadata(undefined, {
764
+ skipLiveWait: true
765
+ }) ?? input.computeDuration(undefined, { skipLiveWait: true });
766
+ };
767
+
761
768
  // src/is-type-of-error.ts
762
769
  function isNetworkError(error) {
763
770
  if (error.message.includes("Failed to fetch") || error.message.includes("Load failed") || error.message.includes("NetworkError when attempting to fetch resource")) {
@@ -788,12 +795,77 @@ var makeNonceManager = () => {
788
795
  import { CanvasSink } from "mediabunny";
789
796
  import { Internals as Internals3 } from "remotion";
790
797
 
798
+ // src/canvas-ahead-of-time.ts
799
+ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
800
+ const iterator = videoSink.canvases(startTimestamp);
801
+ let inFlight = iterator.next();
802
+ let resolved = null;
803
+ const trackResolution = () => {
804
+ const captured = inFlight;
805
+ captured.then((result) => {
806
+ if (captured === inFlight) {
807
+ resolved = result;
808
+ }
809
+ }, () => {
810
+ return;
811
+ });
812
+ };
813
+ trackResolution();
814
+ const advance = () => {
815
+ inFlight = iterator.next();
816
+ resolved = null;
817
+ trackResolution();
818
+ };
819
+ const next = () => {
820
+ if (resolved) {
821
+ if (resolved.done) {
822
+ return { type: "ready", frame: null };
823
+ }
824
+ const frame = resolved.value;
825
+ advance();
826
+ return { type: "ready", frame };
827
+ }
828
+ const captured = inFlight;
829
+ return {
830
+ type: "pending",
831
+ wait: async () => {
832
+ const result = await captured;
833
+ if (captured === inFlight && !result.done) {
834
+ advance();
835
+ }
836
+ return result.done ? null : result.value;
837
+ }
838
+ };
839
+ };
840
+ const closeFrame = (frame) => {
841
+ frame.close?.();
842
+ };
843
+ const closeIterator = async () => {
844
+ if (resolved) {
845
+ if (!resolved.done) {
846
+ closeFrame(resolved.value);
847
+ }
848
+ } else {
849
+ const captured = inFlight;
850
+ captured.then((result) => {
851
+ if (!result.done) {
852
+ closeFrame(result.value);
853
+ }
854
+ }, () => {
855
+ return;
856
+ });
857
+ }
858
+ await iterator.return();
859
+ };
860
+ return { next, closeIterator };
861
+ };
862
+
791
863
  // src/prewarm-iterator-for-looping.ts
792
864
  var makePrewarmedVideoIteratorCache = (videoSink) => {
793
865
  const prewarmedVideoIterators = new Map;
794
866
  const prewarmIteratorForLooping = ({ timeToSeek }) => {
795
867
  if (!prewarmedVideoIterators.has(timeToSeek)) {
796
- prewarmedVideoIterators.set(timeToSeek, videoSink.canvases(timeToSeek));
868
+ prewarmedVideoIterators.set(timeToSeek, canvasesAheadOfTime(videoSink, timeToSeek));
797
869
  }
798
870
  };
799
871
  const makeIteratorOrUsePrewarmed = (timeToSeek) => {
@@ -802,12 +874,11 @@ var makePrewarmedVideoIteratorCache = (videoSink) => {
802
874
  prewarmedVideoIterators.delete(timeToSeek);
803
875
  return prewarmedIterator;
804
876
  }
805
- const iterator = videoSink.canvases(timeToSeek);
806
- return iterator;
877
+ return canvasesAheadOfTime(videoSink, timeToSeek);
807
878
  };
808
879
  const destroy = () => {
809
880
  for (const iterator of prewarmedVideoIterators.values()) {
810
- iterator.return();
881
+ iterator.closeIterator();
811
882
  }
812
883
  prewarmedVideoIterators.clear();
813
884
  };
@@ -828,48 +899,43 @@ var createVideoIterator = async (timeToSeek, cache) => {
828
899
  let destroyed = false;
829
900
  const iterator = cache.makeIteratorOrUsePrewarmed(timeToSeek);
830
901
  let iteratorEnded = false;
831
- const initialFrame = (await iterator.next())?.value ?? null;
902
+ const firstAwait = iterator.next();
903
+ const initialFrame = firstAwait && firstAwait.type === "ready" ? firstAwait.frame : await firstAwait.wait();
832
904
  let lastReturnedFrame = initialFrame;
833
- const getNextOrNullIfNotAvailable = async () => {
905
+ const getNextOrNullIfNotAvailable = () => {
834
906
  const next = iterator.next();
835
- const result = await Promise.race([
836
- next,
837
- new Promise((resolve) => {
838
- Promise.resolve().then(() => resolve());
839
- })
840
- ]);
841
- if (!result) {
907
+ if (next.type === "pending") {
842
908
  return {
843
909
  type: "need-to-wait-for-it",
844
910
  waitPromise: async () => {
845
- const res = await next;
846
- if (res.value) {
847
- lastReturnedFrame = res.value;
911
+ const res = await next.wait();
912
+ if (res) {
913
+ lastReturnedFrame = res;
848
914
  } else {
849
915
  iteratorEnded = true;
850
916
  }
851
- return res.value;
917
+ return res;
852
918
  }
853
919
  };
854
920
  }
855
- if (result.value) {
856
- lastReturnedFrame = result.value;
921
+ if (next.frame) {
922
+ lastReturnedFrame = next.frame;
857
923
  } else {
858
924
  iteratorEnded = true;
859
925
  }
860
926
  return {
861
927
  type: "got-frame-or-end",
862
- frame: result.value ?? null
928
+ frame: next.frame ?? null
863
929
  };
864
930
  };
865
931
  const destroy = () => {
866
932
  destroyed = true;
867
933
  lastReturnedFrame = null;
868
- iterator.return().catch(() => {
934
+ iterator.closeIterator().catch(() => {
869
935
  return;
870
936
  });
871
937
  };
872
- const tryToSatisfySeek = async (time) => {
938
+ const tryToSatisfySeek = (time) => {
873
939
  if (lastReturnedFrame) {
874
940
  const frameTimestamp = roundTo4Digits(lastReturnedFrame.timestamp);
875
941
  if (roundTo4Digits(time) < frameTimestamp) {
@@ -908,7 +974,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
908
974
  };
909
975
  }
910
976
  while (true) {
911
- const frame = await getNextOrNullIfNotAvailable();
977
+ const frame = getNextOrNullIfNotAvailable();
912
978
  if (frame.type === "need-to-wait-for-it") {
913
979
  return {
914
980
  type: "not-satisfied",
@@ -954,7 +1020,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
954
1020
  };
955
1021
 
956
1022
  // src/video-iterator-manager.ts
957
- var videoIteratorManager = ({
1023
+ var videoIteratorManager = async ({
958
1024
  delayPlaybackHandleIfNotPremounting,
959
1025
  canvas,
960
1026
  context,
@@ -971,9 +1037,11 @@ var videoIteratorManager = ({
971
1037
  let framesRendered = 0;
972
1038
  let currentDelayHandle = null;
973
1039
  if (canvas) {
974
- if (canvas.width !== videoTrack.displayWidth || canvas.height !== videoTrack.displayHeight) {
975
- canvas.width = videoTrack.displayWidth;
976
- canvas.height = videoTrack.displayHeight;
1040
+ const displayWidth = await videoTrack.getDisplayWidth();
1041
+ const displayHeight = await videoTrack.getDisplayHeight();
1042
+ if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
1043
+ canvas.width = displayWidth;
1044
+ canvas.height = displayHeight;
977
1045
  }
978
1046
  }
979
1047
  const canvasSink = new CanvasSink(videoTrack, {
@@ -1034,7 +1102,7 @@ var videoIteratorManager = ({
1034
1102
  });
1035
1103
  }
1036
1104
  }
1037
- const videoSatisfyResult = await videoFrameIterator.tryToSatisfySeek(newTime);
1105
+ const videoSatisfyResult = videoFrameIterator.tryToSatisfySeek(newTime);
1038
1106
  if (videoSatisfyResult.type === "satisfied") {
1039
1107
  drawFrame(videoSatisfyResult.frame);
1040
1108
  return;
@@ -1068,6 +1136,7 @@ var videoIteratorManager = ({
1068
1136
 
1069
1137
  // src/media-player.ts
1070
1138
  class MediaPlayer {
1139
+ tagType;
1071
1140
  canvas;
1072
1141
  context;
1073
1142
  src;
@@ -1114,7 +1183,8 @@ class MediaPlayer {
1114
1183
  onVideoFrameCallback,
1115
1184
  playing,
1116
1185
  sequenceOffset,
1117
- credentials
1186
+ credentials,
1187
+ tagType
1118
1188
  }) {
1119
1189
  this.canvas = canvas ?? null;
1120
1190
  this.src = src;
@@ -1125,7 +1195,7 @@ class MediaPlayer {
1125
1195
  this.loop = loop;
1126
1196
  this.trimBefore = trimBefore;
1127
1197
  this.trimAfter = trimAfter;
1128
- this.audioStreamIndex = audioStreamIndex ?? 0;
1198
+ this.audioStreamIndex = audioStreamIndex;
1129
1199
  this.fps = fps;
1130
1200
  this.debugOverlay = debugOverlay;
1131
1201
  this.bufferState = bufferState;
@@ -1142,6 +1212,7 @@ class MediaPlayer {
1142
1212
  } : undefined),
1143
1213
  formats: ALL_FORMATS
1144
1214
  });
1215
+ this.tagType = tagType;
1145
1216
  if (canvas) {
1146
1217
  const context = canvas.getContext("2d", {
1147
1218
  alpha: true,
@@ -1209,7 +1280,7 @@ class MediaPlayer {
1209
1280
  return { type: "unknown-container-format" };
1210
1281
  }
1211
1282
  const [durationInSeconds, videoTrack, audioTracks] = await Promise.all([
1212
- this.input.computeDuration(),
1283
+ getDurationOrCompute(this.input),
1213
1284
  this.input.getPrimaryVideoTrack(),
1214
1285
  this.input.getAudioTracks()
1215
1286
  ]);
@@ -1217,11 +1288,17 @@ class MediaPlayer {
1217
1288
  return { type: "disposed" };
1218
1289
  }
1219
1290
  this.totalDuration = durationInSeconds;
1220
- const audioTrack = audioTracks[this.audioStreamIndex] ?? null;
1291
+ const audioTrack = await (this.audioStreamIndex === null ? videoTrack?.getPrimaryPairableAudioTrack() : audioTracks[this.audioStreamIndex] ?? null);
1221
1292
  if (!videoTrack && !audioTrack) {
1222
1293
  return { type: "no-tracks" };
1223
1294
  }
1224
- if (videoTrack) {
1295
+ if (videoTrack && this.tagType === "video") {
1296
+ if (await videoTrack.isLive()) {
1297
+ throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + this.src);
1298
+ }
1299
+ if (await videoTrack.isRelativeToUnixEpoch()) {
1300
+ throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + this.src);
1301
+ }
1225
1302
  const canDecode = await videoTrack.canDecode();
1226
1303
  if (!canDecode) {
1227
1304
  return { type: "cannot-decode" };
@@ -1229,7 +1306,7 @@ class MediaPlayer {
1229
1306
  if (this.input.disposed) {
1230
1307
  return { type: "disposed" };
1231
1308
  }
1232
- this.videoIteratorManager = videoIteratorManager({
1309
+ this.videoIteratorManager = await videoIteratorManager({
1233
1310
  videoTrack,
1234
1311
  delayPlaybackHandleIfNotPremounting: this.delayPlaybackHandleIfNotPremounting,
1235
1312
  context: this.context,
@@ -1247,6 +1324,12 @@ class MediaPlayer {
1247
1324
  throw new Error(`should have asserted that the time is not null`);
1248
1325
  }
1249
1326
  if (audioTrack && this.sharedAudioContext) {
1327
+ if (await audioTrack.isLive()) {
1328
+ throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + this.src);
1329
+ }
1330
+ if (await audioTrack.isRelativeToUnixEpoch()) {
1331
+ throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + this.src);
1332
+ }
1250
1333
  const canDecode = await audioTrack.canDecode();
1251
1334
  if (!canDecode) {
1252
1335
  return { type: "cannot-decode" };
@@ -1778,8 +1861,8 @@ var useCommonEffects = ({
1778
1861
  };
1779
1862
 
1780
1863
  // src/use-media-in-timeline.ts
1781
- import { useContext as useContext2, useState, useEffect } from "react";
1782
- import { Internals as Internals7, useCurrentFrame } from "remotion";
1864
+ import { useContext as useContext2, useEffect, useState } from "react";
1865
+ import { Internals as Internals7 } from "remotion";
1783
1866
  var useMediaInTimeline = ({
1784
1867
  volume,
1785
1868
  mediaVolume,
@@ -1799,9 +1882,7 @@ var useMediaInTimeline = ({
1799
1882
  const parentSequence = useContext2(Internals7.SequenceContext);
1800
1883
  const startsAt = Internals7.useMediaStartsAt();
1801
1884
  const { registerSequence, unregisterSequence } = useContext2(Internals7.SequenceManager);
1802
- const [sequenceId] = useState(() => String(Math.random()));
1803
1885
  const [mediaId] = useState(() => String(Math.random()));
1804
- const frame = useCurrentFrame();
1805
1886
  const {
1806
1887
  volumes,
1807
1888
  duration,
@@ -1830,32 +1911,13 @@ var useMediaInTimeline = ({
1830
1911
  if (!showInTimeline) {
1831
1912
  return;
1832
1913
  }
1833
- const loopIteration = loopDisplay ? Math.floor(frame / loopDisplay.durationInFrames) : 0;
1834
- if (loopDisplay) {
1835
- registerSequence({
1836
- type: "sequence",
1837
- premountDisplay,
1838
- postmountDisplay,
1839
- parent: parentSequence?.id ?? null,
1840
- displayName: finalDisplayName,
1841
- rootId,
1842
- showInTimeline: true,
1843
- nonce: nonce.get(),
1844
- loopDisplay,
1845
- stack,
1846
- from: 0,
1847
- duration,
1848
- id: sequenceId,
1849
- controls: null
1850
- });
1851
- }
1852
1914
  registerSequence({
1853
1915
  type: mediaType,
1854
1916
  src,
1855
1917
  id: mediaId,
1856
- duration: loopDisplay?.durationInFrames ?? duration,
1857
- from: loopDisplay ? loopIteration * loopDisplay.durationInFrames : 0,
1858
- parent: loopDisplay ? sequenceId : parentSequence?.id ?? null,
1918
+ duration,
1919
+ from: 0,
1920
+ parent: parentSequence?.id ?? null,
1859
1921
  displayName: finalDisplayName,
1860
1922
  rootId,
1861
1923
  volume: volumes,
@@ -1863,17 +1925,14 @@ var useMediaInTimeline = ({
1863
1925
  nonce: nonce.get(),
1864
1926
  startMediaFrom: 0 - startsAt + (trimBefore ?? 0),
1865
1927
  doesVolumeChange,
1866
- loopDisplay: undefined,
1928
+ loopDisplay,
1867
1929
  playbackRate,
1868
1930
  stack,
1869
- premountDisplay: null,
1870
- postmountDisplay: null,
1931
+ premountDisplay,
1932
+ postmountDisplay,
1871
1933
  controls: controls ?? null
1872
1934
  });
1873
1935
  return () => {
1874
- if (loopDisplay) {
1875
- unregisterSequence(sequenceId);
1876
- }
1877
1936
  unregisterSequence(mediaId);
1878
1937
  };
1879
1938
  }, [
@@ -1892,14 +1951,12 @@ var useMediaInTimeline = ({
1892
1951
  premountDisplay,
1893
1952
  registerSequence,
1894
1953
  rootId,
1895
- sequenceId,
1896
1954
  showInTimeline,
1897
1955
  src,
1898
1956
  stack,
1899
1957
  startsAt,
1900
1958
  unregisterSequence,
1901
1959
  volumes,
1902
- frame,
1903
1960
  trimBefore
1904
1961
  ]);
1905
1962
  return {
@@ -1943,7 +2000,7 @@ var AudioForPreviewAssertedShowing = ({
1943
2000
  controls
1944
2001
  }) => {
1945
2002
  const videoConfig = useUnsafeVideoConfig();
1946
- const frame = useCurrentFrame2();
2003
+ const frame = useCurrentFrame();
1947
2004
  const mediaPlayerRef = useRef(null);
1948
2005
  const initialTrimBeforeRef = useRef(trimBefore);
1949
2006
  const initialTrimAfterRef = useRef(trimAfter);
@@ -2070,7 +2127,7 @@ var AudioForPreviewAssertedShowing = ({
2070
2127
  fps: videoConfig.fps,
2071
2128
  canvas: null,
2072
2129
  playbackRate: initialPlaybackRate.current,
2073
- audioStreamIndex: audioStreamIndex ?? 0,
2130
+ audioStreamIndex: audioStreamIndex ?? null,
2074
2131
  debugOverlay: false,
2075
2132
  bufferState: buffer,
2076
2133
  isPostmounting: initialIsPostmounting.current,
@@ -2080,7 +2137,8 @@ var AudioForPreviewAssertedShowing = ({
2080
2137
  onVideoFrameCallback: null,
2081
2138
  playing: initialPlaying.current,
2082
2139
  sequenceOffset: initialSequenceOffset.current,
2083
- credentials
2140
+ credentials,
2141
+ tagType: "audio"
2084
2142
  });
2085
2143
  mediaPlayerRef.current = player;
2086
2144
  player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
@@ -2218,7 +2276,7 @@ var AudioForPreview = ({
2218
2276
  }) => {
2219
2277
  const preloadedSrc = usePreload(src);
2220
2278
  const defaultLogLevel = Internals8.useLogLevel();
2221
- const frame = useCurrentFrame2();
2279
+ const frame = useCurrentFrame();
2222
2280
  const videoConfig = useVideoConfig2();
2223
2281
  const currentTime = frame / videoConfig.fps;
2224
2282
  const showShow = useMemo2(() => {
@@ -2246,7 +2304,7 @@ var AudioForPreview = ({
2246
2304
  return null;
2247
2305
  }
2248
2306
  return /* @__PURE__ */ jsx(AudioForPreviewAssertedShowing, {
2249
- audioStreamIndex: audioStreamIndex ?? 0,
2307
+ audioStreamIndex,
2250
2308
  src: preloadedSrc,
2251
2309
  playbackRate,
2252
2310
  logLevel: logLevel ?? defaultLogLevel,
@@ -2275,7 +2333,7 @@ import {
2275
2333
  Html5Audio,
2276
2334
  Internals as Internals16,
2277
2335
  random,
2278
- useCurrentFrame as useCurrentFrame3,
2336
+ useCurrentFrame as useCurrentFrame2,
2279
2337
  useDelayRender,
2280
2338
  useRemotionEnvironment
2281
2339
  } from "remotion";
@@ -3458,6 +3516,12 @@ var getSinks = async (src, credentials) => {
3458
3516
  if (!videoTrack) {
3459
3517
  return "no-video-track";
3460
3518
  }
3519
+ if (await videoTrack.isLive()) {
3520
+ throw new Error("Live streams are not currently supported by Remotion. Sorry! Source: " + src);
3521
+ }
3522
+ if (await videoTrack.isRelativeToUnixEpoch()) {
3523
+ throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + src);
3524
+ }
3461
3525
  const canDecode = await videoTrack.canDecode();
3462
3526
  if (!canDecode) {
3463
3527
  return "cannot-decode";
@@ -3491,8 +3555,8 @@ var getSinks = async (src, credentials) => {
3491
3555
  if (format === "network-error") {
3492
3556
  return "network-error";
3493
3557
  }
3494
- const audioTracks = await input.getAudioTracks();
3495
- const audioTrack = audioTracks[index];
3558
+ const videoTrack = await input.getPrimaryVideoTrack();
3559
+ const audioTrack = videoTrack === null ? (await input.getAudioTracks())[index ?? 0] : await (index === null ? videoTrack?.getPrimaryPairableAudioTrack() : (await input.getAudioTracks())[index] ?? null);
3496
3560
  if (!audioTrack) {
3497
3561
  return "no-audio-track";
3498
3562
  }
@@ -3505,11 +3569,12 @@ var getSinks = async (src, credentials) => {
3505
3569
  };
3506
3570
  };
3507
3571
  const getAudioSinksPromise = (index) => {
3508
- if (audioSinksPromise[index]) {
3509
- return audioSinksPromise[index];
3572
+ const keyIndex = index === null ? -1 : index;
3573
+ if (audioSinksPromise[keyIndex]) {
3574
+ return audioSinksPromise[keyIndex];
3510
3575
  }
3511
- audioSinksPromise[index] = getAudioSinks(index);
3512
- return audioSinksPromise[index];
3576
+ audioSinksPromise[keyIndex] = getAudioSinks(index);
3577
+ return audioSinksPromise[keyIndex];
3513
3578
  };
3514
3579
  return {
3515
3580
  getVideo: () => getVideoSinksPromise(),
@@ -3517,7 +3582,7 @@ var getSinks = async (src, credentials) => {
3517
3582
  actualMatroskaTimestamps: rememberActualMatroskaTimestamps(isMatroska),
3518
3583
  isMatroska,
3519
3584
  getDuration: () => {
3520
- return input.computeDuration();
3585
+ return getDurationOrCompute(input);
3521
3586
  }
3522
3587
  };
3523
3588
  };
@@ -4157,7 +4222,7 @@ var AudioForRendering = ({
4157
4222
  }) => {
4158
4223
  const defaultLogLevel = Internals16.useLogLevel();
4159
4224
  const logLevel = overriddenLogLevel ?? defaultLogLevel;
4160
- const frame = useCurrentFrame3();
4225
+ const frame = useCurrentFrame2();
4161
4226
  const absoluteFrame = Internals16.useTimelinePosition();
4162
4227
  const videoConfig = Internals16.useUnsafeVideoConfig();
4163
4228
  const { registerRenderAsset, unregisterRenderAsset } = useContext4(Internals16.RenderAssetManager);
@@ -4213,7 +4278,7 @@ var AudioForRendering = ({
4213
4278
  includeVideo: false,
4214
4279
  isClientSideRendering: environment.isClientSideRendering,
4215
4280
  loop: loop ?? false,
4216
- audioStreamIndex: audioStreamIndex ?? 0,
4281
+ audioStreamIndex: audioStreamIndex ?? null,
4217
4282
  trimAfter,
4218
4283
  trimBefore,
4219
4284
  fps,
@@ -4408,7 +4473,7 @@ import {
4408
4473
  Html5Video,
4409
4474
  Internals as Internals19,
4410
4475
  useBufferState as useBufferState2,
4411
- useCurrentFrame as useCurrentFrame4,
4476
+ useCurrentFrame as useCurrentFrame3,
4412
4477
  useVideoConfig as useVideoConfig3
4413
4478
  } from "remotion";
4414
4479
 
@@ -4500,7 +4565,7 @@ var VideoForPreviewAssertedShowing = ({
4500
4565
  const src = usePreload2(unpreloadedSrc);
4501
4566
  const canvasRef = useRef2(null);
4502
4567
  const videoConfig = useUnsafeVideoConfig2();
4503
- const frame = useCurrentFrame4();
4568
+ const frame = useCurrentFrame3();
4504
4569
  const mediaPlayerRef = useRef2(null);
4505
4570
  const initialTrimBeforeRef = useRef2(trimBefore);
4506
4571
  const initialTrimAfterRef = useRef2(trimAfter);
@@ -4652,7 +4717,8 @@ var VideoForPreviewAssertedShowing = ({
4652
4717
  onVideoFrameCallback: initialOnVideoFrameRef.current ?? null,
4653
4718
  playing: initialPlaying.current,
4654
4719
  sequenceOffset: initialSequenceOffset.current,
4655
- credentials
4720
+ credentials,
4721
+ tagType: "video"
4656
4722
  });
4657
4723
  mediaPlayerRef.current = player;
4658
4724
  player.initialize(currentTimeRef.current, initialMuted.current).then((result) => {
@@ -4821,7 +4887,7 @@ var VideoForPreviewAssertedShowing = ({
4821
4887
  });
4822
4888
  };
4823
4889
  var VideoForPreview = (props) => {
4824
- const frame = useCurrentFrame4();
4890
+ const frame = useCurrentFrame3();
4825
4891
  const videoConfig = useVideoConfig3();
4826
4892
  const currentTime = frame / videoConfig.fps;
4827
4893
  const showShow = useMemo4(() => {
@@ -4866,7 +4932,7 @@ import {
4866
4932
  Internals as Internals20,
4867
4933
  Loop,
4868
4934
  random as random2,
4869
- useCurrentFrame as useCurrentFrame5,
4935
+ useCurrentFrame as useCurrentFrame4,
4870
4936
  useDelayRender as useDelayRender2,
4871
4937
  useRemotionEnvironment as useRemotionEnvironment3,
4872
4938
  useVideoConfig as useVideoConfig4
@@ -4901,7 +4967,7 @@ var VideoForRendering = ({
4901
4967
  if (!src) {
4902
4968
  throw new TypeError("No `src` was passed to <Video>.");
4903
4969
  }
4904
- const frame = useCurrentFrame5();
4970
+ const frame = useCurrentFrame4();
4905
4971
  const absoluteFrame = Internals20.useTimelinePosition();
4906
4972
  const { fps } = useVideoConfig4();
4907
4973
  const { registerRenderAsset, unregisterRenderAsset } = useContext6(Internals20.RenderAssetManager);
@@ -8,7 +8,7 @@ export declare const extractFrameAndAudio: ({ src, timeInSeconds, logLevel, dura
8
8
  includeAudio: boolean;
9
9
  includeVideo: boolean;
10
10
  loop: boolean;
11
- audioStreamIndex: number;
11
+ audioStreamIndex: number | null;
12
12
  trimAfter: number | undefined;
13
13
  trimBefore: number | undefined;
14
14
  fps: number;
@@ -0,0 +1,2 @@
1
+ import type { Input } from 'mediabunny';
2
+ export declare const getDurationOrCompute: (input: Input<import("mediabunny").Source>) => Promise<number>;
@@ -2,7 +2,7 @@ import type { GetSink } from './video-extraction/get-frames-since-keyframe';
2
2
  export declare const sinkPromises: Record<string, Promise<GetSink>>;
3
3
  export declare const getSink: (src: string, logLevel: "error" | "info" | "trace" | "verbose" | "warn", credentials: RequestCredentials | undefined) => Promise<{
4
4
  getVideo: () => Promise<import("./video-extraction/get-frames-since-keyframe").VideoSinkResult>;
5
- getAudio: (index: number) => Promise<import("./video-extraction/get-frames-since-keyframe").AudioSinkResult>;
5
+ getAudio: (index: number | null) => Promise<import("./video-extraction/get-frames-since-keyframe").AudioSinkResult>;
6
6
  actualMatroskaTimestamps: {
7
7
  observeTimestamp: (startTime: number) => void;
8
8
  getRealTimestamp: (observedTimestamp: number) => number | null;
@@ -17,6 +17,7 @@ export type MediaPlayerInitResult = {
17
17
  type: 'disposed';
18
18
  };
19
19
  export declare class MediaPlayer {
20
+ private tagType;
20
21
  private canvas;
21
22
  private context;
22
23
  private src;
@@ -43,7 +44,7 @@ export declare class MediaPlayer {
43
44
  private isPremounting;
44
45
  private isPostmounting;
45
46
  private seekPromiseChain;
46
- constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing, sequenceOffset, credentials }: {
47
+ constructor({ canvas, src, logLevel, sharedAudioContext, loop, trimBefore, trimAfter, playbackRate, globalPlaybackRate, audioStreamIndex, fps, debugOverlay, bufferState, isPremounting, isPostmounting, durationInFrames, onVideoFrameCallback, playing, sequenceOffset, credentials, tagType }: {
47
48
  canvas: HTMLCanvasElement | OffscreenCanvas | null;
48
49
  src: string;
49
50
  logLevel: LogLevel;
@@ -53,7 +54,7 @@ export declare class MediaPlayer {
53
54
  trimAfter: number | undefined;
54
55
  playbackRate: number;
55
56
  globalPlaybackRate: number;
56
- audioStreamIndex: number;
57
+ audioStreamIndex: number | null;
57
58
  fps: number;
58
59
  debugOverlay: boolean;
59
60
  bufferState: ReturnType<typeof useBufferState>;
@@ -64,6 +65,7 @@ export declare class MediaPlayer {
64
65
  playing: boolean;
65
66
  sequenceOffset: number;
66
67
  credentials: RequestCredentials | undefined;
68
+ tagType: 'audio' | 'video';
67
69
  });
68
70
  private input;
69
71
  private isDisposalError;
@@ -1,9 +1,12 @@
1
- import type { CanvasSink, WrappedCanvas } from 'mediabunny';
1
+ import type { CanvasSink } from 'mediabunny';
2
2
  export declare const makePrewarmedVideoIteratorCache: (videoSink: CanvasSink) => {
3
3
  prewarmIteratorForLooping: ({ timeToSeek }: {
4
4
  timeToSeek: number;
5
5
  }) => void;
6
- makeIteratorOrUsePrewarmed: (timeToSeek: number) => AsyncGenerator<WrappedCanvas, void, unknown>;
6
+ makeIteratorOrUsePrewarmed: (timeToSeek: number) => {
7
+ next: () => import("./canvas-ahead-of-time").CanvasAheadOfTimeNext;
8
+ closeIterator: () => Promise<void>;
9
+ };
7
10
  destroy: () => void;
8
11
  };
9
12
  export type PrewarmedVideoIteratorCache = ReturnType<typeof makePrewarmedVideoIteratorCache>;
@@ -3,18 +3,21 @@ export declare const createVideoIterator: (timeToSeek: number, cache: {
3
3
  prewarmIteratorForLooping: ({ timeToSeek }: {
4
4
  timeToSeek: number;
5
5
  }) => void;
6
- makeIteratorOrUsePrewarmed: (timeToSeek: number) => AsyncGenerator<WrappedCanvas, void, unknown>;
6
+ makeIteratorOrUsePrewarmed: (timeToSeek: number) => {
7
+ next: () => import("../canvas-ahead-of-time").CanvasAheadOfTimeNext;
8
+ closeIterator: () => Promise<void>;
9
+ };
7
10
  destroy: () => void;
8
11
  }) => Promise<{
9
12
  destroy: () => void;
10
13
  initialFrame: WrappedCanvas | null;
11
14
  isDestroyed: () => boolean;
12
- tryToSatisfySeek: (time: number) => Promise<{
15
+ tryToSatisfySeek: (time: number) => {
13
16
  type: "not-satisfied";
14
17
  reason: string;
15
18
  } | {
16
19
  type: "satisfied";
17
20
  frame: WrappedCanvas;
18
- }>;
21
+ };
19
22
  }>;
20
23
  export type VideoIterator = Awaited<ReturnType<typeof createVideoIterator>>;
@@ -38,7 +38,7 @@ export type ExtractFrameRequest = {
38
38
  includeAudio: boolean;
39
39
  includeVideo: boolean;
40
40
  loop: boolean;
41
- audioStreamIndex: number;
41
+ audioStreamIndex: number | null;
42
42
  trimAfter: number | undefined;
43
43
  trimBefore: number | undefined;
44
44
  fps: number;
@@ -25,7 +25,7 @@ export declare const extractFrameViaBroadcastChannel: ({ src, timeInSeconds, log
25
25
  includeVideo: boolean;
26
26
  isClientSideRendering: boolean;
27
27
  loop: boolean;
28
- audioStreamIndex: number;
28
+ audioStreamIndex: number | null;
29
29
  trimAfter: number | undefined;
30
30
  trimBefore: number | undefined;
31
31
  fps: number;
@@ -9,7 +9,7 @@ export type AudioSinkResult = AudioSinks | 'no-audio-track' | 'cannot-decode-aud
9
9
  export type VideoSinkResult = VideoSinks | 'no-video-track' | 'cannot-decode' | 'cannot-decode-alpha' | 'unknown-container-format' | 'network-error';
10
10
  export declare const getSinks: (src: string, credentials: RequestCredentials | undefined) => Promise<{
11
11
  getVideo: () => Promise<VideoSinkResult>;
12
- getAudio: (index: number) => Promise<AudioSinkResult>;
12
+ getAudio: (index: number | null) => Promise<AudioSinkResult>;
13
13
  actualMatroskaTimestamps: {
14
14
  observeTimestamp: (startTime: number) => void;
15
15
  getRealTimestamp: (observedTimestamp: number) => number | null;
@@ -12,7 +12,7 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
12
12
  getLoopSegmentMediaEndTimestamp: () => number;
13
13
  getStartTime: () => number;
14
14
  getIsLooping: () => boolean;
15
- }) => {
15
+ }) => Promise<{
16
16
  startVideoIterator: (timeToSeek: number, nonce: Nonce) => Promise<void>;
17
17
  getVideoIteratorsCreated: () => number;
18
18
  seek: ({ newTime, nonce }: {
@@ -24,15 +24,15 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
24
24
  destroy: () => void;
25
25
  initialFrame: WrappedCanvas | null;
26
26
  isDestroyed: () => boolean;
27
- tryToSatisfySeek: (time: number) => Promise<{
27
+ tryToSatisfySeek: (time: number) => {
28
28
  type: "not-satisfied";
29
29
  reason: string;
30
30
  } | {
31
31
  type: "satisfied";
32
32
  frame: WrappedCanvas;
33
- }>;
33
+ };
34
34
  } | null;
35
35
  drawFrame: (frame: WrappedCanvas) => void;
36
36
  getFramesRendered: () => number;
37
- };
38
- export type VideoIteratorManager = ReturnType<typeof videoIteratorManager>;
37
+ }>;
38
+ export type VideoIteratorManager = Awaited<ReturnType<typeof videoIteratorManager>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/media",
3
- "version": "4.0.452",
3
+ "version": "4.0.454",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/esm/index.mjs",
@@ -22,8 +22,8 @@
22
22
  "make": "tsgo && bun --env-file=../.env.bundle bundle.ts"
23
23
  },
24
24
  "dependencies": {
25
- "mediabunny": "1.39.2",
26
- "remotion": "4.0.452",
25
+ "mediabunny": "1.42.0",
26
+ "remotion": "4.0.454",
27
27
  "zod": "4.3.6"
28
28
  },
29
29
  "peerDependencies": {
@@ -31,7 +31,7 @@
31
31
  "react-dom": ">=16.8.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@remotion/eslint-config-internal": "4.0.452",
34
+ "@remotion/eslint-config-internal": "4.0.454",
35
35
  "@vitest/browser-webdriverio": "4.0.9",
36
36
  "eslint": "9.19.0",
37
37
  "react": "19.2.3",
@@ -1,5 +0,0 @@
1
- export declare const calculatePlaybackTime: ({ audioSyncAnchor, currentTime, playbackRate, }: {
2
- audioSyncAnchor: number;
3
- currentTime: number;
4
- playbackRate: number;
5
- }) => number;
@@ -1,11 +0,0 @@
1
- export declare const ALLOWED_GLOBAL_TIME_ANCHOR_SHIFT = 0.1;
2
- export declare const setGlobalTimeAnchor: ({ audioContext, audioSyncAnchor, absoluteTimeInSeconds, globalPlaybackRate, debugAudioScheduling, logLevel, }: {
3
- audioContext: AudioContext;
4
- audioSyncAnchor: {
5
- value: number;
6
- };
7
- absoluteTimeInSeconds: number;
8
- globalPlaybackRate: number;
9
- debugAudioScheduling: boolean;
10
- logLevel: "error" | "info" | "trace" | "verbose" | "warn";
11
- }) => void;