@remotion/media-parser 4.0.311 → 4.0.313

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.
Files changed (57) hide show
  1. package/dist/containers/aac/get-seeking-byte.js +5 -1
  2. package/dist/containers/flac/get-seeking-byte.d.ts +2 -1
  3. package/dist/containers/flac/get-seeking-byte.js +1 -1
  4. package/dist/containers/iso-base-media/base-media-box.d.ts +3 -2
  5. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.d.ts +3 -1
  6. package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.js +2 -1
  7. package/dist/containers/iso-base-media/find-keyframe-before-time.d.ts +1 -1
  8. package/dist/containers/iso-base-media/find-keyframe-before-time.js +1 -1
  9. package/dist/containers/iso-base-media/find-track-to-seek.js +2 -0
  10. package/dist/containers/iso-base-media/get-keyframes.js +1 -0
  11. package/dist/containers/iso-base-media/get-sample-positions-from-track.d.ts +3 -1
  12. package/dist/containers/iso-base-media/get-sample-positions-from-track.js +2 -1
  13. package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +4 -1
  14. package/dist/containers/iso-base-media/get-seeking-byte.js +3 -1
  15. package/dist/containers/iso-base-media/moov/mvhd.d.ts +30 -0
  16. package/dist/containers/iso-base-media/moov/mvhd.js +65 -0
  17. package/dist/containers/iso-base-media/moov/trex.d.ts +16 -0
  18. package/dist/containers/iso-base-media/moov/trex.js +27 -0
  19. package/dist/containers/iso-base-media/process-box.js +10 -1
  20. package/dist/containers/iso-base-media/tkhd.d.ts +1 -1
  21. package/dist/containers/iso-base-media/traversal.d.ts +4 -1
  22. package/dist/containers/iso-base-media/traversal.js +18 -1
  23. package/dist/containers/m3u/get-seeking-byte.js +2 -0
  24. package/dist/containers/mp3/get-seeking-byte.js +4 -1
  25. package/dist/containers/riff/get-seeking-byte.js +3 -0
  26. package/dist/containers/wav/get-seeking-byte.js +1 -0
  27. package/dist/containers/wav/parse-list.js +4 -3
  28. package/dist/containers/webm/seek/get-seeking-byte.js +21 -6
  29. package/dist/controller/media-parser-controller.d.ts +3 -0
  30. package/dist/controller/media-parser-controller.js +15 -0
  31. package/dist/esm/index.mjs +327 -156
  32. package/dist/esm/server-worker.mjs +17 -0
  33. package/dist/esm/worker-server-entry.mjs +341 -155
  34. package/dist/esm/worker-web-entry.mjs +341 -155
  35. package/dist/esm/worker.mjs +28 -0
  36. package/dist/get-duration.js +1 -0
  37. package/dist/get-seeking-byte.js +13 -2
  38. package/dist/index.cjs +54 -0
  39. package/dist/index.d.ts +3 -2
  40. package/dist/index.js +1 -1
  41. package/dist/internal-parse-media.js +25 -0
  42. package/dist/iterator/buffer-iterator.d.ts +1 -1
  43. package/dist/iterator/buffer-manager.d.ts +1 -1
  44. package/dist/iterator/buffer-manager.js +19 -5
  45. package/dist/parse-media-on-worker-entry.js +17 -0
  46. package/dist/samples-from-moof.d.ts +3 -1
  47. package/dist/samples-from-moof.js +15 -12
  48. package/dist/state/iso-base-media/cached-sample-positions.js +1 -0
  49. package/dist/state/iso-base-media/lazy-mfra-load.js +1 -1
  50. package/dist/version.d.ts +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/webcodec-sample-types.d.ts +2 -2
  53. package/dist/work-on-seek-request.d.ts +22 -0
  54. package/dist/work-on-seek-request.js +3 -2
  55. package/dist/worker/forward-controller-to-worker.js +18 -0
  56. package/dist/worker/worker-types.d.ts +13 -2
  57. package/package.json +3 -3
@@ -243,6 +243,14 @@ var parseMediaOnWorkerImplementation = async ({ controller, reader, ...params },
243
243
  seekingHintPromises.push(prom);
244
244
  return prom.promise;
245
245
  });
246
+ const simulateSeekPromises = {};
247
+ controller?._internals.attachSimulateSeekResolution((seek) => {
248
+ const prom = withResolvers();
249
+ const nonce = String(Math.random());
250
+ post(worker, { type: "request-simulate-seek", payload: seek, nonce });
251
+ simulateSeekPromises[nonce] = prom;
252
+ return prom.promise;
253
+ });
246
254
  const callbacks = {};
