@remotion/media-parser 4.0.311 → 4.0.312

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 (33) 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/find-keyframe-before-time.d.ts +1 -1
  5. package/dist/containers/iso-base-media/find-keyframe-before-time.js +1 -1
  6. package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +3 -1
  7. package/dist/containers/iso-base-media/get-seeking-byte.js +3 -1
  8. package/dist/containers/m3u/get-seeking-byte.js +2 -0
  9. package/dist/containers/mp3/get-seeking-byte.js +4 -1
  10. package/dist/containers/riff/get-seeking-byte.js +3 -0
  11. package/dist/containers/wav/get-seeking-byte.js +1 -0
  12. package/dist/containers/wav/parse-list.js +4 -3
  13. package/dist/containers/webm/seek/get-seeking-byte.js +21 -6
  14. package/dist/controller/media-parser-controller.d.ts +3 -0
  15. package/dist/controller/media-parser-controller.js +15 -0
  16. package/dist/esm/index.mjs +226 -131
  17. package/dist/esm/server-worker.mjs +17 -0
  18. package/dist/esm/worker-server-entry.mjs +240 -130
  19. package/dist/esm/worker-web-entry.mjs +240 -130
  20. package/dist/esm/worker.mjs +28 -0
  21. package/dist/get-seeking-byte.js +13 -2
  22. package/dist/index.cjs +54 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/internal-parse-media.js +25 -0
  25. package/dist/parse-media-on-worker-entry.js +17 -0
  26. package/dist/version.d.ts +1 -1
  27. package/dist/version.js +1 -1
  28. package/dist/webcodec-sample-types.d.ts +2 -2
  29. package/dist/work-on-seek-request.d.ts +22 -0
  30. package/dist/work-on-seek-request.js +3 -2
  31. package/dist/worker/forward-controller-to-worker.js +18 -0
  32. package/dist/worker/worker-types.d.ts +13 -2
  33. package/package.json +3 -3
@@ -647,24 +647,38 @@ var mediaParserController = () => {
647
647
  await pauseSignal.waitUntilResume();
648
648
  };
649
649
  let seekingHintResolution = null;
650
+ let simulateSeekResolution = null;
650
651
  const getSeekingHints = () => {
651
652
  if (!seekingHintResolution) {
652
653
  throw new Error("The mediaParserController() was not yet used in a parseMedia() call");
653
654
  }
654
655
  return seekingHintResolution();
655
656
  };
657
+ const simulateSeek = (seekInSeconds) => {
658
+ if (!simulateSeekResolution) {
659
+ throw new Error("The mediaParserController() was not yet used in a parseMedia() call");
660
+ }
661
+ return simulateSeekResolution(seekInSeconds);
662
+ };
656
663
  const attachSeekingHintResolution = (callback) => {
657
664
  if (seekingHintResolution) {
658
665
  throw new Error("The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.");
659
666
  }
660
667
  seekingHintResolution = callback;
661
668
  };
669
+ const attachSimulateSeekResolution = (callback) => {
670
+ if (simulateSeekResolution) {
671
+ throw new Error("The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.");
672
+ }
673
+ simulateSeekResolution = callback;
674
+ };
662
675
  return {
663
676
  abort: (reason) => {
664
677
  abortController.abort(reason);
665
678
  emitter.dispatchAbort(reason);
666
679
  },
667
680
  seek: seekSignal.seek,
681
+ simulateSeek,
668
682
  pause: pauseSignal.pause,
669
683
  resume: pauseSignal.resume,
670
684
  addEventListener: emitter.addEventListener,
@@ -676,7 +690,8 @@ var mediaParserController = () => {
676
690
  seekSignal,
677
691
  markAsReadyToEmitEvents: emitter.markAsReady,
678
692
  performedSeeksSignal,
679
- attachSeekingHintResolution
693
+ attachSeekingHintResolution,
694
+ attachSimulateSeekResolution
680
695
  }
681
696
  };
682
697
  };
@@ -5741,7 +5756,11 @@ var getSeekingByteForAac = ({
5741
5756
  }
5742
5757
  }
