@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.
- package/dist/audio-extraction/extract-audio.d.ts +1 -1
- package/dist/canvas-ahead-of-time.d.ts +13 -0
- package/dist/debug-overlay/preview-overlay.d.ts +2 -2
- package/dist/esm/index.mjs +156 -90
- package/dist/extract-frame-and-audio.d.ts +1 -1
- package/dist/get-duration-or-compute.d.ts +2 -0
- package/dist/get-sink.d.ts +1 -1
- package/dist/media-player.d.ts +4 -2
- package/dist/prewarm-iterator-for-looping.d.ts +5 -2
- package/dist/video/video-preview-iterator.d.ts +6 -3
- package/dist/video-extraction/add-broadcast-channel-listener.d.ts +1 -1
- package/dist/video-extraction/extract-frame-via-broadcast-channel.d.ts +1 -1
- package/dist/video-extraction/get-frames-since-keyframe.d.ts +1 -1
- package/dist/video-iterator-manager.d.ts +5 -5
- package/package.json +4 -4
- package/dist/calculate-playbacktime.d.ts +0 -5
- package/dist/set-global-time-anchor.d.ts +0 -11
|
@@ -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) =>
|
|
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;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
Internals as Internals8,
|
|
46
46
|
Audio as RemotionAudio,
|
|
47
47
|
useBufferState,
|
|
48
|
-
useCurrentFrame
|
|
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
|
|
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
|
-
|
|
806
|
-
return iterator;
|
|
877
|
+
return canvasesAheadOfTime(videoSink, timeToSeek);
|
|
807
878
|
};
|
|
808
879
|
const destroy = () => {
|
|
809
880
|
for (const iterator of prewarmedVideoIterators.values()) {
|
|
810
|
-
iterator.
|
|
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
|
|
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 =
|
|
905
|
+
const getNextOrNullIfNotAvailable = () => {
|
|
834
906
|
const next = iterator.next();
|
|
835
|
-
|
|
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
|
|
847
|
-
lastReturnedFrame = res
|
|
911
|
+
const res = await next.wait();
|
|
912
|
+
if (res) {
|
|
913
|
+
lastReturnedFrame = res;
|
|
848
914
|
} else {
|
|
849
915
|
iteratorEnded = true;
|
|
850
916
|
}
|
|
851
|
-
return res
|
|
917
|
+
return res;
|
|
852
918
|
}
|
|
853
919
|
};
|
|
854
920
|
}
|
|
855
|
-
if (
|
|
856
|
-
lastReturnedFrame =
|
|
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:
|
|
928
|
+
frame: next.frame ?? null
|
|
863
929
|
};
|
|
864
930
|
};
|
|
865
931
|
const destroy = () => {
|
|
866
932
|
destroyed = true;
|
|
867
933
|
lastReturnedFrame = null;
|
|
868
|
-
iterator.
|
|
934
|
+
iterator.closeIterator().catch(() => {
|
|
869
935
|
return;
|
|
870
936
|
});
|
|
871
937
|
};
|
|
872
|
-
const tryToSatisfySeek =
|
|
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 =
|
|
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
|
-
|
|
975
|
-
|
|
976
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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,
|
|
1782
|
-
import { Internals as Internals7
|
|
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
|
|
1857
|
-
from:
|
|
1858
|
-
parent:
|
|
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
|
|
1928
|
+
loopDisplay,
|
|
1867
1929
|
playbackRate,
|
|
1868
1930
|
stack,
|
|
1869
|
-
premountDisplay
|
|
1870
|
-
postmountDisplay
|
|
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 =
|
|
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 ??
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
3495
|
-
const audioTrack =
|
|
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
|
-
|
|
3509
|
-
|
|
3572
|
+
const keyIndex = index === null ? -1 : index;
|
|
3573
|
+
if (audioSinksPromise[keyIndex]) {
|
|
3574
|
+
return audioSinksPromise[keyIndex];
|
|
3510
3575
|
}
|
|
3511
|
-
audioSinksPromise[
|
|
3512
|
-
return audioSinksPromise[
|
|
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
|
|
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 =
|
|
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 ??
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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;
|
package/dist/get-sink.d.ts
CHANGED
|
@@ -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;
|
package/dist/media-player.d.ts
CHANGED
|
@@ -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
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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>>;
|
|
@@ -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) =>
|
|
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.
|
|
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.
|
|
26
|
-
"remotion": "4.0.
|
|
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.
|
|
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,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;
|