247
255
  function onMessage(message) {
248
256
  const data = message.data;
@@ -462,6 +470,15 @@ var parseMediaOnWorkerImplementation = async ({ controller, reader, ...params },
462
470
  firstPromise.resolve(data.payload);
463
471
  return;
464
472
  }
473
+ if (data.type === "response-simulate-seek") {
474
+ const prom = simulateSeekPromises[data.nonce];
475
+ if (!prom) {
476
+ throw new Error("No simulate seek promise found");
477
+ }
478
+ prom.resolve(data.payload);
479
+ delete simulateSeekPromises[data.nonce];
480
+ return;
481
+ }
465
482
  throw new Error(`Unknown response type: ${JSON.stringify(data)}`);
466
483
  }
467
484
  worker.addEventListener("message", onMessage);
@@ -489,6 +506,17 @@ var parseMediaOnWebWorker = (params) => {
489
506
  if (typeof Worker === "undefined") {
490
507
  throw new Error('"Worker" is not available. Cannot call parseMediaOnWebWorker()');
491
508
  }
509
+ if (import.meta.url.includes(".vite/deps")) {
510
+ const err = [
511
+ "Detected Vite pre-bundling, which will break the worker.",
512
+ "Please add the following to your vite.config.js:",
513
+ " optimizeDeps: {",
514
+ ' exclude: ["@remotion/media-parser/worker"]',
515
+ " }"
516
+ ].join(`
517
+ `);
518
+ throw new Error(err);
519
+ }
492
520
  const worker = new Worker(new URL("./worker-web-entry.mjs", import.meta.url));
493
521
  return parseMediaOnWorkerImplementation(params, worker, "parseMediaOnWebWorker");
494
522
  };
@@ -82,6 +82,7 @@ const getDurationFromIsoBaseMedia = (parserState) => {
82
82
  trakBox,
83
83
  moofBoxes,
84
84
  moofComplete: (0, are_samples_complete_1.areSamplesComplete)({ moofBoxes, tfraBoxes }),
85
+ trexBoxes: (0, traversal_1.getTrexBoxes)(moovBox),
85
86
  });
