@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
@@ -6860,24 +6860,38 @@ var mediaParserController = () => {
6860
6860
  await pauseSignal.waitUntilResume();
6861
6861
  };
6862
6862
  let seekingHintResolution = null;
6863
+ let simulateSeekResolution = null;
6863
6864
  const getSeekingHints = () => {
6864
6865
  if (!seekingHintResolution) {
6865
6866
  throw new Error("The mediaParserController() was not yet used in a parseMedia() call");
6866
6867
  }
6867
6868
  return seekingHintResolution();
6868
6869
  };
6870
+ const simulateSeek = (seekInSeconds) => {
6871
+ if (!simulateSeekResolution) {
6872
+ throw new Error("The mediaParserController() was not yet used in a parseMedia() call");
6873
+ }
6874
+ return simulateSeekResolution(seekInSeconds);
6875
+ };
6869
6876
  const attachSeekingHintResolution = (callback) => {
6870
6877
  if (seekingHintResolution) {
6871
6878
  throw new Error("The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.");
6872
6879
  }
6873
6880
  seekingHintResolution = callback;
6874
6881
  };
6882
+ const attachSimulateSeekResolution = (callback) => {
6883
+ if (simulateSeekResolution) {
6884
+ throw new Error("The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.");
6885
+ }
6886
+ simulateSeekResolution = callback;
6887
+ };
6875
6888
  return {
6876
6889
  abort: (reason) => {
6877
6890
  abortController.abort(reason);
6878
6891
  emitter.dispatchAbort(reason);
6879
6892
  },
6880
6893
  seek: seekSignal.seek,
6894
+ simulateSeek,
6881
6895
  pause: pauseSignal.pause,
6882
6896
  resume: pauseSignal.resume,
6883
6897
  addEventListener: emitter.addEventListener,
@@ -6889,7 +6903,8 @@ var mediaParserController = () => {
6889
6903
  seekSignal,
6890
6904
  markAsReadyToEmitEvents: emitter.markAsReady,
6891
6905
  performedSeeksSignal,
6892
- attachSeekingHintResolution
6906
+ attachSeekingHintResolution,
6907
+ attachSimulateSeekResolution
6893
6908
  }
6894
6909
  };
6895
6910
  };
@@ -8102,7 +8117,11 @@ var getSeekingByteForAac = ({
8102
8117
  }
8103
8118
  }
8104
8119
  if (bestAudioSample) {
8105
- return { type: "do-seek", byte: bestAudioSample.offset };
8120
+ return {
8121
+ type: "do-seek",
8122
+ byte: bestAudioSample.offset,
8123
+ timeInSeconds: bestAudioSample.timeInSeconds
8124
+ };
8106
8125
  }
8107
8126
  return { type: "valid-but-must-wait" };
8108
8127
  };
@@ -8129,7 +8148,7 @@ var getSeekingByteForFlac = ({
8129
8148
  }
8130
8149
  }
8131
8150
  if (bestAudioSample) {
8132
- return bestAudioSample.offset;
8151
+ return bestAudioSample;
8133
8152
  }
8134
8153
  return null;
8135
8154
  };
@@ -8167,7 +8186,7 @@ var findKeyframeBeforeTime = ({
8167
8186
  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);
8168
8187
  return null;
8169
8188
  }
8170
- return videoSample.offset;
8189
+ return videoSample;
8171
8190
  };
8172
8191
 
8173
8192
  // src/containers/iso-base-media/find-track-to-seek.ts
