@remotion/media-parser 4.0.310 → 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.
- package/dist/containers/aac/get-seeking-byte.js +5 -1
- package/dist/containers/flac/get-seeking-byte.d.ts +2 -1
- package/dist/containers/flac/get-seeking-byte.js +1 -1
- package/dist/containers/iso-base-media/find-keyframe-before-time.d.ts +1 -1
- package/dist/containers/iso-base-media/find-keyframe-before-time.js +1 -1
- package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +3 -1
- package/dist/containers/iso-base-media/get-seeking-byte.js +3 -1
- package/dist/containers/m3u/get-seeking-byte.js +2 -0
- package/dist/containers/mp3/get-seeking-byte.js +4 -1
- package/dist/containers/riff/get-seeking-byte.js +3 -0
- package/dist/containers/wav/get-seeking-byte.js +1 -0
- package/dist/containers/wav/parse-list.js +4 -3
- package/dist/containers/webm/seek/get-seeking-byte.js +21 -6
- package/dist/controller/media-parser-controller.d.ts +3 -0
- package/dist/controller/media-parser-controller.js +15 -0
- package/dist/esm/index.mjs +226 -131
- package/dist/esm/server-worker.mjs +20 -1
- package/dist/esm/worker-server-entry.mjs +248 -130
- package/dist/esm/worker-web-entry.mjs +248 -130
- package/dist/esm/worker.mjs +31 -1
- package/dist/get-seeking-byte.js +13 -2
- package/dist/index.cjs +54 -0
- package/dist/index.d.ts +1 -0
- package/dist/internal-parse-media.js +25 -0
- package/dist/parse-media-on-worker-entry.js +19 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/webcodec-sample-types.d.ts +2 -2
- package/dist/work-on-seek-request.d.ts +22 -0
- package/dist/work-on-seek-request.js +3 -2
- package/dist/worker/forward-controller-to-worker.js +18 -0
- package/dist/worker/serialize-error.js +14 -4
- package/dist/worker/worker-types.d.ts +17 -3
- 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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
14651
|
-
|
|
14652
|
-
|
|
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;
|
|
@@ -17701,6 +17811,14 @@ var serializeError = ({
|
|
|
17701
17811
|
seekingHints
|
|
17702
17812
|
};
|
|
17703
17813
|
}
|
|
17814
|
+
if (error instanceof TypeError) {
|
|
17815
|
+
return {
|
|
17816
|
+
type: "response-error",
|
|
17817
|
+
errorName: "TypeError",
|
|
17818
|
+
errorMessage: error.message,
|
|
17819
|
+
errorStack: error.stack ?? ""
|
|
17820
|
+
};
|
|
17821
|
+
}
|
|
17704
17822
|
if (error.name === "AbortError") {
|
|
17705
17823
|
return {
|
|
17706
17824
|
type: "response-error",
|
package/dist/esm/worker.mjs
CHANGED
|
@@ -121,6 +121,8 @@ var deserializeError = (error) => {
|
|
|
121
121
|
return new Error(error.errorMessage);
|
|
122
122
|
case "NotReadableError":
|
|
123
123
|
return new Error(error.errorMessage);
|
|
124
|
+
case "TypeError":
|
|
125
|
+
return new TypeError(error.errorMessage);
|
|
124
126
|
default:
|
|
125
127
|
throw new Error(`Unknown error name: ${error}`);
|
|
126
128
|
}
|
|
@@ -201,7 +203,7 @@ var convertToWorkerPayload = (payload) => {
|
|
|
201
203
|
postM3uAssociatedPlaylistsSelection: Boolean(selectM3uAssociatedPlaylists),
|
|
202
204
|
postOnAudioTrack: Boolean(onAudioTrack),
|
|
203
205
|
postOnVideoTrack: Boolean(onVideoTrack),
|
|
204
|
-
src
|
|
206
|
+
src: src instanceof URL ? src.toString() : src
|
|
205
207
|
};
|
|
206
208
|
};
|
|
207
209
|
var post = (worker, payload) => {
|
|
@@ -241,6 +243,14 @@ var parseMediaOnWorkerImplementation = async ({ controller, reader, ...params },
|
|
|
241
243
|
seekingHintPromises.push(prom);
|
|
242
244
|
return prom.promise;
|
|
243
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
|
+
});
|
|
244
254
|
const callbacks = {};
|
|
245
255
|
function onMessage(message) {
|
|
246
256
|
const data = message.data;
|
|
@@ -460,6 +470,15 @@ var parseMediaOnWorkerImplementation = async ({ controller, reader, ...params },
|
|
|
460
470
|
firstPromise.resolve(data.payload);
|
|
461
471
|
return;
|
|
462
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
|
+
}
|
|
463
482
|
throw new Error(`Unknown response type: ${JSON.stringify(data)}`);
|
|
464
483
|
}
|
|
465
484
|
worker.addEventListener("message", onMessage);
|
|
@@ -487,6 +506,17 @@ var parseMediaOnWebWorker = (params) => {
|
|
|
487
506
|
if (typeof Worker === "undefined") {
|
|
488
507
|
throw new Error('"Worker" is not available. Cannot call parseMediaOnWebWorker()');
|
|
489
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
|
+
}
|
|
490
520
|
const worker = new Worker(new URL("./worker-web-entry.mjs", import.meta.url));
|
|
491
521
|
return parseMediaOnWorkerImplementation(params, worker, "parseMediaOnWebWorker");
|
|
492
522
|
};
|
package/dist/get-seeking-byte.js
CHANGED
|
@@ -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
|
-
|
|
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.
|