86
87
  if (!isComplete) {
87
88
  return null;
@@ -7,6 +7,7 @@ const get_seeking_byte_3 = require("./containers/iso-base-media/get-seeking-byte
7
7
  const get_seeking_byte_4 = require("./containers/m3u/get-seeking-byte");
8
8
  const get_seeking_byte_5 = require("./containers/mp3/get-seeking-byte");
9
9
  const get_seeking_byte_6 = require("./containers/riff/get-seeking-byte");
10
+ const handle_avc_packet_1 = require("./containers/transport-stream/handle-avc-packet");
10
11
  const get_seeking_byte_7 = require("./containers/wav/get-seeking-byte");
11
12
  const get_seeking_byte_8 = require("./containers/webm/seek/get-seeking-byte");
12
13
  const observed_pes_header_1 = require("./state/transport-stream/observed-pes-header");
@@ -46,7 +47,8 @@ const getSeekingByte = ({ info, time, logLevel, currentPosition, isoState, trans
46
47
  if (byte) {
47
48
  return Promise.resolve({
48
49
  type: 'do-seek',
49
- byte,
50
+ byte: byte.offset,
51
+ timeInSeconds: byte.timeInSeconds,
50
52
  });
51
53
  }
52
54
  return Promise.resolve({
@@ -59,11 +61,20 @@ const getSeekingByte = ({ info, time, logLevel, currentPosition, isoState, trans
59
61
  timeInSeconds: time,
60
62
  ptsStartOffset: info.ptsStartOffset,
61
63
  });
62
- const byte = (_a = lastKeyframeBeforeTimeInSeconds === null || lastKeyframeBeforeTimeInSeconds === void 0 ? void 0 : lastKeyframeBeforeTimeInSeconds.offset) !== null && _a !== void 0 ? _a : 0;
64
+ if (!lastKeyframeBeforeTimeInSeconds) {
65
+ transportStream.resetBeforeSeek();
66
+ return Promise.resolve({
67
+ type: 'do-seek',
68
+ byte: 0,
69
+ timeInSeconds: 0,
70
+ });
71
+ }
72
+ const byte = lastKeyframeBeforeTimeInSeconds.offset;
63
73
  transportStream.resetBeforeSeek();
64
74
  return Promise.resolve({
65
75
  type: 'do-seek',
66
76
  byte,
77
+ timeInSeconds: Math.min(lastKeyframeBeforeTimeInSeconds.pts, (_a = lastKeyframeBeforeTimeInSeconds.dts) !== null && _a !== void 0 ? _a : Infinity) / handle_avc_packet_1.MPEG_TIMESCALE,
67
78
  });
68
79
  }
69
80
  if (info.type === 'riff-seeking-hints') {
package/dist/index.cjs ADDED
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WEBCODECS_TIMESCALE = exports.VERSION = exports.mediaParserController = exports.defaultSelectM3uStreamFn = exports.defaultSelectM3uAssociatedPlaylists = exports.MediaParserInternals = exports.downloadAndParseMedia = exports.MediaParserAbortError = exports.IsAPdfError = exports.IsAnUnsupportedFileTypeError = exports.IsAnImageError = exports.hasBeenAborted = exports.parseMedia = void 0;
4
+ const aac_codecprivate_1 = require("./aac-codecprivate");
5
+ const ftyp_1 = require("./containers/iso-base-media/ftyp");
6
+ const mvhd_1 = require("./containers/iso-base-media/mvhd");
7
+ const samples_1 = require("./containers/iso-base-media/stsd/samples");
8
+ const stsd_1 = require("./containers/iso-base-media/stsd/stsd");
9
+ const tkhd_1 = require("./containers/iso-base-media/tkhd");
10
+ const parse_ebml_1 = require("./containers/webm/parse-ebml");
11
+ const all_segments_1 = require("./containers/webm/segments/all-segments");
12
+ const internal_parse_media_1 = require("./internal-parse-media");
13
+ const buffer_iterator_1 = require("./iterator/buffer-iterator");
14
+ const log_1 = require("./log");
15
+ const need_samples_for_fields_1 = require("./state/need-samples-for-fields");
16
+ const parser_state_1 = require("./state/parser-state");
17
+ var parse_media_1 = require("./parse-media");
18
+ Object.defineProperty(exports, "parseMedia", { enumerable: true, get: function () { return parse_media_1.parseMedia; } });
19
+ var errors_1 = require("./errors");
20
+ Object.defineProperty(exports, "hasBeenAborted", { enumerable: true, get: function () { return errors_1.hasBeenAborted; } });
21
+ Object.defineProperty(exports, "IsAnImageError", { enumerable: true, get: function () { return errors_1.IsAnImageError; } });
22
+ Object.defineProperty(exports, "IsAnUnsupportedFileTypeError", { enumerable: true, get: function () { return errors_1.IsAnUnsupportedFileTypeError; } });
23
+ Object.defineProperty(exports, "IsAPdfError", { enumerable: true, get: function () { return errors_1.IsAPdfError; } });
24
+ Object.defineProperty(exports, "MediaParserAbortError", { enumerable: true, get: function () { return errors_1.MediaParserAbortError; } });
25
+ var download_and_parse_media_1 = require("./download-and-parse-media");
26
+ Object.defineProperty(exports, "downloadAndParseMedia", { enumerable: true, get: function () { return download_and_parse_media_1.downloadAndParseMedia; } });
27
+ /**
28
+ * @deprecated Dont use these yet.
29
+ */
30
+ exports.MediaParserInternals = {
31
+ Log: log_1.Log,
32
+ createAacCodecPrivate: aac_codecprivate_1.createAacCodecPrivate,
33
+ matroskaElements: all_segments_1.matroskaElements,
34
+ ebmlMap: all_segments_1.ebmlMap,
35
+ parseTkhd: tkhd_1.parseTkhd,
36
+ getArrayBufferIterator: buffer_iterator_1.getArrayBufferIterator,
37
+ parseStsd: stsd_1.parseStsd,
38
+ makeParserState: parser_state_1.makeParserState,
39
+ processSample: samples_1.processIsoFormatBox,
40
+ parseFtyp: ftyp_1.parseFtyp,
41
+ parseEbml: parse_ebml_1.parseEbml,
42
+ parseMvhd: mvhd_1.parseMvhd,
43
+ internalParseMedia: internal_parse_media_1.internalParseMedia,
44
+ fieldsNeedSamplesMap: need_samples_for_fields_1.fieldsNeedSamplesMap,
45
+ };
46
+ var select_stream_1 = require("./containers/m3u/select-stream");
47
+ Object.defineProperty(exports, "defaultSelectM3uAssociatedPlaylists", { enumerable: true, get: function () { return select_stream_1.defaultSelectM3uAssociatedPlaylists; } });
48
+ Object.defineProperty(exports, "defaultSelectM3uStreamFn", { enumerable: true, get: function () { return select_stream_1.defaultSelectM3uStreamFn; } });
49
+ var media_parser_controller_1 = require("./controller/media-parser-controller");
50
+ Object.defineProperty(exports, "mediaParserController", { enumerable: true, get: function () { return media_parser_controller_1.mediaParserController; } });
51
+ var version_1 = require("./version");
52
+ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.VERSION; } });
53
+ var webcodecs_timescale_1 = require("./webcodecs-timescale");
54
+ Object.defineProperty(exports, "WEBCODECS_TIMESCALE", { enumerable: true, get: function () { return webcodecs_timescale_1.WEBCODECS_TIMESCALE; } });
package/dist/index.d.ts CHANGED
@@ -669,7 +669,7 @@ export declare const MediaParserInternals: {
669
669
  offset: number;
670
670
  size: number;
671
671
  }) => import("./containers/iso-base-media/tkhd").TkhdBox;
672
- getArrayBufferIterator: (initialData: Uint8Array, maxBytes: number | null) => {
672
+ getArrayBufferIterator: (initialData: Uint8Array, maxBytes: number) => {
673
673
  startReadingBits: () => void;
674
674
  stopReadingBits: () => void;
675
675
  skipTo: (offset: number) => void;
@@ -1265,7 +1265,7 @@ export declare const MediaParserInternals: {
1265
1265
  iterator: import("./iterator/buffer-iterator").BufferIterator;
1266
1266
  offset: number;
1267
1267
  size: number;
1268
- }) => import("./containers/iso-base-media/mvhd").MvhdBox;
1268
+ }) => import("./containers/iso-base-media/moov/mvhd").MvhdBox;
1269
1269
  internalParseMedia: import("./options").InternalParseMedia;
1270
1270
  fieldsNeedSamplesMap: Record<keyof import("./fields").AllOptions<import("./fields").ParseMediaFields>, boolean>;
1271
1271
  };