@@ -8398,7 +8417,8 @@ var getSeekingByteFromFragmentedMp4 = async ({
8398
8417
  if (kf) {
8399
8418
  return {
8400
8419
  type: "do-seek",
8401
- byte: kf
8420
+ byte: kf.offset,
8421
+ timeInSeconds: Math.min(kf.decodingTimestamp, kf.timestamp) / firstTrack.originalTimescale
8402
8422
  };
8403
8423
  }
8404
8424
  }
@@ -8501,7 +8521,8 @@ var getSeekingByteFromIsoBaseMedia = ({
8501
8521
  if (keyframe) {
8502
8522
  return Promise.resolve({
8503
8523
  type: "do-seek",
8504
- byte: keyframe
8524
+ byte: keyframe.offset,
8525
+ timeInSeconds: Math.min(keyframe.decodingTimestamp, keyframe.timestamp) / track.originalTimescale
8505
8526
  });
8506
8527
  }
8507
8528
  return Promise.resolve({
@@ -8541,7 +8562,8 @@ var getSeekingByteForM3u8 = ({
8541
8562
  }
8542
8563
  return {
8543
8564
  type: "do-seek",
8544
- byte: currentPosition
8565
+ byte: currentPosition,
8566
+ timeInSeconds: time
8545
8567
  };
8546
8568
  };
8547
8569
 
@@ -8775,9 +8797,12 @@ var getSeekingByteForMp3 = ({
8775
8797
  type: "valid-but-must-wait"
8776
8798
  };
8777
8799
  }
8800
+ const byte = Math.max(...candidates);
8801
+ const timeInSeconds = byte === bestAudioSample?.offset ? bestAudioSample.timeInSeconds : time;
8778
8802
  return {
8779
8803
  type: "do-seek",
8780
- byte: Math.max(...candidates)
8804
+ byte,
8805
+ timeInSeconds
8781
8806
  };
8782
8807
  };
8783
8808
 
@@ -8821,7 +8846,8 @@ var getSeekingByteForRiff = async ({
8821
8846
  avcState.clear();
8822
8847
  return {
8823
8848
  type: "do-seek",
8824
- byte: lastKeyframe.positionInBytes
8849
+ byte: lastKeyframe.positionInBytes,
8850
+ timeInSeconds: Math.min(lastKeyframe.decodingTimeInSeconds, lastKeyframe.presentationTimeInSeconds)
8825
8851
  };
8826
8852
  }
8827
8853
  if (idx1Entries.videoTrackIndex === null) {
@@ -8852,121 +8878,8 @@ var getSeekingByteForRiff = async ({
8852
8878
  avcState.clear();
8853
8879
  return {
8854
8880
  type: "do-seek",
8855
- byte: bestEntry.offset + info.moviOffset - 4
8856
- };
8857
- };
8858
-
8859
- // src/containers/wav/get-seeking-byte.ts
8860
- var WAVE_SAMPLES_PER_SECOND = 25;
8861
- var getSeekingByteFromWav = ({
8862
- info,
8863
- time
8864
- }) => {
8865
- const bytesPerSecond = info.sampleRate * info.blockAlign;
8866
- const durationInSeconds = info.mediaSection.size / bytesPerSecond;
8867
- const timeRoundedDown = Math.floor(Math.min(time, durationInSeconds - 0.0000001) * WAVE_SAMPLES_PER_SECOND) / WAVE_SAMPLES_PER_SECOND;
8868
- const byteOffset = bytesPerSecond * timeRoundedDown;
8869
- return Promise.resolve({
8870
- type: "do-seek",
8871
- byte: byteOffset + info.mediaSection.start
8872
- });
8873
- };
8874
-
8875
- // src/containers/webm/seek/get-seeking-byte.ts
8876
- var toSeconds = (timeInTimescale, track) => {
8877
- return timeInTimescale / track.timescale * 1000;
8878
- };
8879
- var findBiggestCueBeforeTime = ({
8880
- cues,
8881
- time,
8882
- track
8883
- }) => {
8884
- let biggestCueBeforeTime;
8885
- for (const cue of cues) {
8886
- const cueTimeInSeconds = toSeconds(cue.timeInTimescale, track);
8887
- if (cueTimeInSeconds < time && (!biggestCueBeforeTime || cueTimeInSeconds > toSeconds(biggestCueBeforeTime.timeInTimescale, track))) {
8888
- biggestCueBeforeTime = cue;
8889
- }
8890
- }
8891
- return biggestCueBeforeTime;
8892
- };
8893
- var findKeyframeBeforeTime2 = ({
8894
- keyframes,
8895
- time
8896
- }) => {
8897
- let keyframeBeforeTime;
8898
- for (const keyframe of keyframes) {
8899
- if (keyframe.decodingTimeInSeconds < time && (!keyframeBeforeTime || keyframe.decodingTimeInSeconds > keyframeBeforeTime.decodingTimeInSeconds)) {
8900
- keyframeBeforeTime = keyframe;
8901
- }
8902
- }
8903
- return keyframeBeforeTime?.positionInBytes ?? null;
8904
- };
8905
- var getByteFromCues = ({
8906
- cuesResponse,
8907
- time,
8908
- info,
8909
- logLevel
8910
- }) => {
8911
- if (!cuesResponse) {
8912
- Log.trace(logLevel, "Has no Matroska cues at the moment, cannot use them");
8913
- return null;
8914
- }
8915
- const { cues, segmentOffset } = cuesResponse;
8916
- Log.trace(logLevel, "Has Matroska cues. Will use them to perform a seek.");
8917
- const biggestCueBeforeTime = findBiggestCueBeforeTime({
8918
- cues,
8919
- time,
8920
- track: info.track
8921
- });
8922
- if (!biggestCueBeforeTime) {
8923
- return null;
8924
- }
8925
- return biggestCueBeforeTime.clusterPositionInSegment + segmentOffset;
8926
- };
8927
- var getSeekingByteFromMatroska = async ({
8928
- time,
8929
- webmState,
8930
- info,
8931
- logLevel,
8932
- mediaSection
8933
- }) => {
8934
- if (!info.track) {
8935
- Log.trace(logLevel, "No video track found, cannot seek yet");
8936
- return {
8937
- type: "valid-but-must-wait"
8938
- };
8939
- }
8940
- const cuesResponse = info.loadedCues ?? await webmState.cues.getLoadedCues();
8941
- const byteFromObservedKeyframe = findKeyframeBeforeTime2({
8942
- keyframes: info.keyframes,
8943
- time
8944
- });
8945
- const byteFromCues = getByteFromCues({
8946
- cuesResponse,
8947
- time,
8948
- info,
8949
- logLevel
8950
- });
8951
- const byteFromFirstMediaSection = webmState.getFirstCluster()?.start ?? null;
8952
- const seekPossibilities = [
8953
- byteFromCues,
8954
- byteFromObservedKeyframe,
8955
- byteFromFirstMediaSection
8956
- ].filter((n) => n !== null);
8957
- const byteToSeekTo = seekPossibilities.length === 0 ? null : Math.max(...seekPossibilities);
8958
- if (byteToSeekTo === null) {
8959
- return {
8960
- type: "invalid"
8961
- };
8962
- }
8963
- mediaSection.addMediaSection({
8964
- start: byteToSeekTo,
8965
- size: 1
8966
- });
8967
- return {
8968
- type: "do-seek",
8969
- byte: byteToSeekTo
8881
+ byte: bestEntry.offset + info.moviOffset - 4,
8882
+ timeInSeconds: bestEntry.sampleCounts[idx1Entries.videoTrackIndex] / info.samplesPerSecond
8970
8883
  };
8971
8884
  };
8972
8885
 
@@ -9137,6 +9050,137 @@ var handleAvcPacket = async ({
9137
9050
  transportStream.lastEmittedSample.setLastEmittedSample(sample);
9138
9051
  };
9139
9052
 
9053
+ // src/containers/wav/get-seeking-byte.ts
9054
+ var WAVE_SAMPLES_PER_SECOND = 25;
9055
+ var getSeekingByteFromWav = ({
9056
+ info,
9057
+ time
9058
+ }) => {
9059
+ const bytesPerSecond = info.sampleRate * info.blockAlign;
9060
+ const durationInSeconds = info.mediaSection.size / bytesPerSecond;
9061
+ const timeRoundedDown = Math.floor(Math.min(time, durationInSeconds - 0.0000001) * WAVE_SAMPLES_PER_SECOND) / WAVE_SAMPLES_PER_SECOND;
9062
+ const byteOffset = bytesPerSecond * timeRoundedDown;
9063
+ return Promise.resolve({
9064
+ type: "do-seek",
9065
+ byte: byteOffset + info.mediaSection.start,
9066
+ timeInSeconds: timeRoundedDown
9067
+ });
9068
+ };
9069
+
9070
+ // src/containers/webm/seek/get-seeking-byte.ts
9071
+ var toSeconds = (timeInTimescale, track) => {
9072
+ return timeInTimescale / track.timescale * 1000;
9073
+ };
9074
+ var findBiggestCueBeforeTime = ({
9075
+ cues,
9076
+ time,
9077
+ track
9078
+ }) => {
9079
+ let biggestCueBeforeTime;
9080
+ for (const cue of cues) {
9081
+ const cueTimeInSeconds = toSeconds(cue.timeInTimescale, track);
9082
+ if (cueTimeInSeconds < time && (!biggestCueBeforeTime || cueTimeInSeconds > toSeconds(biggestCueBeforeTime.timeInTimescale, track))) {
9083
+ biggestCueBeforeTime = cue;
9084
+ }
9085
+ }
9086
+ return biggestCueBeforeTime;
9087
+ };
9088
+ var findKeyframeBeforeTime2 = ({
9089
+ keyframes,
9090
+ time
9091
+ }) => {
9092
+ let keyframeBeforeTime;
9093
+ for (const keyframe of keyframes) {
9094
+ if (keyframe.decodingTimeInSeconds < time && (!keyframeBeforeTime || keyframe.decodingTimeInSeconds > keyframeBeforeTime.decodingTimeInSeconds)) {
9095
+ keyframeBeforeTime = keyframe;
9096
+ }
9097
+ }
9098
+ return keyframeBeforeTime ?? null;
9099
+ };
9100
+ var getByteFromCues = ({
9101
+ cuesResponse,
9102
+ time,
9103
+ info,
9104
+ logLevel
9105
+ }) => {
9106
+ if (!cuesResponse) {
9107
+ Log.trace(logLevel, "Has no Matroska cues at the moment, cannot use them");
9108
+ return null;
9109
+ }
9110
+ const { cues, segmentOffset } = cuesResponse;
9111
+ Log.trace(logLevel, "Has Matroska cues. Will use them to perform a seek.");
9112
+ const biggestCueBeforeTime = findBiggestCueBeforeTime({
9113
+ cues,
9114
+ time,
9115
+ track: info.track
9116
+ });
9117
+ if (!biggestCueBeforeTime) {
9118
+ return null;
9119
+ }
9120
+ return {
9121
+ byte: biggestCueBeforeTime.clusterPositionInSegment + segmentOffset,
9122
+ timeInSeconds: toSeconds(biggestCueBeforeTime.timeInTimescale, info.track)
9123
+ };
9124
+ };
9125
+ var getSeekingByteFromMatroska = async ({
9126
+ time,
9127
+ webmState,
9128
+ info,
9129
+ logLevel,
9130
+ mediaSection
9131
+ }) => {
9132
+ if (!info.track) {
9133
+ Log.trace(logLevel, "No video track found, cannot seek yet");
9134
+ return {
9135
+ type: "valid-but-must-wait"
9136
+ };
9137
+ }
9138
+ const cuesResponse = info.loadedCues ?? await webmState.cues.getLoadedCues();
9139
+ const byteFromObservedKeyframe = findKeyframeBeforeTime2({
9140
+ keyframes: info.keyframes,
9141
+ time
9142
+ });
9143
+ const byteFromCues = getByteFromCues({
9144
+ cuesResponse,
9145
+ time,
9146
+ info,
9147
+ logLevel
9148
+ });
9149
+ const byteFromFirstMediaSection = webmState.getFirstCluster()?.start ?? null;
9150
+ const seekPossibilities = [
9151
+ byteFromCues?.byte ?? null,
9152
+ byteFromObservedKeyframe?.positionInBytes ?? null,
9153
+ byteFromFirstMediaSection
9154
+ ].filter((n) => n !== null);
9155
+ const byteToSeekTo = seekPossibilities.length === 0 ? null : Math.max(...seekPossibilities);
9156
+ if (byteToSeekTo === null) {
9157
+ return {
9158
+ type: "invalid"
9159
+ };
9160
+ }
9161
+ mediaSection.addMediaSection({
9162
+ start: byteToSeekTo,
9163
+ size: 1
9164
+ });
9165
+ const timeInSeconds = (() => {
9166
+ if (byteToSeekTo === byteFromObservedKeyframe?.positionInBytes) {
9167
+ return Math.min(byteFromObservedKeyframe.decodingTimeInSeconds, byteFromObservedKeyframe.presentationTimeInSeconds);
9168
+ }
9169
+ if (byteToSeekTo === byteFromCues?.byte) {
9170
+ return byteFromCues.timeInSeconds;
9171
+ }
9172
+ if (byteToSeekTo === byteFromFirstMediaSection) {
9173
+ return 0;
9174
+ }
9175
+ throw new Error("Should not happen");
9176
+ })();
9177
+ return {
9178
+ type: "do-seek",
9179
+ byte: byteToSeekTo,
9180
+ timeInSeconds
9181
+ };
9182
+ };
9183
+
9140
9184
  // src/state/transport-stream/observed-pes-header.ts
9141
9185
  var makeObservedPesHeader = () => {
9142
9186
  const pesHeaders = [];
@@ -9226,7 +9270,8 @@ var getSeekingByte = ({
9226
9270
  if (byte) {
9227
9271
  return Promise.resolve({
9228
9272
  type: "do-seek",
9229
- byte
9273
+ byte: byte.offset,
9274
+ timeInSeconds: byte.timeInSeconds
9230
9275
  });
9231
9276
  }
9232
9277
  return Promise.resolve({
@@ -9239,11 +9284,20 @@ var getSeekingByte = ({
9239
9284
  timeInSeconds: time,
9240
9285
  ptsStartOffset: info.ptsStartOffset
9241
9286
  });
9242
- const byte = lastKeyframeBeforeTimeInSeconds?.offset ?? 0;
9287
+ if (!lastKeyframeBeforeTimeInSeconds) {
9288
+ transportStream.resetBeforeSeek();
9289
+ return Promise.resolve({
9290
+ type: "do-seek",
9291
+ byte: 0,
9292
+ timeInSeconds: 0
9293
+ });
9294
+ }
9295
+ const byte = lastKeyframeBeforeTimeInSeconds.offset;
9243
9296
  transportStream.resetBeforeSeek();
9244
9297
  return Promise.resolve({
9245
9298
  type: "do-seek",
9246
- byte
9299
+ byte,
9300
+ timeInSeconds: Math.min(lastKeyframeBeforeTimeInSeconds.pts, lastKeyframeBeforeTimeInSeconds.dts ?? Infinity) / MPEG_TIMESCALE
9247
9301
  });
9248
9302
  }
9249
9303
  if (info.type === "riff-seeking-hints") {
@@ -15039,10 +15093,11 @@ var parseList = ({
15039
15093
  const metadata = [];
15040
15094
  const remainingBytes = () => ckSize - (iterator.counter.getOffset() - startOffset);
15041
15095
  while (remainingBytes() > 0) {
15042
- if (remainingBytes() < 4) {
15043
- iterator.discard(remainingBytes());
15044
- break;
15096
+ const byte = iterator.getUint8();
15097
+ if (byte === 0) {
15098
+ continue;
15045
15099
  }
15100
+ iterator.counter.decrement(1);
15046
15101
  const key = iterator.getByteString(4, false);
15047
15102
  const size = iterator.getUint32Le();
15048
15103
  const value = iterator.getByteString(size, true);
@@ -17598,6 +17653,46 @@ var internalParseMedia = async function({
17598
17653
  contentLength: state.contentLength,
17599
17654
  aacState: state.aac
17600
17655
  })));
17656
+ controller._internals.attachSimulateSeekResolution((seek2) => {
17657
+ const {
17658
+ aacState: aacState2,
17659
+ avcState: avcState2,
17660
+ flacState: flacState2,
17661
+ isoState,
17662
+ iterator,
17663
+ keyframes,
17664
+ m3uState: m3uState2,
17665
+ mediaSection,
17666
+ mp3State,
17667
+ riffState,
17668
+ samplesObserved,
17669
+ structureState: structureState2,
17670
+ tracksState,
17671
+ transportStream,
17672
+ webmState: webmState2
17673
+ } = getWorkOnSeekRequestOptions(state);
17674
+ return turnSeekIntoByte({
17675
+ aacState: aacState2,
17676
+ seek: seek2,
17677
+ avcState: avcState2,
17678
+ contentLength,
17679
+ flacState: flacState2,
17680
+ isoState,
17681
+ iterator,
17682
+ keyframes,
17683
+ logLevel,
17684
+ m3uPlaylistContext,
17685
+ m3uState: m3uState2,
17686
+ mediaSectionState: mediaSection,
17687
+ mp3State,
17688
+ riffState,
17689
+ samplesObserved,
17690
+ structureState: structureState2,
17691
+ tracksState,
17692
+ transportStream,
17693
+ webmState: webmState2
17694
+ });
17695
+ });
17601
17696
  if (!hasAudioTrackHandlers && !hasVideoTrackHandlers && Object.values(state.fields).every((v) => !v) && mode === "query") {
17602
17697
  Log.warn(logLevel, new Error("Warning - No `fields` and no `on*` callbacks were passed to `parseMedia()`. Specify the data you would like to retrieve."));
17603
17698
  }
@@ -17699,7 +17794,7 @@ var downloadAndParseMedia = async (options) => {
17699
17794
  return returnValue;
17700
17795
  };
17701
17796
  // src/version.ts
17702
- var VERSION = "4.0.311";
17797
+ var VERSION = "4.0.312";
17703
17798
 
17704
17799
  // src/index.ts
17705
17800
  var MediaParserInternals = {
@@ -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);