@remotion/media 4.0.497 → 4.0.498
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.
|
@@ -68,16 +68,22 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
|
|
|
68
68
|
videoIteratorManager: {
|
|
69
69
|
startVideoIterator: (timeToSeek: number, nonce: import("../nonce-manager").Nonce) => Promise<void>;
|
|
70
70
|
getVideoIteratorsCreated: () => number;
|
|
71
|
-
seek: ({ newTime, nonce }: {
|
|
71
|
+
seek: ({ newTime, nonce, fps, playbackRate, isPlaying, }: {
|
|
72
72
|
newTime: number;
|
|
73
73
|
nonce: import("../nonce-manager").Nonce;
|
|
74
|
+
fps: number;
|
|
75
|
+
playbackRate: number;
|
|
76
|
+
isPlaying: boolean;
|
|
74
77
|
}) => Promise<void>;
|
|
75
78
|
destroy: () => void;
|
|
76
79
|
getVideoFrameIterator: () => {
|
|
77
80
|
destroy: () => void;
|
|
78
81
|
initialFrame: import("mediabunny").WrappedCanvas | null;
|
|
79
82
|
isDestroyed: () => boolean;
|
|
80
|
-
tryToSatisfySeek: (time: number
|
|
83
|
+
tryToSatisfySeek: (time: number, options: {
|
|
84
|
+
pendingFrameBehavior: "restart-iterator" | "wait";
|
|
85
|
+
shouldContinue: () => boolean;
|
|
86
|
+
}) => Promise<{
|
|
81
87
|
type: "not-satisfied";
|
|
82
88
|
reason: string;
|
|
83
89
|
} | {
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1277,7 +1277,6 @@ var makePrewarmedVideoIteratorCache = (videoSink) => {
|
|
|
1277
1277
|
};
|
|
1278
1278
|
|
|
1279
1279
|
// src/video/video-preview-iterator.ts
|
|
1280
|
-
var MAXIMUM_AWAITED_PEEK_DISTANCE_SECONDS = 0.05;
|
|
1281
1280
|
var createVideoIterator = async (timeToSeek, cache) => {
|
|
1282
1281
|
let destroyed = false;
|
|
1283
1282
|
const iterator = cache.makeIteratorOrUsePrewarmed(timeToSeek);
|
|
@@ -1315,22 +1314,12 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1315
1314
|
wait: next.wait
|
|
1316
1315
|
};
|
|
1317
1316
|
};
|
|
1318
|
-
const peek = async () => {
|
|
1319
|
-
const peeked = peekIfReady();
|
|
1320
|
-
if (peeked.type === "ready") {
|
|
1321
|
-
return peeked.frame;
|
|
1322
|
-
}
|
|
1323
|
-
return setPeekedFrame(await peeked.wait());
|
|
1324
|
-
};
|
|
1325
1317
|
const getFrameEndTimestampFromPeek = (frame) => {
|
|
1326
1318
|
return frame ? roundTo4Digits(frame.timestamp) : Infinity;
|
|
1327
1319
|
};
|
|
1328
|
-
const getFrameEndTimestamp = async (
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
const getFrameEndTimestampIfCloseEnough = async ({
|
|
1332
|
-
timestamp,
|
|
1333
|
-
frameTimestamp
|
|
1320
|
+
const getFrameEndTimestamp = async ({
|
|
1321
|
+
pendingFrameBehavior,
|
|
1322
|
+
shouldContinue
|
|
1334
1323
|
}) => {
|
|
1335
1324
|
const peeked = peekIfReady();
|
|
1336
1325
|
if (peeked.type === "ready") {
|
|
@@ -1339,10 +1328,16 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1339
1328
|
timestamp: getFrameEndTimestampFromPeek(peeked.frame)
|
|
1340
1329
|
};
|
|
1341
1330
|
}
|
|
1342
|
-
if (
|
|
1331
|
+
if (pendingFrameBehavior === "restart-iterator") {
|
|
1343
1332
|
return { type: "pending" };
|
|
1344
1333
|
}
|
|
1334
|
+
if (!shouldContinue()) {
|
|
1335
|
+
return { type: "cancelled" };
|
|
1336
|
+
}
|
|
1345
1337
|
const awaitedPeeked = setPeekedFrame(await peeked.wait());
|
|
1338
|
+
if (!shouldContinue()) {
|
|
1339
|
+
return { type: "cancelled" };
|
|
1340
|
+
}
|
|
1346
1341
|
return {
|
|
1347
1342
|
type: "ready",
|
|
1348
1343
|
timestamp: getFrameEndTimestampFromPeek(awaitedPeeked)
|
|
@@ -1396,7 +1391,13 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1396
1391
|
return;
|
|
1397
1392
|
});
|
|
1398
1393
|
};
|
|
1399
|
-
const tryToSatisfySeek = async (time) => {
|
|
1394
|
+
const tryToSatisfySeek = async (time, options) => {
|
|
1395
|
+
if (!options.shouldContinue()) {
|
|
1396
|
+
return {
|
|
1397
|
+
type: "not-satisfied",
|
|
1398
|
+
reason: "seek was superseded"
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1400
1401
|
const timestamp = roundTo4Digits(time);
|
|
1401
1402
|
if (lastReturnedFrame) {
|
|
1402
1403
|
const frameTimestamp = roundTo4Digits(lastReturnedFrame.timestamp);
|
|
@@ -1414,8 +1415,23 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1414
1415
|
reason: `iterator is too far, most recently returned ${frameTimestamp}`
|
|
1415
1416
|
};
|
|
1416
1417
|
}
|
|
1417
|
-
const frameEndTimestamp = await getFrameEndTimestamp(
|
|
1418
|
-
|
|
1418
|
+
const frameEndTimestamp = await getFrameEndTimestamp({
|
|
1419
|
+
pendingFrameBehavior: options.pendingFrameBehavior,
|
|
1420
|
+
shouldContinue: options.shouldContinue
|
|
1421
|
+
});
|
|
1422
|
+
if (frameEndTimestamp.type === "cancelled") {
|
|
1423
|
+
return {
|
|
1424
|
+
type: "not-satisfied",
|
|
1425
|
+
reason: "seek was superseded"
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
if (frameEndTimestamp.type === "pending") {
|
|
1429
|
+
return {
|
|
1430
|
+
type: "not-satisfied",
|
|
1431
|
+
reason: "iterator did not have next frame ready"
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
if (frameTimestamp <= timestamp && frameEndTimestamp.timestamp > timestamp) {
|
|
1419
1435
|
return {
|
|
1420
1436
|
type: "satisfied",
|
|
1421
1437
|
frame: lastReturnedFrame
|
|
@@ -1435,6 +1451,12 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1435
1451
|
};
|
|
1436
1452
|
}
|
|
1437
1453
|
while (true) {
|
|
1454
|
+
if (!options.shouldContinue()) {
|
|
1455
|
+
return {
|
|
1456
|
+
type: "not-satisfied",
|
|
1457
|
+
reason: "seek was superseded"
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1438
1460
|
const frame = getNextOrNullIfNotAvailable();
|
|
1439
1461
|
if (frame.type === "need-to-wait-for-it") {
|
|
1440
1462
|
return {
|
|
@@ -1457,10 +1479,16 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1457
1479
|
};
|
|
1458
1480
|
}
|
|
1459
1481
|
const frameTimestamp = roundTo4Digits(frame.frame.timestamp);
|
|
1460
|
-
const frameEndTimestamp = await
|
|
1461
|
-
|
|
1462
|
-
|
|
1482
|
+
const frameEndTimestamp = await getFrameEndTimestamp({
|
|
1483
|
+
pendingFrameBehavior: options.pendingFrameBehavior,
|
|
1484
|
+
shouldContinue: options.shouldContinue
|
|
1463
1485
|
});
|
|
1486
|
+
if (frameEndTimestamp.type === "cancelled") {
|
|
1487
|
+
return {
|
|
1488
|
+
type: "not-satisfied",
|
|
1489
|
+
reason: "seek was superseded"
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1464
1492
|
if (frameEndTimestamp.type === "pending") {
|
|
1465
1493
|
return {
|
|
1466
1494
|
type: "not-satisfied",
|
|
@@ -1490,6 +1518,19 @@ var createVideoIterator = async (timeToSeek, cache) => {
|
|
|
1490
1518
|
|
|
1491
1519
|
// src/video-iterator-manager.ts
|
|
1492
1520
|
var { runEffectChain } = Internals4;
|
|
1521
|
+
var isSequentialMediaTimeAdvance = ({
|
|
1522
|
+
previousTime,
|
|
1523
|
+
newTime,
|
|
1524
|
+
fps,
|
|
1525
|
+
playbackRate,
|
|
1526
|
+
isPlaying
|
|
1527
|
+
}) => {
|
|
1528
|
+
if (!isPlaying || newTime < previousTime) {
|
|
1529
|
+
return false;
|
|
1530
|
+
}
|
|
1531
|
+
const maximumSequentialAdvance = Math.abs(playbackRate) / fps;
|
|
1532
|
+
return roundTo4Digits(newTime - previousTime) <= roundTo4Digits(maximumSequentialAdvance);
|
|
1533
|
+
};
|
|
1493
1534
|
var videoIteratorManager = async ({
|
|
1494
1535
|
delayPlaybackHandleIfNotPremounting,
|
|
1495
1536
|
canvas,
|
|
@@ -1599,13 +1640,20 @@ var videoIteratorManager = async ({
|
|
|
1599
1640
|
__callDispose(__stack, _err, _hasErr);
|
|
1600
1641
|
}
|
|
1601
1642
|
};
|
|
1602
|
-
const seek = async ({
|
|
1643
|
+
const seek = async ({
|
|
1644
|
+
newTime,
|
|
1645
|
+
nonce,
|
|
1646
|
+
fps,
|
|
1647
|
+
playbackRate,
|
|
1648
|
+
isPlaying
|
|
1649
|
+
}) => {
|
|
1603
1650
|
if (!videoFrameIterator) {
|
|
1604
1651
|
return;
|
|
1605
1652
|
}
|
|
1606
1653
|
if (currentSeek !== null && roundTo4Digits(currentSeek) === roundTo4Digits(newTime)) {
|
|
1607
1654
|
return;
|
|
1608
1655
|
}
|
|
1656
|
+
const previousTime = currentSeek;
|
|
1609
1657
|
currentSeek = newTime;
|
|
1610
1658
|
if (getIsLooping()) {
|
|
1611
1659
|
if (getLoopSegmentMediaEndTimestamp() - newTime < 1) {
|
|
@@ -1614,7 +1662,17 @@ var videoIteratorManager = async ({
|
|
|
1614
1662
|
});
|
|
1615
1663
|
}
|
|
1616
1664
|
}
|
|
1617
|
-
const
|
|
1665
|
+
const pendingFrameBehavior = previousTime !== null && isSequentialMediaTimeAdvance({
|
|
1666
|
+
previousTime,
|
|
1667
|
+
newTime,
|
|
1668
|
+
fps,
|
|
1669
|
+
playbackRate,
|
|
1670
|
+
isPlaying
|
|
1671
|
+
}) ? "wait" : "restart-iterator";
|
|
1672
|
+
const videoSatisfyResult = await videoFrameIterator.tryToSatisfySeek(newTime, {
|
|
1673
|
+
pendingFrameBehavior,
|
|
1674
|
+
shouldContinue: () => !nonce.isStale()
|
|
1675
|
+
});
|
|
1618
1676
|
if (videoSatisfyResult.type === "satisfied") {
|
|
1619
1677
|
await drawFrame(videoSatisfyResult.frame);
|
|
1620
1678
|
return;
|
|
@@ -1949,7 +2007,10 @@ class MediaPlayer {
|
|
|
1949
2007
|
await Promise.all([
|
|
1950
2008
|
this.videoIteratorManager?.seek({
|
|
1951
2009
|
newTime,
|
|
1952
|
-
nonce
|
|
2010
|
+
nonce,
|
|
2011
|
+
fps: this.fps,
|
|
2012
|
+
playbackRate: this.playbackRate,
|
|
2013
|
+
isPlaying: this.playing
|
|
1953
2014
|
}),
|
|
1954
2015
|
this.audioIteratorManager?.seek({
|
|
1955
2016
|
newTime,
|
|
@@ -12,7 +12,10 @@ export declare const createVideoIterator: (timeToSeek: number, cache: {
|
|
|
12
12
|
destroy: () => void;
|
|
13
13
|
initialFrame: WrappedCanvas | null;
|
|
14
14
|
isDestroyed: () => boolean;
|
|
15
|
-
tryToSatisfySeek: (time: number
|
|
15
|
+
tryToSatisfySeek: (time: number, options: {
|
|
16
|
+
pendingFrameBehavior: "restart-iterator" | "wait";
|
|
17
|
+
shouldContinue: () => boolean;
|
|
18
|
+
}) => Promise<{
|
|
16
19
|
type: "not-satisfied";
|
|
17
20
|
reason: string;
|
|
18
21
|
} | {
|
|
@@ -2,6 +2,13 @@ import type { InputVideoTrack, WrappedCanvas } from 'mediabunny';
|
|
|
2
2
|
import type { EffectChainState, EffectDefinitionAndStack } from 'remotion';
|
|
3
3
|
import type { DelayPlaybackIfNotPremounting } from './delay-playback-if-not-premounting';
|
|
4
4
|
import type { Nonce } from './nonce-manager';
|
|
5
|
+
export declare const isSequentialMediaTimeAdvance: ({ previousTime, newTime, fps, playbackRate, isPlaying, }: {
|
|
6
|
+
previousTime: number;
|
|
7
|
+
newTime: number;
|
|
8
|
+
fps: number;
|
|
9
|
+
playbackRate: number;
|
|
10
|
+
isPlaying: boolean;
|
|
11
|
+
}) => boolean;
|
|
5
12
|
export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremounting, canvas, context, drawDebugOverlay, logLevel, getOnVideoFrameCallback, videoTrack, getLoopSegmentMediaEndTimestamp, getStartTime, getIsLooping, getEffects, getEffectChainState, }: {
|
|
6
13
|
videoTrack: InputVideoTrack;
|
|
7
14
|
delayPlaybackHandleIfNotPremounting: () => DelayPlaybackIfNotPremounting;
|
|
@@ -18,16 +25,22 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
|
|
|
18
25
|
}) => Promise<{
|
|
19
26
|
startVideoIterator: (timeToSeek: number, nonce: Nonce) => Promise<void>;
|
|
20
27
|
getVideoIteratorsCreated: () => number;
|
|
21
|
-
seek: ({ newTime, nonce }: {
|
|
28
|
+
seek: ({ newTime, nonce, fps, playbackRate, isPlaying, }: {
|
|
22
29
|
newTime: number;
|
|
23
30
|
nonce: Nonce;
|
|
31
|
+
fps: number;
|
|
32
|
+
playbackRate: number;
|
|
33
|
+
isPlaying: boolean;
|
|
24
34
|
}) => Promise<void>;
|
|
25
35
|
destroy: () => void;
|
|
26
36
|
getVideoFrameIterator: () => {
|
|
27
37
|
destroy: () => void;
|
|
28
38
|
initialFrame: WrappedCanvas | null;
|
|
29
39
|
isDestroyed: () => boolean;
|
|
30
|
-
tryToSatisfySeek: (time: number
|
|
40
|
+
tryToSatisfySeek: (time: number, options: {
|
|
41
|
+
pendingFrameBehavior: "restart-iterator" | "wait";
|
|
42
|
+
shouldContinue: () => boolean;
|
|
43
|
+
}) => Promise<{
|
|
31
44
|
type: "not-satisfied";
|
|
32
45
|
reason: string;
|
|
33
46
|
} | {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.498",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"mediabunny": "1.50.8",
|
|
26
|
-
"remotion": "4.0.
|
|
26
|
+
"remotion": "4.0.498",
|
|
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.498",
|
|
35
|
+
"@remotion/player": "4.0.498",
|
|
36
36
|
"@vitest/browser-webdriverio": "4.0.9",
|
|
37
37
|
"eslint": "9.19.0",
|
|
38
38
|
"react": "19.2.3",
|