@@ -1275,6 +1275,7 @@ export { defaultSelectM3uAssociatedPlaylists, defaultSelectM3uStreamFn, SelectM3
1275
1275
  export { mediaParserController, MediaParserController, } from './controller/media-parser-controller';
1276
1276
  export { VERSION } from './version';
1277
1277
  export { WEBCODECS_TIMESCALE } from './webcodecs-timescale';
1278
+ export type { SeekResolution } from './work-on-seek-request';
1278
1279
  export type { MediaParserSampleAspectRatio } from './get-tracks';
1279
1280
  /**
1280
1281
  * @deprecated Dont use these yet.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WEBCODECS_TIMESCALE = exports.VERSION = exports.mediaParserController = exports.defaultSelectM3uStreamFn = exports.defaultSelectM3uAssociatedPlaylists = exports.MediaParserInternals = exports.downloadAndParseMedia = exports.MediaParserAbortError = exports.IsAPdfError = exports.IsAnUnsupportedFileTypeError = exports.IsAnImageError = exports.hasBeenAborted = exports.parseMedia = void 0;
4
4
  const aac_codecprivate_1 = require("./aac-codecprivate");
5
5
  const ftyp_1 = require("./containers/iso-base-media/ftyp");
6
- const mvhd_1 = require("./containers/iso-base-media/mvhd");
6
+ const mvhd_1 = require("./containers/iso-base-media/moov/mvhd");
7
7
  const samples_1 = require("./containers/iso-base-media/stsd/samples");
8
8
  const stsd_1 = require("./containers/iso-base-media/stsd/stsd");
9
9
  const tkhd_1 = require("./containers/iso-base-media/tkhd");
@@ -11,6 +11,7 @@ const remotion_license_acknowledge_1 = require("./remotion-license-acknowledge")
11
11
  const set_seeking_hints_1 = require("./set-seeking-hints");
12
12
  const parser_state_1 = require("./state/parser-state");
13
13
  const throttled_progress_1 = require("./throttled-progress");
14
+ const work_on_seek_request_1 = require("./work-on-seek-request");
14
15
  const internalParseMedia = async function ({ src, fields: _fieldsInReturnValue, reader: readerInterface, onAudioTrack, onVideoTrack, controller = (0, media_parser_controller_1.mediaParserController)(), logLevel, onParseProgress: onParseProgressDoNotCallDirectly, progressIntervalInMs, mode, onDiscardedData, onError, acknowledgeRemotionLicense, apiName, selectM3uStream: selectM3uStreamFn, selectM3uAssociatedPlaylists: selectM3uAssociatedPlaylistsFn, m3uPlaylistContext, makeSamplesStartAtZero, seekingHints, ...more }) {
15
16
  var _a;
16
17
  if (!src) {
@@ -82,6 +83,30 @@ const internalParseMedia = async function ({ src, fields: _fieldsInReturnValue,
82
83
  contentLength: state.contentLength,
83
84
  aacState: state.aac,
84
85
  })));
86
+ controller._internals.attachSimulateSeekResolution((seek) => {
87
+ const { aacState, avcState, flacState, isoState, iterator, keyframes, m3uState, mediaSection, mp3State, riffState, samplesObserved, structureState, tracksState, transportStream, webmState, } = (0, work_on_seek_request_1.getWorkOnSeekRequestOptions)(state);
88
+ return (0, work_on_seek_request_1.turnSeekIntoByte)({
89
+ aacState,
90
+ seek,
91
+ avcState,
92
+ contentLength,
93
+ flacState,
94
+ isoState,
95
+ iterator,
96
+ keyframes,
97
+ logLevel,
98
+ m3uPlaylistContext,
99
+ m3uState,
100
+ mediaSectionState: mediaSection,
101
+ mp3State,
102
+ riffState,
103
+ samplesObserved,
104
+ structureState,
105
+ tracksState,
106
+ transportStream,
107
+ webmState,
108
+ });
109
+ });
85
110
  if (!hasAudioTrackHandlers &&
86
111
  !hasVideoTrackHandlers &&
87
112
  Object.values(state.fields).every((v) => !v) &&
@@ -1,4 +1,4 @@
1
- export declare const getArrayBufferIterator: (initialData: Uint8Array, maxBytes: number | null) => {
1
+ export declare const getArrayBufferIterator: (initialData: Uint8Array, maxBytes: number) => {
2
2
  startReadingBits: () => void;
3
3
  stopReadingBits: () => void;
4
4
  skipTo: (offset: number) => void;
@@ -2,7 +2,7 @@ import type { ParseMediaMode } from '../options';
2
2
  import type { OffsetCounter } from './offset-counter';
3
3
  export declare const bufferManager: ({ initialData, maxBytes, counter, }: {
4
4
  initialData: Uint8Array;
5
- maxBytes: number | null;
5
+ maxBytes: number;
6
6
  counter: OffsetCounter;
7
7
  }) => {
8
8
  view: DataView<ArrayBuffer>;
@@ -1,12 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.bufferManager = void 0;
4
+ const makeBufferWithMaxBytes = (initialData, maxBytes) => {
5
+ const maxByteLength = Math.min(maxBytes, 2 ** 31);
6
+ try {
7
+ const buf = new ArrayBuffer(initialData.byteLength, {
8
+ maxByteLength,
9
+ });
10
+ return buf;
11
+ }
12
+ catch (e) {
13
+ // Cloudflare Workers have a limit of 128MB max array buffer size
14
+ if (e instanceof RangeError && maxBytes > 2 ** 27) {
15
+ return new ArrayBuffer(initialData.byteLength, {
16
+ maxByteLength: 2 ** 27,
17
+ });
18
+ }
19
+ throw e;
20
+ }
21
+ };
4
22
  const bufferManager = ({ initialData, maxBytes, counter, }) => {
5
- const buf = new ArrayBuffer(initialData.byteLength, {
6
- maxByteLength: maxBytes === null
7
- ? initialData.byteLength
8
- : Math.min(maxBytes, 2 ** 31),
9
- });
23
+ const buf = makeBufferWithMaxBytes(initialData, maxBytes);
10
24
  if (!buf.resize) {
11
25
  throw new Error('`ArrayBuffer.resize` is not supported in this Runtime. On the server: Use at least Node.js 20 or Bun. In the browser: Chrome 111, Edge 111, Safari 16.4, Firefox 128, Opera 111');
12
26
  }
@@ -84,6 +84,14 @@ const parseMediaOnWorkerImplementation = async ({ controller, reader, ...params
84
84
  seekingHintPromises.push(prom);
85
85
  return prom.promise;
86
86
  });
87
+ const simulateSeekPromises = {};
88
+ controller === null || controller === void 0 ? void 0 : controller._internals.attachSimulateSeekResolution((seek) => {
89
+ const prom = (0, with_resolvers_1.withResolvers)();
90
+ const nonce = String(Math.random());
91
+ post(worker, { type: 'request-simulate-seek', payload: seek, nonce });
92
+ simulateSeekPromises[nonce] = prom;
93
+ return prom.promise;
94
+ });
87
95
  const callbacks = {};
88
96
  function onMessage(message) {
89
97
  const data = message.data;
@@ -313,6 +321,15 @@ const parseMediaOnWorkerImplementation = async ({ controller, reader, ...params
313
321
  firstPromise.resolve(data.payload);
314
322
  return;
315
323
  }
324
+ if (data.type === 'response-simulate-seek') {
325
+ const prom = simulateSeekPromises[data.nonce];
326
+ if (!prom) {
327
+ throw new Error('No simulate seek promise found');
328
+ }
329
+ prom.resolve(data.payload);
330
+ delete simulateSeekPromises[data.nonce];
331
+ return;
332
+ }
316
333
  throw new Error(`Unknown response type: ${JSON.stringify(data)}`);
317
334
  }
318
335
  worker.addEventListener('message', onMessage);
@@ -1,6 +1,8 @@
1
+ import type { TrexBox } from './containers/iso-base-media/moov/trex';
1
2
  import type { SamplePosition } from './get-sample-positions';
2
3
  import type { MoofBox } from './state/iso-base-media/precomputed-moof';
3
- export declare const getSamplesFromMoof: ({ moofBox, trackId, }: {
4
+ export declare const getSamplesFromMoof: ({ moofBox, trackId, trexBoxes, }: {
4
5
  moofBox: MoofBox;
5
6
  trackId: number;
7
+ trexBoxes: TrexBox[];
6
8
  }) => SamplePosition[];
@@ -2,15 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSamplesFromMoof = void 0;
4
4
  const traversal_1 = require("./containers/iso-base-media/traversal");
5
- const getSamplesFromTraf = (trafSegment, moofOffset) => {
6
- var _a, _b, _c, _d, _e, _f, _g;
5
+ const getSamplesFromTraf = (trafSegment, moofOffset, trexBoxes) => {
6
+ var _a, _b, _c, _d, _e, _f;
7
7
  if (trafSegment.type !== 'regular-box' || trafSegment.boxType !== 'traf') {
8
8
  throw new Error('Expected traf-box');
9
9
  }
10
10
  const tfhdBox = (0, traversal_1.getTfhdBox)(trafSegment);
11
- const defaultSampleDuration = (_a = tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleDuration) !== null && _a !== void 0 ? _a : null;
12
- const defaultSampleSize = (_b = tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleSize) !== null && _b !== void 0 ? _b : null;
13
- const defaultSampleFlags = (_c = tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleFlags) !== null && _c !== void 0 ? _c : null;
11
+ const trexBox = (_a = trexBoxes.find((t) => t.trackId === (tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.trackId))) !== null && _a !== void 0 ? _a : null;
12
+ // intentional || instead of ?? to allow for 0, doesn't make sense for duration or size
13
+ const defaultTrackSampleDuration = (tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleDuration) || (trexBox === null || trexBox === void 0 ? void 0 : trexBox.defaultSampleDuration) || null;
14
+ const defaultTrackSampleSize = (tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleSize) || (trexBox === null || trexBox === void 0 ? void 0 : trexBox.defaultSampleSize) || null;
15
+ // but flags may just be 0 :)
16
+ const defaultTrackSampleFlags = (_c = (_b = tfhdBox === null || tfhdBox === void 0 ? void 0 : tfhdBox.defaultSampleFlags) !== null && _b !== void 0 ? _b : trexBox === null || trexBox === void 0 ? void 0 : trexBox.defaultSampleFlags) !== null && _c !== void 0 ? _c : null;
14
17
  const tfdtBox = (0, traversal_1.getTfdtBox)(trafSegment);
15
18
  const trunBoxes = (0, traversal_1.getTrunBoxes)(trafSegment);
16
19
  let time = 0;
@@ -25,11 +28,11 @@ const getSamplesFromTraf = (trafSegment, moofOffset) => {
25
28
  }
26
29
  for (const sample of trunBox.samples) {
27
30
  i++;
28
- const duration = (_d = sample.sampleDuration) !== null && _d !== void 0 ? _d : defaultSampleDuration;
31
+ const duration = sample.sampleDuration || defaultTrackSampleDuration;
29
32
  if (duration === null) {
30
33
  throw new Error('Expected duration');
31
34
  }
32
- const size = (_e = sample.sampleSize) !== null && _e !== void 0 ? _e : defaultSampleSize;
35
+ const size = (_d = sample.sampleSize) !== null && _d !== void 0 ? _d : defaultTrackSampleSize;
33
36
  if (size === null) {
34
37
  throw new Error('Expected size');
35
38
  }
@@ -38,16 +41,16 @@ const getSamplesFromTraf = (trafSegment, moofOffset) => {
38
41
  ? sample.sampleFlags
39
42
  : isFirstSample && trunBox.firstSampleFlags !== null
40
43
  ? trunBox.firstSampleFlags
41
- : defaultSampleFlags;
44
+ : defaultTrackSampleFlags;
42
45
  if (sampleFlags === null) {
43
46
  throw new Error('Expected sample flags');
44
47
  }
45
48
  const keyframe = !((sampleFlags >> 16) & 0x1);
46
- const dts = time + ((_f = tfdtBox === null || tfdtBox === void 0 ? void 0 : tfdtBox.baseMediaDecodeTime) !== null && _f !== void 0 ? _f : 0);
49
+ const dts = time + ((_e = tfdtBox === null || tfdtBox === void 0 ? void 0 : tfdtBox.baseMediaDecodeTime) !== null && _e !== void 0 ? _e : 0);
47
50
  const samplePosition = {
48
51
  offset: offset + (moofOffset !== null && moofOffset !== void 0 ? moofOffset : 0) + (dataOffset !== null && dataOffset !== void 0 ? dataOffset : 0),
49
52
  decodingTimestamp: dts,
50
- timestamp: dts + ((_g = sample.sampleCompositionTimeOffset) !== null && _g !== void 0 ? _g : 0),
53
+ timestamp: dts + ((_f = sample.sampleCompositionTimeOffset) !== null && _f !== void 0 ? _f : 0),
51
54
  duration,
52
55
  isKeyframe: keyframe,
53
56
  size,
@@ -62,13 +65,13 @@ const getSamplesFromTraf = (trafSegment, moofOffset) => {
62
65
  }
63
66
  return samples;
64
67
  };
65
- const getSamplesFromMoof = ({ moofBox, trackId, }) => {
68
+ const getSamplesFromMoof = ({ moofBox, trackId, trexBoxes, }) => {
66
69
  const mapped = moofBox.trafBoxes.map((traf) => {
67
70
  const tfhdBox = (0, traversal_1.getTfhdBox)(traf);
68
71
  if (!tfhdBox || tfhdBox.trackId !== trackId) {
69
72
  return [];
70
73
  }
71
- return getSamplesFromTraf(traf, moofBox.offset);
74
+ return getSamplesFromTraf(traf, moofBox.offset, trexBoxes);
72
75
  });
73
76
  return mapped.flat(1);
74
77
  };
@@ -37,6 +37,7 @@ const calculateFlatSamples = ({ state, mediaSectionStart, }) => {
37
37
  trakBox,
38
38
  moofBoxes: relevantMoofBox ? [relevantMoofBox] : [],
39
39
  moofComplete,
40
+ trexBoxes: (0, traversal_1.getTrexBoxes)(moov),
40
41
  });
41
42
  return samplePositions.map((samplePosition) => {
42
43
  return {
@@ -19,7 +19,7 @@ const lazyMfraLoad = ({ contentLength, controller, readerInterface, src, logLeve
19
19
  logLevel,
20
20
  prefetchCache,
21
21
  }).then((boxes) => {
22
- log_1.Log.verbose(logLevel, 'Lazily found mfra atom.');
22
+ log_1.Log.verbose(logLevel, boxes ? 'Lazily found mfra atom.' : 'No mfra atom found.');
23
23
  result = boxes;
24
24
  return boxes;
25
25
  });
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "4.0.311";
1
+ export declare const VERSION = "4.0.313";
package/dist/version.js CHANGED
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  // Automatically generated on publish
5
- exports.VERSION = '4.0.311';
5
+ exports.VERSION = '4.0.313';
@@ -1,7 +1,7 @@
1
1
  import type { MediaParserAudioTrack, MediaParserVideoTrack } from './get-tracks';
2
2
  import type { MediaParserContainer } from './options';
3
- export type MediaParserOnAudioSample = (sample: MediaParserAudioSample) => void | Promise<void> | OnTrackDoneCallback | Promise<OnTrackDoneCallback>;
4
- export type MediaParserOnVideoSample = (sample: MediaParserVideoSample) => void | Promise<void> | OnTrackDoneCallback | Promise<OnTrackDoneCallback>;
3
+ export type MediaParserOnAudioSample = (sample: MediaParserAudioSample) => void | Promise<OnTrackDoneCallback | void> | Promise<void> | OnTrackDoneCallback;
4
+ export type MediaParserOnVideoSample = (sample: MediaParserVideoSample) => void | Promise<OnTrackDoneCallback | void> | Promise<void> | OnTrackDoneCallback;
5
5
  export type OnTrackDoneCallback = () => void | Promise<void>;
6
6
  export type MediaParserOnAudioTrackParams = {
7
7
  track: MediaParserAudioTrack;
@@ -22,6 +22,27 @@ import type { SeekInfiniteLoop } from './state/seek-infinite-loop';
22
22
  import type { StructureState } from './state/structure';
23
23
  import type { TransportStreamState } from './state/transport-stream/transport-stream';
24
24
  import { type MediaSectionState } from './state/video-section';
25
+ export declare const turnSeekIntoByte: ({ seek, mediaSectionState, logLevel, iterator, structureState, m3uPlaylistContext, isoState, transportStream, tracksState, webmState, keyframes, flacState, samplesObserved, riffState, mp3State, contentLength, aacState, m3uState, avcState, }: {
26
+ seek: number;
27
+ mediaSectionState: MediaSectionState;
28
+ logLevel: MediaParserLogLevel;
29
+ iterator: BufferIterator;
30
+ structureState: StructureState;
31
+ m3uPlaylistContext: M3uPlaylistContext | null;
32
+ isoState: IsoBaseMediaState;
33
+ transportStream: TransportStreamState;
34
+ tracksState: TracksState;
35
+ webmState: WebmState;
36
+ keyframes: KeyframesState;
37
+ flacState: FlacState;
38
+ samplesObserved: SamplesObservedState;
39
+ riffState: RiffState;
40
+ mp3State: Mp3State;
41
+ aacState: AacState;
42
+ contentLength: number;
43
+ m3uState: M3uState;
44
+ avcState: AvcState;
45
+ }) => Promise<SeekResolution>;
25
46
  export type WorkOnSeekRequestOptions = {
26
47
  logLevel: MediaParserLogLevel;
27
48
  controller: MediaParserController;
@@ -63,4 +84,5 @@ export type SeekResolution = {
63
84
  } | {
64
85
  type: 'do-seek';
65
86
  byte: number;
87
+ timeInSeconds: number;
66
88
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.workOnSeekRequest = exports.getWorkOnSeekRequestOptions = void 0;
3
+ exports.workOnSeekRequest = exports.getWorkOnSeekRequestOptions = exports.turnSeekIntoByte = void 0;
4
4
  const get_seeking_byte_1 = require("./get-seeking-byte");
5
5
  const get_seeking_hints_1 = require("./get-seeking-hints");
6
6
  const log_1 = require("./log");
@@ -55,6 +55,7 @@ const turnSeekIntoByte = async ({ seek, mediaSectionState, logLevel, iterator, s
55
55
  });
56
56
  return seekingByte;
57
57
  };
58
+ exports.turnSeekIntoByte = turnSeekIntoByte;
58
59
  const getWorkOnSeekRequestOptions = (state) => {
59
60
  return {
60
61
  logLevel: state.logLevel,
@@ -94,7 +95,7 @@ const workOnSeekRequest = async (options) => {
94
95
  return;
95
96
  }
96
97
  log_1.Log.trace(logLevel, `Has seek request for ${src}: ${JSON.stringify(seek)}`);
97
- const resolution = await turnSeekIntoByte({
98
+ const resolution = await (0, exports.turnSeekIntoByte)({
98
99
  seek,
99
100
  mediaSectionState: mediaSection,
100
101
  logLevel,
@@ -29,6 +29,24 @@ const forwardMediaParserControllerToWorker = (controller) => {
29
29
  });
30
30
  return;
31
31
  }
32
+ if (message.type === 'request-simulate-seek') {
33
+ controller
34
+ .simulateSeek(message.payload)
35
+ .then((resolution) => {
36
+ postMessage({
37
+ type: 'response-simulate-seek',
38
+ nonce: message.nonce,
39
+ payload: resolution,
40
+ });
41
+ })
42
+ .catch((err) => {
43
+ postMessage({
44
+ type: 'response-error',
45
+ payload: err,
46
+ });
47
+ });
48
+ return;
49
+ }
32
50
  if (message.type === 'request-resume') {
33
51
  controller.resume();
34
52
  return;
@@ -12,6 +12,7 @@ import type { SeekingHints } from '../seeking-hints';
12
12
  import type { MediaParserEmbeddedImage } from '../state/images';
13
13
  import type { InternalStats } from '../state/parser-state';
14
14
  import type { MediaParserAudioSample, MediaParserOnAudioTrackParams, MediaParserOnVideoTrackParams, MediaParserVideoSample } from '../webcodec-sample-types';
15
+ import type { SeekResolution } from '../work-on-seek-request';
15
16
  export type ParseMediaOnWorkerPayload = {
16
17
  type: 'request-worker';
17
18
  src: ParseMediaSrc;
@@ -63,6 +64,11 @@ type RequestResume = {
63
64
  type RequestGetSeekingHints = {
64
65
  type: 'request-get-seeking-hints';
65
66
  };
67
+ type RequestSimulateSeek = {
68
+ type: 'request-simulate-seek';
69
+ payload: number;
70
+ nonce: string;
71
+ };
66
72
  type RequestAbort = {
67
73
  type: 'request-abort';
68
74
  };
@@ -75,6 +81,11 @@ type ResponseGetSeekingHints = {
75
81
  type: 'response-get-seeking-hints';
76
82
  payload: SeekingHints;
77
83
  };
84
+ type ResponseSimulateSeek = {
85
+ type: 'response-simulate-seek';
86
+ nonce: string;
87
+ payload: SeekResolution;
88
+ };
78
89
  type BaseError = {
79
90
  errorStack: string;
80
91
  errorMessage: string;
@@ -261,6 +272,6 @@ export type SignalErrorInCallback = {
261
272
  type: 'signal-error-in-callback';
262
273
  nonce: string;
263
274
  };
264
- export type WorkerRequestPayload = ParseMediaOnWorkerPayload | RequestResume | RequestPause | RequestAbort | RequestSeek | RequestGetSeekingHints | AcknowledgeCallback | SignalErrorInCallback;
265
- export type WorkerResponsePayload = ResponseDone | ResponseError | ResponseOnCallbackRequest | ResponseGetSeekingHints;
275
+ export type WorkerRequestPayload = ParseMediaOnWorkerPayload | RequestResume | RequestPause | RequestAbort | RequestSeek | RequestGetSeekingHints | RequestSimulateSeek | AcknowledgeCallback | SignalErrorInCallback;
276
+ export type WorkerResponsePayload = ResponseDone | ResponseError | ResponseOnCallbackRequest | ResponseGetSeekingHints | ResponseSimulateSeek;
266
277
  export {};
package/package.json CHANGED
@@ -3,15 +3,15 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
4
4
  },
5
5
  "name": "@remotion/media-parser",
6
- "version": "4.0.311",
6
+ "version": "4.0.313",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "devDependencies": {
10
10
  "@types/wicg-file-system-access": "2023.10.5",
11
11
  "eslint": "9.19.0",
12
12
  "@types/bun": "1.2.8",
13
- "@remotion/example-videos": "4.0.311",
14
- "@remotion/eslint-config-internal": "4.0.311"
13
+ "@remotion/example-videos": "4.0.313",
14
+ "@remotion/eslint-config-internal": "4.0.313"
15
15
  },
16
16
  "publishConfig": {
17
17
  "access": "public"