@remotion/timeline-utils 4.0.495 → 4.0.497

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.
@@ -0,0 +1,4 @@
1
+ export declare const clampTimestampsToDuration: ({ timestamps, durationInSeconds, }: {
2
+ readonly timestamps: readonly number[];
3
+ readonly durationInSeconds: number | null;
4
+ }) => number[];
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clampTimestampsToDuration = void 0;
4
+ const LAST_FRAME_EPSILON_IN_SECONDS = 1 / 1000000;
5
+ const clampTimestampsToDuration = ({ timestamps, durationInSeconds, }) => {
6
+ if (durationInSeconds === null) {
7
+ return [...timestamps];
8
+ }
9
+ const lastTimestamp = Math.max(0, durationInSeconds - LAST_FRAME_EPSILON_IN_SECONDS);
10
+ return timestamps.map((timestamp) => Math.min(timestamp, lastTimestamp));
11
+ };
12
+ exports.clampTimestampsToDuration = clampTimestampsToDuration;
@@ -365,6 +365,18 @@ var drawRepeatingImageThumbnail = ({
365
365
  ctx.fillStyle = pattern;
366
366
  ctx.fillRect(0, 0, width, height);
367
367
  };
368
+ // src/clamp-timestamps-to-duration.ts
369
+ var LAST_FRAME_EPSILON_IN_SECONDS = 1 / 1e6;
370
+ var clampTimestampsToDuration = ({
371
+ timestamps,
372
+ durationInSeconds
373
+ }) => {
374
+ if (durationInSeconds === null) {
375
+ return [...timestamps];
376
+ }
377
+ const lastTimestamp = Math.max(0, durationInSeconds - LAST_FRAME_EPSILON_IN_SECONDS);
378
+ return timestamps.map((timestamp) => Math.min(timestamp, lastTimestamp));
379
+ };
368
380
  // src/extract-frames.ts
369
381
  import {
370
382
  ALL_FORMATS as ALL_FORMATS2,
@@ -386,7 +398,8 @@ async function extractFrames({
386
398
  src,
387
399
  timestampsInSeconds,
388
400
  onVideoSample,
389
- signal
401
+ signal,
402
+ repeatLastFrame = false
390
403
  }) {
391
404
  const input = new Input2({
392
405
  formats: ALL_FORMATS2,
@@ -413,7 +426,7 @@ async function extractFrames({
413
426
  if (await videoTrack.isRelativeToUnixEpoch()) {
414
427
  throw new Error("Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: " + src);
415
428
  }
416
- const timestamps = typeof timestampsInSeconds === "function" ? await timestampsInSeconds({
429
+ const requestedTimestamps = typeof timestampsInSeconds === "function" ? await timestampsInSeconds({
417
430
  track: {
418
431
  width: await videoTrack.getDisplayWidth(),
419
432
  height: await videoTrack.getDisplayHeight()
@@ -421,6 +434,10 @@ async function extractFrames({
421
434
  container: format.name,
422
435
  durationInSeconds
423
436
  }) : timestampsInSeconds;
437
+ const timestamps = repeatLastFrame ? clampTimestampsToDuration({
438
+ timestamps: requestedTimestamps,
439
+ durationInSeconds
440
+ }) : requestedTimestamps;
424
441
  if (timestamps.length === 0) {
425
442
  return;
426
443
  }
@@ -885,6 +902,7 @@ export {
885
902
  drawRepeatingImageThumbnail,
886
903
  drawBars,
887
904
  createWaveformPeakProcessor,
905
+ clampTimestampsToDuration,
888
906
  calculateTimestampSlots,
889
907
  aspectRatioCache,
890
908
  addFrameToCache,
@@ -13,6 +13,7 @@ export type ExtractFramesProps = {
13
13
  timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
14
14
  onVideoSample: (sample: VideoSample) => void;
15
15
  signal?: AbortSignal;
16
+ repeatLastFrame?: boolean;
16
17
  };
17
- export declare function extractFrames({ src, timestampsInSeconds, onVideoSample, signal }: ExtractFramesProps): Promise<void>;
18
+ export declare function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, repeatLastFrame }: ExtractFramesProps): Promise<void>;
18
19
  export {};
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractFrames = extractFrames;
4
4
  const mediabunny_1 = require("mediabunny");
5
+ const clamp_timestamps_to_duration_1 = require("./clamp-timestamps-to-duration");
5
6
  const get_duration_or_compute_1 = require("./get-duration-or-compute");
6
- async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, }) {
7
+ async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, repeatLastFrame = false, }) {
7
8
  var _a;
8
9
  const input = new mediabunny_1.Input({
9
10
  formats: mediabunny_1.ALL_FORMATS,
@@ -32,7 +33,7 @@ async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal,
32
33
  throw new Error('Streams with UNIX timestamps are not currently supported by Remotion. Sorry! Source: ' +
33
34
  src);
34
35
  }
35
- const timestamps = typeof timestampsInSeconds === 'function'
36
+ const requestedTimestamps = typeof timestampsInSeconds === 'function'
36
37
  ? await timestampsInSeconds({
37
38
  track: {
38
39
  width: await videoTrack.getDisplayWidth(),
@@ -42,6 +43,12 @@ async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal,
42
43
  durationInSeconds,
43
44
  })
44
45
  : timestampsInSeconds;
46
+ const timestamps = repeatLastFrame
47
+ ? (0, clamp_timestamps_to_duration_1.clampTimestampsToDuration)({
48
+ timestamps: requestedTimestamps,
49
+ durationInSeconds,
50
+ })
51
+ : requestedTimestamps;
45
52
  if (timestamps.length === 0) {
46
53
  return;
47
54
  }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { sliceWaveformPeaks } from './audio-waveform/slice-waveform-peaks';
7
7
  export { createWaveformPeakProcessor, emitWaveformProgress, } from './audio-waveform/waveform-peak-processor';
8
8
  export { drawRepeatingImageThumbnail } from './image-thumbnail/draw-repeating-image-thumbnail';
9
9
  export { getScaledImageThumbnailDimensions } from './image-thumbnail/get-scaled-image-thumbnail-dimensions';
10
+ export { clampTimestampsToDuration } from './clamp-timestamps-to-duration';
10
11
  export { extractFrames } from './extract-frames';
11
12
  export type { ExtractFramesProps, ExtractFramesTimestampsInSecondsFn, } from './extract-frames';
12
13
  export { addFrameToCache, aspectRatioCache, frameDatabase, getAspectRatioFromCache, getFrameDatabaseKeyPrefix, getTimestampFromFrameDatabaseKey, makeFrameDatabaseKey, } from './frame-database';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resizeVideoFrame = exports.renderFrameStripToCanvas = exports.WEBCODECS_TIMESCALE = exports.getDurationOfOneFrame = exports.fillWithCachedFrames = exports.fillFrameWhereItFits = exports.ensureSlots = exports.drawSlot = exports.calculateTimestampSlots = exports.shouldTileLoopDisplay = exports.getLoopDisplayWidth = exports.makeFrameDatabaseKey = exports.getTimestampFromFrameDatabaseKey = exports.getFrameDatabaseKeyPrefix = exports.getAspectRatioFromCache = exports.frameDatabase = exports.aspectRatioCache = exports.addFrameToCache = exports.extractFrames = exports.getScaledImageThumbnailDimensions = exports.drawRepeatingImageThumbnail = exports.emitWaveformProgress = exports.createWaveformPeakProcessor = exports.sliceWaveformPeaks = exports.makeAudioWaveformWorker = exports.loadWaveformPeaks = exports.drawBars = exports.TARGET_SAMPLE_RATE = void 0;
3
+ exports.resizeVideoFrame = exports.renderFrameStripToCanvas = exports.WEBCODECS_TIMESCALE = exports.getDurationOfOneFrame = exports.fillWithCachedFrames = exports.fillFrameWhereItFits = exports.ensureSlots = exports.drawSlot = exports.calculateTimestampSlots = exports.shouldTileLoopDisplay = exports.getLoopDisplayWidth = exports.makeFrameDatabaseKey = exports.getTimestampFromFrameDatabaseKey = exports.getFrameDatabaseKeyPrefix = exports.getAspectRatioFromCache = exports.frameDatabase = exports.aspectRatioCache = exports.addFrameToCache = exports.extractFrames = exports.clampTimestampsToDuration = exports.getScaledImageThumbnailDimensions = exports.drawRepeatingImageThumbnail = exports.emitWaveformProgress = exports.createWaveformPeakProcessor = exports.sliceWaveformPeaks = exports.makeAudioWaveformWorker = exports.loadWaveformPeaks = exports.drawBars = exports.TARGET_SAMPLE_RATE = void 0;
4
4
  const constants_1 = require("./audio-waveform/constants");
5
5
  Object.defineProperty(exports, "TARGET_SAMPLE_RATE", { enumerable: true, get: function () { return constants_1.TARGET_SAMPLE_RATE; } });
6
6
  const draw_peaks_1 = require("./audio-waveform/draw-peaks");
@@ -18,6 +18,8 @@ const draw_repeating_image_thumbnail_1 = require("./image-thumbnail/draw-repeati
18
18
  Object.defineProperty(exports, "drawRepeatingImageThumbnail", { enumerable: true, get: function () { return draw_repeating_image_thumbnail_1.drawRepeatingImageThumbnail; } });
19
19
  const get_scaled_image_thumbnail_dimensions_1 = require("./image-thumbnail/get-scaled-image-thumbnail-dimensions");
20
20
  Object.defineProperty(exports, "getScaledImageThumbnailDimensions", { enumerable: true, get: function () { return get_scaled_image_thumbnail_dimensions_1.getScaledImageThumbnailDimensions; } });
21
+ const clamp_timestamps_to_duration_1 = require("./clamp-timestamps-to-duration");
22
+ Object.defineProperty(exports, "clampTimestampsToDuration", { enumerable: true, get: function () { return clamp_timestamps_to_duration_1.clampTimestampsToDuration; } });
21
23
  const extract_frames_1 = require("./extract-frames");
22
24
  Object.defineProperty(exports, "extractFrames", { enumerable: true, get: function () { return extract_frames_1.extractFrames; } });
23
25
  const frame_database_1 = require("./frame-database");
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/timeline-utils"
4
4
  },
5
5
  "name": "@remotion/timeline-utils",
6
- "version": "4.0.495",
6
+ "version": "4.0.497",
7
7
  "description": "Internal utilities for rendering Remotion timelines",
8
8
  "main": "dist/index.js",
9
9
  "scripts": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@mediabunny/server": "1.50.8",
28
- "@remotion/eslint-config-internal": "4.0.495",
28
+ "@remotion/eslint-config-internal": "4.0.497",
29
29
  "eslint": "9.19.0",
30
30
  "@typescript/native-preview": "7.0.0-dev.20260217.1"
31
31
  },