5743
5758
  if (bestAudioSample) {
5744
- return { type: "do-seek", byte: bestAudioSample.offset };
5759
+ return {
5760
+ type: "do-seek",
5761
+ byte: bestAudioSample.offset,
5762
+ timeInSeconds: bestAudioSample.timeInSeconds
5763
+ };
5745
5764
  }
5746
5765
  return { type: "valid-but-must-wait" };
5747
5766
  };
@@ -5768,7 +5787,7 @@ var getSeekingByteForFlac = ({
5768
5787
  }
5769
5788
  }
5770
5789
  if (bestAudioSample) {
5771
- return bestAudioSample.offset;
5790
+ return bestAudioSample;
5772
5791
  }
5773
5792
  return null;
5774
5793
  };
@@ -5806,7 +5825,7 @@ var findKeyframeBeforeTime = ({
5806
5825
  Log.trace(logLevel, "Found a sample, but the offset has not yet been marked as a video section yet. Not yet able to seek, but probably once we have started reading the next box.", videoSample);
5807
5826
  return null;
5808
5827
  }
5809
- return videoSample.offset;
5828
+ return videoSample;
5810
5829
  };
5811
5830
 
5812
5831
  // src/containers/iso-base-media/find-track-to-seek.ts
@@ -6037,7 +6056,8 @@ var getSeekingByteFromFragmentedMp4 = async ({
6037
6056
  if (kf) {
6038
6057
  return {
6039
6058
  type: "do-seek",
6040
- byte: kf
6059
+ byte: kf.offset,
6060
+ timeInSeconds: Math.min(kf.decodingTimestamp, kf.timestamp) / firstTrack.originalTimescale
6041
6061
  };
6042
6062
  }
6043
6063
  }
@@ -6140,7 +6160,8 @@ var getSeekingByteFromIsoBaseMedia = ({
6140
6160
  if (keyframe) {
6141
6161
  return Promise.resolve({
6142
6162
  type: "do-seek",
6143
- byte: keyframe
6163
+ byte: keyframe.offset,
6164
+ timeInSeconds: Math.min(keyframe.decodingTimestamp, keyframe.timestamp) / track.originalTimescale
6144
6165
  });
6145
6166
  }
6146
6167
  return Promise.resolve({
@@ -6180,7 +6201,8 @@ var getSeekingByteForM3u8 = ({
6180
6201
  }
6181
6202
  return {
6182
6203
  type: "do-seek",
6183
- byte: currentPosition
6204
+ byte: currentPosition,
6205
+ timeInSeconds: time
6184
6206
  };
6185
6207
  };
6186
6208
 
@@ -6414,9 +6436,12 @@ var getSeekingByteForMp3 = ({
6414
6436
  type: "valid-but-must-wait"
6415
6437
  };
6416
6438
  }
6439
+ const byte = Math.max(...candidates);
6440
+ const timeInSeconds = byte === bestAudioSample?.offset ? bestAudioSample.timeInSeconds : time;
6417
6441
  return {
6418
6442
  type: "do-seek",
6419
- byte: Math.max(...candidates)
6443
+ byte,
6444
+ timeInSeconds
6420
6445
  };
6421
6446
  };
6422
6447
 
@@ -6460,7 +6485,8 @@ var getSeekingByteForRiff = async ({
6460
6485
  avcState.clear();
6461
6486
  return {
6462
6487
  type: "do-seek",
6463
- byte: lastKeyframe.positionInBytes
6488
+ byte: lastKeyframe.positionInBytes,
6489
+ timeInSeconds: Math.min(lastKeyframe.decodingTimeInSeconds, lastKeyframe.presentationTimeInSeconds)
6464
6490
  };
6465
6491
  }
6466
6492
  if (idx1Entries.videoTrackIndex === null) {
@@ -6491,121 +6517,8 @@ var getSeekingByteForRiff = async ({
6491
6517
  avcState.clear();
6492
6518
  return {
6493
6519
  type: "do-seek",
6494
- byte: bestEntry.offset + info.moviOffset - 4
6495
- };
6496
- };
6497
-
6498
- // src/containers/wav/get-seeking-byte.ts
6499
- var WAVE_SAMPLES_PER_SECOND = 25;
6500
- var getSeekingByteFromWav = ({
6501
- info,
6502
- time
6503
- }) => {
6504
- const bytesPerSecond = info.sampleRate * info.blockAlign;
6505
- const durationInSeconds = info.mediaSection.size / bytesPerSecond;
6506
- const timeRoundedDown = Math.floor(Math.min(time, durationInSeconds - 0.0000001) * WAVE_SAMPLES_PER_SECOND) / WAVE_SAMPLES_PER_SECOND;
6507
- const byteOffset = bytesPerSecond * timeRoundedDown;
6508
- return Promise.resolve({
6509
- type: "do-seek",
6510
- byte: byteOffset + info.mediaSection.start
6511
- });
6512
- };
6513
-
6514
- // src/containers/webm/seek/get-seeking-byte.ts
6515
- var toSeconds = (timeInTimescale, track) => {
6516
- return timeInTimescale / track.timescale * 1000;
6517
- };
6518
- var findBiggestCueBeforeTime = ({
6519
- cues,
6520
- time,
6521
- track
6522
- }) => {
6523
- let biggestCueBeforeTime;
6524
- for (const cue of cues) {
6525
- const cueTimeInSeconds = toSeconds(cue.timeInTimescale, track);
6526
- if (cueTimeInSeconds < time && (!biggestCueBeforeTime || cueTimeInSeconds > toSeconds(biggestCueBeforeTime.timeInTimescale, track))) {
6527
- biggestCueBeforeTime = cue;
6528
- }
6529
- }
6530
- return biggestCueBeforeTime;
6531
- };
6532
- var findKeyframeBeforeTime2 = ({
6533
- keyframes,
6534
- time
6535
- }) => {
6536
- let keyframeBeforeTime;
6537
- for (const keyframe of keyframes) {
6538
- if (keyframe.decodingTimeInSeconds < time && (!keyframeBeforeTime || keyframe.decodingTimeInSeconds > keyframeBeforeTime.decodingTimeInSeconds)) {
6539
- keyframeBeforeTime = keyframe;
6540
- }
6541
- }
6542
- return keyframeBeforeTime?.positionInBytes ?? null;
6543
- };
6544
- var getByteFromCues = ({
6545
- cuesResponse,
6546
- time,
6547
- info,
6548
- logLevel
6549
- }) => {
6550
- if (!cuesResponse) {
6551
- Log.trace(logLevel, "Has no Matroska cues at the moment, cannot use them");
6552
- return null;
6553
- }
6554
- const { cues, segmentOffset } = cuesResponse;
6555
- Log.trace(logLevel, "Has Matroska cues. Will use them to perform a seek.");
6556
- const biggestCueBeforeTime = findBiggestCueBeforeTime({
6557
- cues,
6558
- time,
6559
- track: info.track
6560
- });
6561
- if (!biggestCueBeforeTime) {
6562
- return null;
6563
- }
6564
- return biggestCueBeforeTime.clusterPositionInSegment + segmentOffset;
6565
- };
6566
- var getSeekingByteFromMatroska = async ({
6567
- time,
6568
- webmState,
6569
- info,
6570
- logLevel,
6571
- mediaSection
6572
- }) => {
6573
- if (!info.track) {
6574
- Log.trace(logLevel, "No video track found, cannot seek yet");
6575
- return {
6576
- type: "valid-but-must-wait"
6577
- };
6578
- }
6579
- const cuesResponse = info.loadedCues ?? await webmState.cues.getLoadedCues();
6580
- const byteFromObservedKeyframe = findKeyframeBeforeTime2({
6581
- keyframes: info.keyframes,
6582
- time
6583
- });
6584
- const byteFromCues = getByteFromCues({
6585
- cuesResponse,
6586
- time,
6587
- info,
6588
- logLevel
6589
- });
6590
- const byteFromFirstMediaSection = webmState.getFirstCluster()?.start ?? null;
6591
- const seekPossibilities = [
6592
- byteFromCues,
6593
- byteFromObservedKeyframe,
6594
- byteFromFirstMediaSection
6595
- ].filter((n) => n !== null);
6596
- const byteToSeekTo = seekPossibilities.length === 0 ? null : Math.max(...seekPossibilities);
6597
- if (byteToSeekTo === null) {
6598
- return {
6599
- type: "invalid"
6600
- };
6601
- }
6602
- mediaSection.addMediaSection({
6603
- start: byteToSeekTo,
6604
- size: 1
6605
- });
6606
- return {
6607
- type: "do-seek",
6608
- byte: byteToSeekTo
6520
+ byte: bestEntry.offset + info.moviOffset - 4,
6521
+ timeInSeconds: bestEntry.sampleCounts[idx1Entries.videoTrackIndex] / info.samplesPerSecond
6609
6522
  };
6610
6523
  };
6611
6524
 
@@ -7147,6 +7060,137 @@ var handleAvcPacket = async ({
7147
7060
  transportStream.lastEmittedSample.setLastEmittedSample(sample);
7148
7061
  };
7149
7062
 
7063
+ // src/containers/wav/get-seeking-byte.ts
7064
+ var WAVE_SAMPLES_PER_SECOND = 25;
7065
+ var getSeekingByteFromWav = ({
7066
+ info,
7067
+ time
7068
+ }) => {
7069
+ const bytesPerSecond = info.sampleRate * info.blockAlign;
7070
+ const durationInSeconds = info.mediaSection.size / bytesPerSecond;
7071
+ const timeRoundedDown = Math.floor(Math.min(time, durationInSeconds - 0.0000001) * WAVE_SAMPLES_PER_SECOND) / WAVE_SAMPLES_PER_SECOND;
7072
+ const byteOffset = bytesPerSecond * timeRoundedDown;
7073
+ return Promise.resolve({
7074
+ type: "do-seek",
7075
+ byte: byteOffset + info.mediaSection.start,
7076
+ timeInSeconds: timeRoundedDown
7077
+ });
7078
+ };
7079
+
7080
+ // src/containers/webm/seek/get-seeking-byte.ts
7081
+ var toSeconds = (timeInTimescale, track) => {
7082
+ return timeInTimescale / track.timescale * 1000;
7083
+ };
7084
+ var findBiggestCueBeforeTime = ({
7085
+ cues,
7086
+ time,
7087
+ track
7088
+ }) => {
7089
+ let biggestCueBeforeTime;
7090
+ for (const cue of cues) {
7091
+ const cueTimeInSeconds = toSeconds(cue.timeInTimescale, track);
7092
+ if (cueTimeInSeconds < time && (!biggestCueBeforeTime || cueTimeInSeconds > toSeconds(biggestCueBeforeTime.timeInTimescale, track))) {
7093
+ biggestCueBeforeTime = cue;
7094
+ }
7095
+ }
7096
+ return biggestCueBeforeTime;
7097
+ };
7098
+ var findKeyframeBeforeTime2 = ({
7099
+ keyframes,
7100
+ time
7101
+ }) => {
7102
+ let keyframeBeforeTime;
7103
+ for (const keyframe of keyframes) {
7104
+ if (keyframe.decodingTimeInSeconds < time && (!keyframeBeforeTime || keyframe.decodingTimeInSeconds > keyframeBeforeTime.decodingTimeInSeconds)) {
7105
+ keyframeBeforeTime = keyframe;
7106
+ }
7107
+ }
7108
+ return keyframeBeforeTime ?? null;
7109
+ };
7110
+ var getByteFromCues = ({
7111
+ cuesResponse,
7112
+ time,
7113
+ info,
7114
+ logLevel
7115
+ }) => {
7116
+ if (!cuesResponse) {
7117
+ Log.trace(logLevel, "Has no Matroska cues at the moment, cannot use them");
7118
+ return null;
7119
+ }
7120
+ const { cues, segmentOffset } = cuesResponse;
7121
+ Log.trace(logLevel, "Has Matroska cues. Will use them to perform a seek.");
7122
+ const biggestCueBeforeTime = findBiggestCueBeforeTime({
7123
+ cues,
7124
+ time,
7125
+ track: info.track
7126
+ });
7127
+ if (!biggestCueBeforeTime) {
7128
+ return null;
7129
+ }
7130
+ return {
7131
+ byte: biggestCueBeforeTime.clusterPositionInSegment + segmentOffset,
7132
+ timeInSeconds: toSeconds(biggestCueBeforeTime.timeInTimescale, info.track)
7133
+ };
7134
+ };
7135
+ var getSeekingByteFromMatroska = async ({
7136
+ time,
7137
+ webmState,
7138
+ info,
7139
+ logLevel,
7140
+ mediaSection
7141
+ }) => {
7142
+ if (!info.track) {
7143
+ Log.trace(logLevel, "No video track found, cannot seek yet");
7144
+ return {
7145
+ type: "valid-but-must-wait"
7146
+ };
7147
+ }
7148
+ const cuesResponse = info.loadedCues ?? await webmState.cues.getLoadedCues();
7149
+ const byteFromObservedKeyframe = findKeyframeBeforeTime2({
7150
+ keyframes: info.keyframes,
7151
+ time
7152
+ });
7153
+ const byteFromCues = getByteFromCues({
7154
+ cuesResponse,
7155
+ time,
7156
+ info,
7157
+ logLevel
7158
+ });
7159
+ const byteFromFirstMediaSection = webmState.getFirstCluster()?.start ?? null;
7160
+ const seekPossibilities = [
7161
+ byteFromCues?.byte ?? null,
7162
+ byteFromObservedKeyframe?.positionInBytes ?? null,
7163
+ byteFromFirstMediaSection
7164
+ ].filter((n) => n !== null);
7165
+ const byteToSeekTo = seekPossibilities.length === 0 ? null : Math.max(...seekPossibilities);
7166
+ if (byteToSeekTo === null) {
7167
+ return {
7168
+ type: "invalid"
7169
+ };
7170
+ }
7171
+ mediaSection.addMediaSection({
7172
+ start: byteToSeekTo,
7173
+ size: 1
7174
+ });
7175
+ const timeInSeconds = (() => {
7176
+ if (byteToSeekTo === byteFromObservedKeyframe?.positionInBytes) {
7177
+ return Math.min(byteFromObservedKeyframe.decodingTimeInSeconds, byteFromObservedKeyframe.presentationTimeInSeconds);
7178
+ }
7179
+ if (byteToSeekTo === byteFromCues?.byte) {
7180
+ return byteFromCues.timeInSeconds;
7181
+ }
7182
+ if (byteToSeekTo === byteFromFirstMediaSection) {
7183
+ return 0;
7184
+ }
7185
+ throw new Error("Should not happen");
7186
+ })();
7187
+ return {
7188
+ type: "do-seek",
7189
+ byte: byteToSeekTo,
7190
+ timeInSeconds
7191
+ };
7192
+ };
7193
+
7150
7194
  // src/state/transport-stream/observed-pes-header.ts
7151
7195
  var makeObservedPesHeader = () => {
7152
7196
  const pesHeaders = [];
@@ -7236,7 +7280,8 @@ var getSeekingByte = ({
7236
7280
  if (byte) {
7237
7281
  return Promise.resolve({
7238
7282
  type: "do-seek",
7239
- byte
7283
+ byte: byte.offset,
7284
+ timeInSeconds: byte.timeInSeconds
7240
7285
  });
7241
7286
  }
7242
7287
  return Promise.resolve({
@@ -7249,11 +7294,20 @@ var getSeekingByte = ({
7249
7294
  timeInSeconds: time,
7250
7295
  ptsStartOffset: info.ptsStartOffset
7251
7296
  });
7252
- const byte = lastKeyframeBeforeTimeInSeconds?.offset ?? 0;
7297
+ if (!lastKeyframeBeforeTimeInSeconds) {
7298
+ transportStream.resetBeforeSeek();
7299
+ return Promise.resolve({
7300
+ type: "do-seek",
7301
+ byte: 0,
7302
+ timeInSeconds: 0
7303
+ });
7304
+ }
7305
+ const byte = lastKeyframeBeforeTimeInSeconds.offset;
7253
7306
  transportStream.resetBeforeSeek();
7254
7307
  return Promise.resolve({
7255
7308
  type: "do-seek",
7256
- byte
7309
+ byte,
7310
+ timeInSeconds: Math.min(lastKeyframeBeforeTimeInSeconds.pts, lastKeyframeBeforeTimeInSeconds.dts ?? Infinity) / MPEG_TIMESCALE
7257
7311
  });
7258
7312
  }
7259
7313
  if (info.type === "riff-seeking-hints") {
@@ -14647,10 +14701,11 @@ var parseList = ({
14647
14701
  const metadata = [];
14648
14702
  const remainingBytes = () => ckSize - (iterator.counter.getOffset() - startOffset);
14649
14703
  while (remainingBytes() > 0) {
14650
- if (remainingBytes() < 4) {
14651
- iterator.discard(remainingBytes());
14652
- break;
14704
+ const byte = iterator.getUint8();
14705
+ if (byte === 0) {
14706
+ continue;
14653
14707
  }
14708
+ iterator.counter.decrement(1);
14654
14709
  const key = iterator.getByteString(4, false);
14655
14710
  const size = iterator.getUint32Le();
14656
14711
  const value = iterator.getByteString(size, true);
@@ -17595,6 +17650,46 @@ var internalParseMedia = async function({
17595
17650
  contentLength: state.contentLength,
17596
17651
  aacState: state.aac
17597
17652
  })));
17653
+ controller._internals.attachSimulateSeekResolution((seek2) => {
17654
+ const {
17655
+ aacState: aacState2,
17656
+ avcState: avcState2,
17657
+ flacState: flacState2,
17658
+ isoState,
17659
+ iterator,
17660
+ keyframes,
17661
+ m3uState: m3uState2,
17662
+ mediaSection,
17663
+ mp3State,
17664
+ riffState,
17665
+ samplesObserved,
17666
+ structureState: structureState2,
17667
+ tracksState,
17668
+ transportStream,
17669
+ webmState: webmState2
17670
+ } = getWorkOnSeekRequestOptions(state);
17671
+ return turnSeekIntoByte({
17672
+ aacState: aacState2,
17673
+ seek: seek2,
17674
+ avcState: avcState2,
17675
+ contentLength,
17676
+ flacState: flacState2,
17677
+ isoState,
17678
+ iterator,
17679
+ keyframes,
17680
+ logLevel,
17681
+ m3uPlaylistContext,
17682
+ m3uState: m3uState2,
17683
+ mediaSectionState: mediaSection,
17684
+ mp3State,
17685
+ riffState,
17686
+ samplesObserved,
17687
+ structureState: structureState2,
17688
+ tracksState,
17689
+ transportStream,
17690
+ webmState: webmState2
17691
+ });
17692
+ });
17598
17693
  if (!hasAudioTrackHandlers && !hasVideoTrackHandlers && Object.values(state.fields).every((v) => !v) && mode === "query") {
17599
17694
  Log.warn(logLevel, new Error("Warning - No `fields` and no `on*` callbacks were passed to `parseMedia()`. Specify the data you would like to retrieve."));
17600
17695
  }
@@ -17648,6 +17743,21 @@ var forwardMediaParserControllerToWorker = (controller) => {
17648
17743
  });
17649
17744
  return;
17650
17745
  }
17746
+ if (message.type === "request-simulate-seek") {
17747
+ controller.simulateSeek(message.payload).then((resolution) => {
17748
+ postMessage({
17749
+ type: "response-simulate-seek",
17750
+ nonce: message.nonce,
17751
+ payload: resolution
17752
+ });
17753
+ }).catch((err) => {
17754
+ postMessage({
17755
+ type: "response-error",
17756
+ payload: err
17757
+ });
17758
+ });
17759
+ return;
17760
+ }
17651
17761
  if (message.type === "request-resume") {
17652
17762
  controller.resume();
17653
17763
  return;
@@ -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
  };
@@ -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
@@ -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.