@remotion/media 4.0.484 → 4.0.485
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/canvas-ahead-of-time.d.ts +1 -0
- package/dist/esm/index.mjs +74 -21
- package/package.json +5 -5
|
@@ -6,6 +6,7 @@ export type CanvasAheadOfTimeNext = {
|
|
|
6
6
|
type: 'pending';
|
|
7
7
|
wait: () => Promise<WrappedCanvas | null>;
|
|
8
8
|
};
|
|
9
|
+
export declare const releaseStableFrame: (frame: WrappedCanvas | null) => void;
|
|
9
10
|
export declare const canvasesAheadOfTime: (videoSink: CanvasSink, startTimestamp?: number | undefined) => {
|
|
10
11
|
next: () => CanvasAheadOfTimeNext;
|
|
11
12
|
closeIterator: () => Promise<void>;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -100,13 +100,13 @@ var getTimeInSeconds = ({
|
|
|
100
100
|
if (mediaDurationInSeconds === null && loop && ifNoMediaDuration === "fail") {
|
|
101
101
|
throw new Error(`Could not determine duration of ${src}, but "loop" was set.`);
|
|
102
102
|
}
|
|
103
|
-
const
|
|
103
|
+
const loopDurationInFrames = loop ? Internals2.calculateMediaDuration({
|
|
104
104
|
trimAfter,
|
|
105
105
|
mediaDurationInFrames: mediaDurationInSeconds ? mediaDurationInSeconds * fps : Infinity,
|
|
106
106
|
playbackRate: 1,
|
|
107
107
|
trimBefore
|
|
108
|
-
})
|
|
109
|
-
const timeInSeconds = unloopedTimeInSeconds * playbackRate %
|
|
108
|
+
}) : Infinity;
|
|
109
|
+
const timeInSeconds = loop ? unloopedTimeInSeconds * playbackRate * fps % loopDurationInFrames / fps : unloopedTimeInSeconds * playbackRate;
|
|
110
110
|
if ((trimAfter ?? null) !== null && !loop) {
|
|
111
111
|
const time = (trimAfter - (trimBefore ?? 0)) / fps;
|
|
112
112
|
if (timeInSeconds >= time) {
|
|
@@ -1043,6 +1043,43 @@ var roundTo4Digits = (timestamp) => {
|
|
|
1043
1043
|
|
|
1044
1044
|
// src/canvas-ahead-of-time.ts
|
|
1045
1045
|
var BUFFER_SIZE = 3;
|
|
1046
|
+
var releaseCanvas = Symbol("releaseCanvas");
|
|
1047
|
+
var releaseStableFrame = (frame) => {
|
|
1048
|
+
frame?.[releaseCanvas]?.();
|
|
1049
|
+
};
|
|
1050
|
+
var makeStableFramePool = () => {
|
|
1051
|
+
const availableCanvases = [];
|
|
1052
|
+
const makeStableFrame = (frame) => {
|
|
1053
|
+
const { canvas } = frame;
|
|
1054
|
+
const stableCanvas = availableCanvases.pop() ?? new OffscreenCanvas(canvas.width, canvas.height);
|
|
1055
|
+
if (stableCanvas.width !== canvas.width) {
|
|
1056
|
+
stableCanvas.width = canvas.width;
|
|
1057
|
+
}
|
|
1058
|
+
if (stableCanvas.height !== canvas.height) {
|
|
1059
|
+
stableCanvas.height = canvas.height;
|
|
1060
|
+
}
|
|
1061
|
+
const context = stableCanvas.getContext("2d");
|
|
1062
|
+
if (!context) {
|
|
1063
|
+
throw new Error("Could not create canvas context");
|
|
1064
|
+
}
|
|
1065
|
+
context.drawImage(canvas, 0, 0);
|
|
1066
|
+
let released = false;
|
|
1067
|
+
const stableFrame = {
|
|
1068
|
+
canvas: stableCanvas,
|
|
1069
|
+
duration: frame.duration,
|
|
1070
|
+
timestamp: frame.timestamp,
|
|
1071
|
+
[releaseCanvas]: () => {
|
|
1072
|
+
if (released) {
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
released = true;
|
|
1076
|
+
availableCanvases.push(stableCanvas);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
return stableFrame;
|
|
1080
|
+
};
|
|
1081
|
+
return { makeStableFrame };
|
|
1082
|
+
};
|
|
1046
1083
|
var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
1047
1084
|
const iterator = videoSink.canvases(startTimestamp);
|
|
1048
1085
|
const buffer = [];
|
|
@@ -1050,8 +1087,9 @@ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
|
1050
1087
|
let reachedEnd = false;
|
|
1051
1088
|
let closed = false;
|
|
1052
1089
|
let inFlight = null;
|
|
1053
|
-
const
|
|
1054
|
-
|
|
1090
|
+
const stableFramePool = makeStableFramePool();
|
|
1091
|
+
const takeFrame = (frame) => {
|
|
1092
|
+
return stableFramePool.makeStableFrame(frame);
|
|
1055
1093
|
};
|
|
1056
1094
|
const fillNext = () => {
|
|
1057
1095
|
if (chaining || reachedEnd || closed)
|
|
@@ -1062,17 +1100,18 @@ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
|
1062
1100
|
const slot = { promise: iterator.next(), resolved: null };
|
|
1063
1101
|
buffer.push(slot);
|
|
1064
1102
|
inFlight = slot.promise.then((result) => {
|
|
1065
|
-
slot.resolved = result;
|
|
1066
1103
|
chaining = false;
|
|
1067
1104
|
inFlight = null;
|
|
1068
1105
|
if (result.done) {
|
|
1106
|
+
slot.resolved = result;
|
|
1069
1107
|
reachedEnd = true;
|
|
1070
1108
|
return;
|
|
1071
1109
|
}
|
|
1072
1110
|
if (closed) {
|
|
1073
|
-
|
|
1111
|
+
slot.resolved = { done: true, value: undefined };
|
|
1074
1112
|
return;
|
|
1075
1113
|
}
|
|
1114
|
+
slot.resolved = { ...result, value: takeFrame(result.value) };
|
|
1076
1115
|
fillNext();
|
|
1077
1116
|
}, () => {
|
|
1078
1117
|
chaining = false;
|
|
@@ -1100,7 +1139,7 @@ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
|
1100
1139
|
return next2.resolved.done ? null : next2.resolved.value;
|
|
1101
1140
|
}
|
|
1102
1141
|
const result = await next2.promise;
|
|
1103
|
-
return result.done ? null : result.value;
|
|
1142
|
+
return result.done ? null : takeFrame(result.value);
|
|
1104
1143
|
}
|
|
1105
1144
|
};
|
|
1106
1145
|
}
|
|
@@ -1114,7 +1153,10 @@ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
|
1114
1153
|
type: "pending",
|
|
1115
1154
|
wait: async () => {
|
|
1116
1155
|
const result = await slot.promise;
|
|
1117
|
-
|
|
1156
|
+
if (slot.resolved) {
|
|
1157
|
+
return slot.resolved.done ? null : slot.resolved.value;
|
|
1158
|
+
}
|
|
1159
|
+
return result.done ? null : takeFrame(result.value);
|
|
1118
1160
|
}
|
|
1119
1161
|
};
|
|
1120
1162
|
};
|
|
@@ -1122,7 +1164,7 @@ var canvasesAheadOfTime = (videoSink, startTimestamp) => {
|
|
|
1122
1164
|
closed = true;
|
|
1123
1165
|
for (const slot of buffer) {
|
|
1124
1166
|
if (slot.resolved && !slot.resolved.done) {
|
|
1125
|
-
|
|
1167
|
+
releaseStableFrame(slot.resolved.value);
|
|
1126
1168
|
}
|
|
1127
1169
|
}
|
|
1128
1170
|
buffer.length = 0;
|
|
@@ -1169,6 +1211,12 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1169
1211
|
const initialFrame = firstAwait && firstAwait.type === "ready" ? firstAwait.frame : await firstAwait.wait();
|
|
1170
1212
|
let lastReturnedFrame = initialFrame;
|
|
1171
1213
|
let peekedFrame = null;
|
|
1214
|
+
const setLastReturnedFrame = (frame) => {
|
|
1215
|
+
if (lastReturnedFrame !== frame) {
|
|
1216
|
+
releaseStableFrame(lastReturnedFrame);
|
|
1217
|
+
}
|
|
1218
|
+
lastReturnedFrame = frame;
|
|
1219
|
+
};
|
|
1172
1220
|
const peek = async () => {
|
|
1173
1221
|
if (peekedFrame) {
|
|
1174
1222
|
return peekedFrame;
|
|
@@ -1184,7 +1232,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1184
1232
|
const getNextOrNullIfNotAvailable = () => {
|
|
1185
1233
|
if (peekedFrame) {
|
|
1186
1234
|
const frame = peekedFrame;
|
|
1187
|
-
|
|
1235
|
+
setLastReturnedFrame(frame);
|
|
1188
1236
|
const retValue = {
|
|
1189
1237
|
type: "got-frame-or-end",
|
|
1190
1238
|
frame
|
|
@@ -1199,7 +1247,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1199
1247
|
waitPromise: async () => {
|
|
1200
1248
|
const res = await next.wait();
|
|
1201
1249
|
if (res) {
|
|
1202
|
-
|
|
1250
|
+
setLastReturnedFrame(res);
|
|
1203
1251
|
} else {
|
|
1204
1252
|
iteratorEnded = true;
|
|
1205
1253
|
}
|
|
@@ -1208,7 +1256,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1208
1256
|
};
|
|
1209
1257
|
}
|
|
1210
1258
|
if (next.frame) {
|
|
1211
|
-
|
|
1259
|
+
setLastReturnedFrame(next.frame);
|
|
1212
1260
|
} else {
|
|
1213
1261
|
iteratorEnded = true;
|
|
1214
1262
|
}
|
|
@@ -1219,15 +1267,21 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1219
1267
|
};
|
|
1220
1268
|
const destroy = () => {
|
|
1221
1269
|
destroyed = true;
|
|
1270
|
+
releaseStableFrame(lastReturnedFrame);
|
|
1271
|
+
if (peekedFrame !== lastReturnedFrame) {
|
|
1272
|
+
releaseStableFrame(peekedFrame);
|
|
1273
|
+
}
|
|
1222
1274
|
lastReturnedFrame = null;
|
|
1275
|
+
peekedFrame = null;
|
|
1223
1276
|
iterator.closeIterator().catch(() => {
|
|
1224
1277
|
return;
|
|
1225
1278
|
});
|
|
1226
1279
|
};
|
|
1227
1280
|
const tryToSatisfySeek = async (time) => {
|
|
1281
|
+
const timestamp = roundTo4Digits(time);
|
|
1228
1282
|
if (lastReturnedFrame) {
|
|
1229
1283
|
const frameTimestamp = roundTo4Digits(lastReturnedFrame.timestamp);
|
|
1230
|
-
if (
|
|
1284
|
+
if (timestamp < frameTimestamp) {
|
|
1231
1285
|
const lastFrameWasInitialFrame = lastReturnedFrame === initialFrame;
|
|
1232
1286
|
const firstFrameDoesSatisfy = lastFrameWasInitialFrame && roundTo4Digits(time) >= roundTo4Digits(timeToSeek);
|
|
1233
1287
|
if (firstFrameDoesSatisfy) {
|
|
@@ -1249,7 +1303,6 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1249
1303
|
}
|
|
1250
1304
|
}
|
|
1251
1305
|
const frameEndTimestamp = roundTo4Digits(lastReturnedFrame.timestamp + lastFrameDuration);
|
|
1252
|
-
const timestamp = roundTo4Digits(time);
|
|
1253
1306
|
if (frameTimestamp <= timestamp && frameEndTimestamp > timestamp) {
|
|
1254
1307
|
return {
|
|
1255
1308
|
type: "satisfied",
|
|
@@ -1293,7 +1346,6 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1293
1346
|
}
|
|
1294
1347
|
const frameTimestamp = roundTo4Digits(frame.frame.timestamp);
|
|
1295
1348
|
const frameEndTimestamp = roundTo4Digits(frame.frame.timestamp + frame.frame.duration);
|
|
1296
|
-
const timestamp = roundTo4Digits(time);
|
|
1297
1349
|
if (frameTimestamp <= timestamp && frameEndTimestamp > timestamp) {
|
|
1298
1350
|
return {
|
|
1299
1351
|
type: "satisfied",
|
|
@@ -1349,7 +1401,7 @@ var videoIteratorManager = async ({
|
|
|
1349
1401
|
}
|
|
1350
1402
|
}
|
|
1351
1403
|
const canvasSink = new CanvasSink(videoTrack, {
|
|
1352
|
-
poolSize:
|
|
1404
|
+
poolSize: 3,
|
|
1353
1405
|
fit: "contain",
|
|
1354
1406
|
alpha: true
|
|
1355
1407
|
});
|
|
@@ -4905,6 +4957,8 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
4905
4957
|
const effectChainState = useEffectChainState();
|
|
4906
4958
|
const effectsRef = useRef2(effects);
|
|
4907
4959
|
effectsRef.current = effects;
|
|
4960
|
+
const onErrorRef = useRef2(onError);
|
|
4961
|
+
onErrorRef.current = onError;
|
|
4908
4962
|
const effectChainStateRef = useRef2(effectChainState);
|
|
4909
4963
|
effectChainStateRef.current = effectChainState;
|
|
4910
4964
|
const parentSequence = useContext4(SequenceContext2);
|
|
@@ -5009,7 +5063,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
5009
5063
|
}
|
|
5010
5064
|
const handleError = (error, fallbackMessage) => {
|
|
5011
5065
|
const [action, errorToUse] = callOnErrorAndResolve({
|
|
5012
|
-
onError,
|
|
5066
|
+
onError: onErrorRef.current,
|
|
5013
5067
|
error,
|
|
5014
5068
|
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
5015
5069
|
isClientSideRendering: false,
|
|
@@ -5044,7 +5098,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
5044
5098
|
}
|
|
5045
5099
|
}).catch((error) => {
|
|
5046
5100
|
const [action, errorToUse] = callOnErrorAndResolve({
|
|
5047
|
-
onError,
|
|
5101
|
+
onError: onErrorRef.current,
|
|
5048
5102
|
error,
|
|
5049
5103
|
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
5050
5104
|
isClientSideRendering: false,
|
|
@@ -5059,7 +5113,7 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
5059
5113
|
} catch (error) {
|
|
5060
5114
|
const [action, errorToUse] = callOnErrorAndResolve({
|
|
5061
5115
|
error,
|
|
5062
|
-
onError,
|
|
5116
|
+
onError: onErrorRef.current,
|
|
5063
5117
|
disallowFallback: disallowFallbackToOffthreadVideo,
|
|
5064
5118
|
isClientSideRendering: false,
|
|
5065
5119
|
clientSideError: error
|
|
@@ -5090,7 +5144,6 @@ var VideoForPreviewAssertedShowing = ({
|
|
|
5090
5144
|
preloadedSrc,
|
|
5091
5145
|
sharedAudioContext,
|
|
5092
5146
|
videoConfig.fps,
|
|
5093
|
-
onError,
|
|
5094
5147
|
credentials,
|
|
5095
5148
|
initialRequestInit,
|
|
5096
5149
|
setMediaDurationInSeconds
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.485",
|
|
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.50.3",
|
|
26
|
+
"remotion": "4.0.485",
|
|
27
27
|
"zod": "4.3.6"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"react-dom": ">=16.8.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
35
|
-
"@remotion/player": "4.0.
|
|
34
|
+
"@remotion/eslint-config-internal": "4.0.485",
|
|
35
|
+
"@remotion/player": "4.0.485",
|
|
36
36
|
"@vitest/browser-webdriverio": "4.0.9",
|
|
37
37
|
"eslint": "9.19.0",
|
|
38
38
|
"react": "19.2.3",
|