@remotion/media 4.0.473 → 4.0.475

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.
@@ -77,13 +77,13 @@ export declare const drawPreviewOverlay: ({ context, audioTime, audioContextStat
77
77
  destroy: () => void;
78
78
  initialFrame: import("mediabunny").WrappedCanvas | null;
79
79
  isDestroyed: () => boolean;
80
- tryToSatisfySeek: (time: number) => {
80
+ tryToSatisfySeek: (time: number) => Promise<{
81
81
  type: "not-satisfied";
82
82
  reason: string;
83
83
  } | {
84
84
  type: "satisfied";
85
85
  frame: import("mediabunny").WrappedCanvas;
86
- };
86
+ }>;
87
87
  } | null;
88
88
  drawFrame: (frame: import("mediabunny").WrappedCanvas) => Promise<void>;
89
89
  redrawCurrentFrame: () => Promise<void>;
@@ -1000,6 +1000,11 @@ var resolveRequestInit = ({
1000
1000
  import { CanvasSink } from "mediabunny";
1001
1001
  import { Internals as Internals4 } from "remotion";
1002
1002
 
1003
+ // src/helpers/round-to-4-digits.ts
1004
+ var roundTo4Digits = (timestamp) => {
1005
+ return Math.round(timestamp * 1000) / 1000;
1006
+ };
1007
+
1003
1008
  // src/canvas-ahead-of-time.ts
1004
1009
  var BUFFER_SIZE = 3;
1005
1010
  var canvasesAheadOfTime = (videoSink, startTimestamp) => {
@@ -1119,11 +1124,6 @@ var makePrewarmedVideoIteratorCache = (videoSink) => {
1119
1124
  };
1120
1125
  };
1121
1126
 
1122
- // src/helpers/round-to-4-digits.ts
1123
- var roundTo4Digits = (timestamp) => {
1124
- return Math.round(timestamp * 1000) / 1000;
1125
- };
1126
-
1127
1127
  // src/video/video-preview-iterator.ts
1128
1128
  var createVideoIterator = async (timeToSeek, cache) => {
1129
1129
  let destroyed = false;
@@ -1132,7 +1132,28 @@ var createVideoIterator = async (timeToSeek, cache) => {
1132
1132
  const firstAwait = iterator.next();
1133
1133
  const initialFrame = firstAwait && firstAwait.type === "ready" ? firstAwait.frame : await firstAwait.wait();
1134
1134
  let lastReturnedFrame = initialFrame;
1135
+ let peekedFrame = null;
1136
+ const peek = async () => {
1137
+ if (peekedFrame) {
1138
+ return peekedFrame;
1139
+ }
1140
+ const next = iterator.next();
1141
+ if (next.type === "ready") {
1142
+ peekedFrame = next.frame;
1143
+ } else {
1144
+ peekedFrame = await next.wait();
1145
+ }
1146
+ return peekedFrame;
1147
+ };
1135
1148
  const getNextOrNullIfNotAvailable = () => {
1149
+ if (peekedFrame) {
1150
+ const retValue = {
1151
+ type: "got-frame-or-end",
1152
+ frame: peekedFrame
1153
+ };
1154
+ peekedFrame = null;
1155
+ return retValue;
1156
+ }
1136
1157
  const next = iterator.next();
1137
1158
  if (next.type === "pending") {
1138
1159
  return {
@@ -1165,7 +1186,7 @@ var createVideoIterator = async (timeToSeek, cache) => {
1165
1186
  return;
1166
1187
  });
1167
1188
  };
1168
- const tryToSatisfySeek = (time) => {
1189
+ const tryToSatisfySeek = async (time) => {
1169
1190
  if (lastReturnedFrame) {
1170
1191
  const frameTimestamp = roundTo4Digits(lastReturnedFrame.timestamp);
1171
1192
  if (roundTo4Digits(time) < frameTimestamp) {
@@ -1182,7 +1203,14 @@ var createVideoIterator = async (timeToSeek, cache) => {
1182
1203
  reason: `iterator is too far, most recently returned ${frameTimestamp}`
1183
1204
  };
1184
1205
  }
1185
- const frameEndTimestamp = roundTo4Digits(lastReturnedFrame.timestamp + lastReturnedFrame.duration);
1206
+ let lastFrameDuration = lastReturnedFrame.duration;
1207
+ if (lastFrameDuration === 0) {
1208
+ const peeked = await peek();
1209
+ if (peeked) {
1210
+ lastFrameDuration = peeked.timestamp - lastReturnedFrame.timestamp;
1211
+ }
1212
+ }
1213
+ const frameEndTimestamp = roundTo4Digits(lastReturnedFrame.timestamp + lastFrameDuration);
1186
1214
  const timestamp = roundTo4Digits(time);
1187
1215
  if (frameTimestamp <= timestamp && frameEndTimestamp > timestamp) {
1188
1216
  return {
@@ -1270,6 +1298,7 @@ var videoIteratorManager = async ({
1270
1298
  let framesRendered = 0;
1271
1299
  let currentDelayHandle = null;
1272
1300
  let lastDrawnFrame = null;
1301
+ let currentSeek = null;
1273
1302
  const clearLastDrawnFrame = () => {
1274
1303
  lastDrawnFrame = null;
1275
1304
  };
@@ -1336,6 +1365,7 @@ var videoIteratorManager = async ({
1336
1365
  videoFrameIterator?.destroy();
1337
1366
  const delayHandle = __using(__stack, delayPlaybackHandleIfNotPremounting(), 0);
1338
1367
  currentDelayHandle = delayHandle;
1368
+ currentSeek = timeToSeek;
1339
1369
  const iterator = await createVideoIterator(timeToSeek, prewarmedVideoIteratorCache);
1340
1370
  videoIteratorsCreated++;
1341
1371
  videoFrameIterator = iterator;
@@ -1362,6 +1392,10 @@ var videoIteratorManager = async ({
1362
1392
  if (!videoFrameIterator) {
1363
1393
  return;
1364
1394
  }
1395
+ if (currentSeek !== null && roundTo4Digits(currentSeek) === roundTo4Digits(newTime)) {
1396
+ return;
1397
+ }
1398
+ currentSeek = newTime;
1365
1399
  if (getIsLooping()) {
1366
1400
  if (getLoopSegmentMediaEndTimestamp() - newTime < 1) {
1367
1401
  prewarmedVideoIteratorCache.prewarmIteratorForLooping({
@@ -1369,7 +1403,7 @@ var videoIteratorManager = async ({
1369
1403
  });
1370
1404
  }
1371
1405
  }
1372
- const videoSatisfyResult = videoFrameIterator.tryToSatisfySeek(newTime);
1406
+ const videoSatisfyResult = await videoFrameIterator.tryToSatisfySeek(newTime);
1373
1407
  if (videoSatisfyResult.type === "satisfied") {
1374
1408
  await drawFrame(videoSatisfyResult.frame);
1375
1409
  return;
@@ -2992,7 +3026,12 @@ var makeKeyframeBank = async ({
2992
3026
  }
2993
3027
  const roundedTimestamp = roundTo4Digits(timestamp);
2994
3028
  const firstFrameTimestamp = roundTo4Digits(frameTimestamps[0]);
3029
+ const range = getRangeOfTimestamps();
3030
+ if (!range) {
3031
+ return false;
3032
+ }
2995
3033
  const lastFrameTimestamp = roundTo4Digits(frameTimestamps[frameTimestamps.length - 1]);
3034
+ const lastFrameEndTimestamp = roundTo4Digits(range.lastTimestamp);
2996
3035
  if (hasReachedEndOfVideo && roundedTimestamp > lastFrameTimestamp) {
2997
3036
  return true;
2998
3037
  }
@@ -3001,7 +3040,7 @@ var makeKeyframeBank = async ({
3001
3040
  const firstFrameDoesSatisfy = firstFrameIsInitialFrame && roundedTimestamp >= initialTimestampRequest;
3002
3041
  return firstFrameDoesSatisfy;
3003
3042
  }
3004
- if (roundedTimestamp - BIGGEST_ALLOWED_JUMP_FORWARD_SECONDS > lastFrameTimestamp) {
3043
+ if (roundedTimestamp - BIGGEST_ALLOWED_JUMP_FORWARD_SECONDS > lastFrameEndTimestamp) {
3005
3044
  return false;
3006
3045
  }
3007
3046
  return true;
@@ -4576,7 +4615,7 @@ var audioSchema = {
4576
4615
  min: 0.1,
4577
4616
  step: 0.01,
4578
4617
  default: 1,
4579
- description: "Playback Rate",
4618
+ description: "Playback rate",
4580
4619
  hiddenFromList: false,
4581
4620
  keyframable: false
4582
4621
  },
@@ -5502,7 +5541,7 @@ var videoSchema = {
5502
5541
  min: 0.1,
5503
5542
  step: 0.01,
5504
5543
  default: 1,
5505
- description: "Playback Rate",
5544
+ description: "Playback rate",
5506
5545
  hiddenFromList: false,
5507
5546
  keyframable: false
5508
5547
  },
@@ -12,12 +12,12 @@ 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) => Promise<{
16
16
  type: "not-satisfied";
17
17
  reason: string;
18
18
  } | {
19
19
  type: "satisfied";
20
20
  frame: WrappedCanvas;
21
- };
21
+ }>;
22
22
  }>;
23
23
  export type VideoIterator = Awaited<ReturnType<typeof createVideoIterator>>;
@@ -27,13 +27,13 @@ export declare const videoIteratorManager: ({ delayPlaybackHandleIfNotPremountin
27
27
  destroy: () => void;
28
28
  initialFrame: WrappedCanvas | null;
29
29
  isDestroyed: () => boolean;
30
- tryToSatisfySeek: (time: number) => {
30
+ tryToSatisfySeek: (time: number) => Promise<{
31
31
  type: "not-satisfied";
32
32
  reason: string;
33
33
  } | {
34
34
  type: "satisfied";
35
35
  frame: WrappedCanvas;
36
- };
36
+ }>;
37
37
  } | null;
38
38
  drawFrame: (frame: WrappedCanvas) => Promise<void>;
39
39
  redrawCurrentFrame: () => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/media",
3
- "version": "4.0.473",
3
+ "version": "4.0.475",
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.45.0",
26
- "remotion": "4.0.473",
26
+ "remotion": "4.0.475",
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.473",
34
+ "@remotion/eslint-config-internal": "4.0.475",
35
35
  "@vitest/browser-webdriverio": "4.0.9",
36
36
  "eslint": "9.19.0",
37
37
  "react": "19.2.3",