@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.
- 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/base-media-box.d.ts +3 -2
- package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.d.ts +3 -1
- package/dist/containers/iso-base-media/collect-sample-positions-from-moof-boxes.js +2 -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/find-track-to-seek.js +2 -0
- package/dist/containers/iso-base-media/get-keyframes.js +1 -0
- package/dist/containers/iso-base-media/get-sample-positions-from-track.d.ts +3 -1
- package/dist/containers/iso-base-media/get-sample-positions-from-track.js +2 -1
- package/dist/containers/iso-base-media/get-seeking-byte-from-fragmented-mp4.js +4 -1
- package/dist/containers/iso-base-media/get-seeking-byte.js +3 -1
- package/dist/containers/iso-base-media/moov/mvhd.d.ts +30 -0
- package/dist/containers/iso-base-media/moov/mvhd.js +65 -0
- package/dist/containers/iso-base-media/moov/trex.d.ts +16 -0
- package/dist/containers/iso-base-media/moov/trex.js +27 -0
- package/dist/containers/iso-base-media/process-box.js +10 -1
- package/dist/containers/iso-base-media/tkhd.d.ts +1 -1
- package/dist/containers/iso-base-media/traversal.d.ts +4 -1
- package/dist/containers/iso-base-media/traversal.js +18 -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 +327 -156
- package/dist/esm/server-worker.mjs +17 -0
- package/dist/esm/worker-server-entry.mjs +341 -155
- package/dist/esm/worker-web-entry.mjs +341 -155
- package/dist/esm/worker.mjs +28 -0
- package/dist/get-duration.js +1 -0
- package/dist/get-seeking-byte.js +13 -2
- package/dist/index.cjs +54 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/internal-parse-media.js +25 -0
- package/dist/iterator/buffer-iterator.d.ts +1 -1
- package/dist/iterator/buffer-manager.d.ts +1 -1
- package/dist/iterator/buffer-manager.js +19 -5
- package/dist/parse-media-on-worker-entry.js +17 -0
- package/dist/samples-from-moof.d.ts +3 -1
- package/dist/samples-from-moof.js +15 -12
- package/dist/state/iso-base-media/cached-sample-positions.js +1 -0
- package/dist/state/iso-base-media/lazy-mfra-load.js +1 -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/worker-types.d.ts +13 -2
- package/package.json +3 -3
|
@@ -23,7 +23,11 @@ const getSeekingByteForAac = ({ time, seekingHints, }) => {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
if (bestAudioSample) {
|
|
26
|
-
return {
|
|
26
|
+
return {
|
|
27
|
+
type: 'do-seek',
|
|
28
|
+
byte: bestAudioSample.offset,
|
|
29
|
+
timeInSeconds: bestAudioSample.timeInSeconds,
|
|
30
|
+
};
|
|
27
31
|
}
|
|
28
32
|
return { type: 'valid-but-must-wait' };
|
|
29
33
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { AudioSampleOffset } from '../../state/audio-sample-map';
|
|
1
2
|
import type { FlacSeekingHints } from './seeking-hints';
|
|
2
3
|
export declare const getSeekingByteForFlac: ({ time, seekingHints, }: {
|
|
3
4
|
time: number;
|
|
4
5
|
seekingHints: FlacSeekingHints;
|
|
5
|
-
}) =>
|
|
6
|
+
}) => AudioSampleOffset | null;
|
|
@@ -7,7 +7,8 @@ import type { HdlrBox } from './meta/hdlr';
|
|
|
7
7
|
import type { IlstBox } from './meta/ilst';
|
|
8
8
|
import type { TfraBox } from './mfra/tfra';
|
|
9
9
|
import type { MoovBox } from './moov/moov';
|
|
10
|
-
import type { MvhdBox } from './mvhd';
|
|
10
|
+
import type { MvhdBox } from './moov/mvhd';
|
|
11
|
+
import type { TrexBox } from './moov/trex';
|
|
11
12
|
import type { Av1CBox } from './stsd/av1c';
|
|
12
13
|
import type { AvccBox } from './stsd/avcc';
|
|
13
14
|
import type { ColorParameterBox } from './stsd/colr';
|
|
@@ -35,4 +36,4 @@ export interface RegularBox extends BaseBox {
|
|
|
35
36
|
offset: number;
|
|
36
37
|
type: 'regular-box';
|
|
37
38
|
}
|
|
38
|
-
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | ElstBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox | TfraBox;
|
|
39
|
+
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | ElstBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox | TfraBox | TrexBox;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { MoofBox } from '../../state/iso-base-media/precomputed-moof';
|
|
2
|
+
import type { TrexBox } from './moov/trex';
|
|
2
3
|
import type { TkhdBox } from './tkhd';
|
|
3
|
-
export declare const collectSamplePositionsFromMoofBoxes: ({ moofBoxes, tkhdBox, isComplete, }: {
|
|
4
|
+
export declare const collectSamplePositionsFromMoofBoxes: ({ moofBoxes, tkhdBox, isComplete, trexBoxes, }: {
|
|
4
5
|
moofBoxes: MoofBox[];
|
|
5
6
|
tkhdBox: TkhdBox;
|
|
6
7
|
isComplete: boolean;
|
|
8
|
+
trexBoxes: TrexBox[];
|
|
7
9
|
}) => {
|
|
8
10
|
samplePositions: {
|
|
9
11
|
isLastFragment: boolean;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.collectSamplePositionsFromMoofBoxes = void 0;
|
|
4
4
|
const samples_from_moof_1 = require("../../samples-from-moof");
|
|
5
|
-
const collectSamplePositionsFromMoofBoxes = ({ moofBoxes, tkhdBox, isComplete, }) => {
|
|
5
|
+
const collectSamplePositionsFromMoofBoxes = ({ moofBoxes, tkhdBox, isComplete, trexBoxes, }) => {
|
|
6
6
|
const samplePositions = moofBoxes.map((m, index) => {
|
|
7
7
|
const isLastFragment = index === moofBoxes.length - 1 && isComplete;
|
|
8
8
|
return {
|
|
@@ -10,6 +10,7 @@ const collectSamplePositionsFromMoofBoxes = ({ moofBoxes, tkhdBox, isComplete, }
|
|
|
10
10
|
samples: (0, samples_from_moof_1.getSamplesFromMoof)({
|
|
11
11
|
moofBox: m,
|
|
12
12
|
trackId: tkhdBox.trackId,
|
|
13
|
+
trexBoxes,
|
|
13
14
|
}),
|
|
14
15
|
};
|
|
15
16
|
});
|
|
@@ -28,6 +28,6 @@ const findKeyframeBeforeTime = ({ samplePositions, time, timescale, mediaSection
|
|
|
28
28
|
log_1.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);
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
31
|
-
return videoSample
|
|
31
|
+
return videoSample;
|
|
32
32
|
};
|
|
33
33
|
exports.findKeyframeBeforeTime = findKeyframeBeforeTime;
|
|
@@ -22,6 +22,7 @@ const findAnyTrackWithSamplePositions = (allTracks, struc) => {
|
|
|
22
22
|
moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
|
|
23
23
|
tfraBoxes: (0, traversal_1.getTfraBoxes)(struc.boxes),
|
|
24
24
|
}),
|
|
25
|
+
trexBoxes: (0, traversal_1.getTrexBoxes)(moov),
|
|
25
26
|
});
|
|
26
27
|
if (samplePositions.length === 0) {
|
|
27
28
|
continue;
|
|
@@ -53,6 +54,7 @@ const findTrackToSeek = (allTracks, structure) => {
|
|
|
53
54
|
moofBoxes: (0, traversal_1.getMoofBoxes)(struc.boxes),
|
|
54
55
|
tfraBoxes: (0, traversal_1.getTfraBoxes)(struc.boxes),
|
|
55
56
|
}),
|
|
57
|
+
trexBoxes: (0, traversal_1.getTrexBoxes)(moov),
|
|
56
58
|
});
|
|
57
59
|
if (samplePositions.length === 0) {
|
|
58
60
|
return (0, exports.findAnyTrackWithSamplePositions)(allTracks, struc);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { SamplePosition } from '../../get-sample-positions';
|
|
2
2
|
import type { MoofBox } from '../../state/iso-base-media/precomputed-moof';
|
|
3
|
+
import type { TrexBox } from './moov/trex';
|
|
3
4
|
import type { TrakBox } from './trak/trak';
|
|
4
|
-
export declare const getSamplePositionsFromTrack: ({ trakBox, moofBoxes, moofComplete, }: {
|
|
5
|
+
export declare const getSamplePositionsFromTrack: ({ trakBox, moofBoxes, moofComplete, trexBoxes, }: {
|
|
5
6
|
trakBox: TrakBox;
|
|
6
7
|
moofBoxes: MoofBox[];
|
|
7
8
|
moofComplete: boolean;
|
|
9
|
+
trexBoxes: TrexBox[];
|
|
8
10
|
}) => {
|
|
9
11
|
samplePositions: SamplePosition[];
|
|
10
12
|
isComplete: boolean;
|
|
@@ -4,7 +4,7 @@ exports.getSamplePositionsFromTrack = void 0;
|
|
|
4
4
|
const collect_sample_positions_from_moof_boxes_1 = require("./collect-sample-positions-from-moof-boxes");
|
|
5
5
|
const collect_sample_positions_from_trak_1 = require("./collect-sample-positions-from-trak");
|
|
6
6
|
const traversal_1 = require("./traversal");
|
|
7
|
-
const getSamplePositionsFromTrack = ({ trakBox, moofBoxes, moofComplete, }) => {
|
|
7
|
+
const getSamplePositionsFromTrack = ({ trakBox, moofBoxes, moofComplete, trexBoxes, }) => {
|
|
8
8
|
const tkhdBox = (0, traversal_1.getTkhdBox)(trakBox);
|
|
9
9
|
if (!tkhdBox) {
|
|
10
10
|
throw new Error('Expected tkhd box in trak box');
|
|
@@ -14,6 +14,7 @@ const getSamplePositionsFromTrack = ({ trakBox, moofBoxes, moofComplete, }) => {
|
|
|
14
14
|
moofBoxes,
|
|
15
15
|
tkhdBox,
|
|
16
16
|
isComplete: moofComplete,
|
|
17
|
+
trexBoxes,
|
|
17
18
|
});
|
|
18
19
|
return {
|
|
19
20
|
samplePositions: samplePositions.map((s) => s.samples).flat(1),
|
|
@@ -41,6 +41,7 @@ const getSeekingByteFromFragmentedMp4 = async ({ info, time, logLevel, currentPo
|
|
|
41
41
|
moofBoxes: info.moofBoxes,
|
|
42
42
|
tkhdBox,
|
|
43
43
|
isComplete,
|
|
44
|
+
trexBoxes: (0, traversal_1.getTrexBoxes)(moov),
|
|
44
45
|
});
|
|
45
46
|
log_1.Log.trace(logLevel, 'Fragmented MP4 - Checking if we have seeking info for this time range');
|
|
46
47
|
for (const positions of samplePositionsArray) {
|
|
@@ -59,7 +60,9 @@ const getSeekingByteFromFragmentedMp4 = async ({ info, time, logLevel, currentPo
|
|
|
59
60
|
if (kf) {
|
|
60
61
|
return {
|
|
61
62
|
type: 'do-seek',
|
|
62
|
-
byte: kf,
|
|
63
|
+
byte: kf.offset,
|
|
64
|
+
timeInSeconds: Math.min(kf.decodingTimestamp, kf.timestamp) /
|
|
65
|
+
firstTrack.originalTimescale,
|
|
63
66
|
};
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -58,7 +58,9 @@ const getSeekingByteFromIsoBaseMedia = ({ info, time, logLevel, currentPosition,
|
|
|
58
58
|
if (keyframe) {
|
|
59
59
|
return Promise.resolve({
|
|
60
60
|
type: 'do-seek',
|
|
61
|
-
byte: keyframe,
|
|
61
|
+
byte: keyframe.offset,
|
|
62
|
+
timeInSeconds: Math.min(keyframe.decodingTimestamp, keyframe.timestamp) /
|
|
63
|
+
track.originalTimescale,
|
|
62
64
|
});
|
|
63
65
|
}
|
|
64
66
|
return Promise.resolve({
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../../iterator/buffer-iterator';
|
|
2
|
+
import type { BaseBox } from '../base-type';
|
|
3
|
+
export type ThreeDMatrix = [
|
|
4
|
+
number,
|
|
5
|
+
number,
|
|
6
|
+
number,
|
|
7
|
+
number,
|
|
8
|
+
number,
|
|
9
|
+
number,
|
|
10
|
+
number,
|
|
11
|
+
number,
|
|
12
|
+
number
|
|
13
|
+
];
|
|
14
|
+
export interface MvhdBox extends BaseBox {
|
|
15
|
+
durationInUnits: number;
|
|
16
|
+
durationInSeconds: number;
|
|
17
|
+
creationTime: number | null;
|
|
18
|
+
modificationTime: number | null;
|
|
19
|
+
timeScale: number;
|
|
20
|
+
rate: number;
|
|
21
|
+
volume: number;
|
|
22
|
+
matrix: ThreeDMatrix;
|
|
23
|
+
nextTrackId: number;
|
|
24
|
+
type: 'mvhd-box';
|
|
25
|
+
}
|
|
26
|
+
export declare const parseMvhd: ({ iterator, offset, size, }: {
|
|
27
|
+
iterator: BufferIterator;
|
|
28
|
+
offset: number;
|
|
29
|
+
size: number;
|
|
30
|
+
}) => MvhdBox;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMvhd = void 0;
|
|
4
|
+
const buffer_iterator_1 = require("../../../iterator/buffer-iterator");
|
|
5
|
+
const to_date_1 = require("../to-date");
|
|
6
|
+
const parseMvhd = ({ iterator, offset, size, }) => {
|
|
7
|
+
const version = iterator.getUint8();
|
|
8
|
+
// Flags, we discard them
|
|
9
|
+
iterator.discard(3);
|
|
10
|
+
const creationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
11
|
+
const modificationTime = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
12
|
+
const timeScale = iterator.getUint32();
|
|
13
|
+
const durationInUnits = version === 1 ? iterator.getUint64() : iterator.getUint32();
|
|
14
|
+
const durationInSeconds = Number(durationInUnits) / timeScale;
|
|
15
|
+
const rateArray = iterator.getSlice(4);
|
|
16
|
+
const rateView = (0, buffer_iterator_1.getArrayBufferIterator)(rateArray, rateArray.length);
|
|
17
|
+
const rate = rateView.getInt8() * 10 +
|
|
18
|
+
rateView.getInt8() +
|
|
19
|
+
rateView.getInt8() * 0.1 +
|
|
20
|
+
rateView.getInt8() * 0.01;
|
|
21
|
+
const volumeArray = iterator.getSlice(2);
|
|
22
|
+
const volumeView = (0, buffer_iterator_1.getArrayBufferIterator)(volumeArray, volumeArray.length);
|
|
23
|
+
const volume = volumeView.getInt8() + volumeView.getInt8() * 0.1;
|
|
24
|
+
// reserved 16bit
|
|
25
|
+
iterator.discard(2);
|
|
26
|
+
// reserved 32bit x2
|
|
27
|
+
iterator.discard(4);
|
|
28
|
+
iterator.discard(4);
|
|
29
|
+
// matrix
|
|
30
|
+
const matrix = [
|
|
31
|
+
iterator.getFixedPointSigned1616Number(),
|
|
32
|
+
iterator.getFixedPointSigned1616Number(),
|
|
33
|
+
iterator.getFixedPointSigned230Number(),
|
|
34
|
+
iterator.getFixedPointSigned1616Number(),
|
|
35
|
+
iterator.getFixedPointSigned1616Number(),
|
|
36
|
+
iterator.getFixedPointSigned230Number(),
|
|
37
|
+
iterator.getFixedPointSigned1616Number(),
|
|
38
|
+
iterator.getFixedPointSigned1616Number(),
|
|
39
|
+
iterator.getFixedPointSigned230Number(),
|
|
40
|
+
];
|
|
41
|
+
// pre-defined
|
|
42
|
+
iterator.discard(4 * 6);
|
|
43
|
+
// next track id
|
|
44
|
+
const nextTrackId = iterator.getUint32();
|
|
45
|
+
volumeView.destroy();
|
|
46
|
+
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
47
|
+
if (bytesRemaining !== 0) {
|
|
48
|
+
throw new Error('expected 0 bytes ' + bytesRemaining);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
creationTime: (0, to_date_1.toUnixTimestamp)(Number(creationTime)),
|
|
52
|
+
modificationTime: (0, to_date_1.toUnixTimestamp)(Number(modificationTime)),
|
|
53
|
+
timeScale,
|
|
54
|
+
durationInUnits: Number(durationInUnits),
|
|
55
|
+
durationInSeconds,
|
|
56
|
+
rate,
|
|
57
|
+
volume,
|
|
58
|
+
matrix: matrix,
|
|
59
|
+
nextTrackId,
|
|
60
|
+
type: 'mvhd-box',
|
|
61
|
+
boxSize: size,
|
|
62
|
+
offset,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
exports.parseMvhd = parseMvhd;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../../iterator/buffer-iterator';
|
|
2
|
+
import type { BaseBox } from '../base-type';
|
|
3
|
+
export interface TrexBox extends BaseBox {
|
|
4
|
+
type: 'trex-box';
|
|
5
|
+
version: number;
|
|
6
|
+
trackId: number;
|
|
7
|
+
defaultSampleDescriptionIndex: number;
|
|
8
|
+
defaultSampleDuration: number;
|
|
9
|
+
defaultSampleSize: number;
|
|
10
|
+
defaultSampleFlags: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const parseTrex: ({ iterator, offset, size, }: {
|
|
13
|
+
iterator: BufferIterator;
|
|
14
|
+
offset: number;
|
|
15
|
+
size: number;
|
|
16
|
+
}) => TrexBox;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTrex = void 0;
|
|
4
|
+
const parseTrex = ({ iterator, offset, size, }) => {
|
|
5
|
+
const box = iterator.startBox(size - 8);
|
|
6
|
+
const version = iterator.getUint8();
|
|
7
|
+
// Flags, we discard them
|
|
8
|
+
iterator.discard(3);
|
|
9
|
+
const trackId = iterator.getUint32();
|
|
10
|
+
const defaultSampleDescriptionIndex = iterator.getUint32();
|
|
11
|
+
const defaultSampleDuration = iterator.getUint32();
|
|
12
|
+
const defaultSampleSize = iterator.getUint32();
|
|
13
|
+
const defaultSampleFlags = iterator.getUint32();
|
|
14
|
+
box.expectNoMoreBytes();
|
|
15
|
+
return {
|
|
16
|
+
type: 'trex-box',
|
|
17
|
+
boxSize: size,
|
|
18
|
+
offset,
|
|
19
|
+
trackId,
|
|
20
|
+
version,
|
|
21
|
+
defaultSampleDescriptionIndex,
|
|
22
|
+
defaultSampleDuration,
|
|
23
|
+
defaultSampleSize,
|
|
24
|
+
defaultSampleFlags,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
exports.parseTrex = parseTrex;
|
|
@@ -15,7 +15,8 @@ const hdlr_1 = require("./meta/hdlr");
|
|
|
15
15
|
const ilst_1 = require("./meta/ilst");
|
|
16
16
|
const tfra_1 = require("./mfra/tfra");
|
|
17
17
|
const moov_1 = require("./moov/moov");
|
|
18
|
-
const mvhd_1 = require("./mvhd");
|
|
18
|
+
const mvhd_1 = require("./moov/mvhd");
|
|
19
|
+
const trex_1 = require("./moov/trex");
|
|
19
20
|
const av1c_1 = require("./stsd/av1c");
|
|
20
21
|
const avcc_1 = require("./stsd/avcc");
|
|
21
22
|
const colr_1 = require("./stsd/colr");
|
|
@@ -390,6 +391,12 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
390
391
|
}),
|
|
391
392
|
};
|
|
392
393
|
}
|
|
394
|
+
if (boxType === 'trex') {
|
|
395
|
+
return {
|
|
396
|
+
type: 'box',
|
|
397
|
+
box: await (0, trex_1.parseTrex)({ iterator, offset: fileOffset, size: boxSize }),
|
|
398
|
+
};
|
|
399
|
+
}
|
|
393
400
|
if (boxType === 'moof') {
|
|
394
401
|
await ((_b = onlyIfMoovAtomExpected === null || onlyIfMoovAtomExpected === void 0 ? void 0 : onlyIfMoovAtomExpected.isoState) === null || _b === void 0 ? void 0 : _b.mfra.triggerLoad());
|
|
395
402
|
}
|
|
@@ -404,6 +411,7 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
404
411
|
boxType === 'traf' ||
|
|
405
412
|
boxType === 'mfra' ||
|
|
406
413
|
boxType === 'edts' ||
|
|
414
|
+
boxType === 'mvex' ||
|
|
407
415
|
boxType === 'stsb') {
|
|
408
416
|
const children = await (0, get_children_1.getIsoBaseMediaChildren)({
|
|
409
417
|
iterator,
|
|
@@ -424,6 +432,7 @@ const processBox = async ({ iterator, logLevel, onlyIfMoovAtomExpected, onlyIfMd
|
|
|
424
432
|
};
|
|
425
433
|
}
|
|
426
434
|
iterator.discard(boxSize - 8);
|
|
435
|
+
log_1.Log.verbose(logLevel, 'Unknown ISO Base Media Box:', boxType);
|
|
427
436
|
return {
|
|
428
437
|
type: 'box',
|
|
429
438
|
box: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BufferIterator } from '../../iterator/buffer-iterator';
|
|
2
2
|
import type { BaseBox } from './base-type';
|
|
3
|
-
import type { ThreeDMatrix } from './mvhd';
|
|
3
|
+
import type { ThreeDMatrix } from './moov/mvhd';
|
|
4
4
|
export interface TkhdBox extends BaseBox {
|
|
5
5
|
type: 'tkhd-box';
|
|
6
6
|
alternateGroup: number;
|
|
@@ -8,7 +8,8 @@ import type { FtypBox } from './ftyp';
|
|
|
8
8
|
import type { MdhdBox } from './mdhd';
|
|
9
9
|
import type { TfraBox } from './mfra/tfra';
|
|
10
10
|
import type { MoovBox } from './moov/moov';
|
|
11
|
-
import type { MvhdBox } from './mvhd';
|
|
11
|
+
import type { MvhdBox } from './moov/mvhd';
|
|
12
|
+
import type { TrexBox } from './moov/trex';
|
|
12
13
|
import type { CttsBox } from './stsd/ctts';
|
|
13
14
|
import type { StcoBox } from './stsd/stco';
|
|
14
15
|
import type { StscBox } from './stsd/stsc';
|
|
@@ -47,6 +48,8 @@ export declare const getStssBox: (trakBox: TrakBox) => StssBox | null;
|
|
|
47
48
|
export declare const getTfdtBox: (segment: IsoBaseMediaBox) => TfdtBox | null;
|
|
48
49
|
export declare const getTfhdBox: (segment: IsoBaseMediaBox) => TfhdBox | null;
|
|
49
50
|
export declare const getTrunBoxes: (segment: IsoBaseMediaBox) => TrunBox[];
|
|
51
|
+
export declare const getMvexBox: (moovAtom: MoovBox) => RegularBox | null;
|
|
52
|
+
export declare const getTrexBoxes: (moovAtom: MoovBox) => TrexBox[];
|
|
50
53
|
export declare const getTfraBoxesFromMfraBoxChildren: (mfraBoxChildren: IsoBaseMediaBox[]) => TfraBox[];
|
|
51
54
|
export declare const getTfraBoxes: (structure: IsoBaseMediaBox[]) => TfraBox[];
|
|
52
55
|
export declare const getTrakBoxByTrackId: (moovBox: MoovBox, trackId: number) => TrakBox | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getElstBox = exports.getTrakBoxByTrackId = exports.getTfraBoxes = exports.getTfraBoxesFromMfraBoxChildren = exports.getTrunBoxes = exports.getTfhdBox = exports.getTfdtBox = exports.getStssBox = exports.getStscBox = exports.getStszBox = exports.getCttsBox = exports.getSttsBox = exports.getStcoBox = exports.getVideoDescriptors = exports.getStsdBox = exports.getStblBox = exports.getMdhdBox = exports.getMdiaBox = exports.getTkhdBox = exports.getTraks = exports.getMvhdBox = exports.getMoofBoxes = exports.getMoovBoxFromState = exports.getMoovFromFromIsoStructure = exports.getFtypBox = void 0;
|
|
3
|
+
exports.getElstBox = exports.getTrakBoxByTrackId = exports.getTfraBoxes = exports.getTfraBoxesFromMfraBoxChildren = exports.getTrexBoxes = exports.getMvexBox = exports.getTrunBoxes = exports.getTfhdBox = exports.getTfdtBox = exports.getStssBox = exports.getStscBox = exports.getStszBox = exports.getCttsBox = exports.getSttsBox = exports.getStcoBox = exports.getVideoDescriptors = exports.getStsdBox = exports.getStblBox = exports.getMdhdBox = exports.getMdiaBox = exports.getTkhdBox = exports.getTraks = exports.getMvhdBox = exports.getMoofBoxes = exports.getMoovBoxFromState = exports.getMoovFromFromIsoStructure = exports.getFtypBox = void 0;
|
|
4
4
|
const precomputed_moof_1 = require("../../state/iso-base-media/precomputed-moof");
|
|
5
5
|
const getFtypBox = (segments) => {
|
|
6
6
|
const ftypBox = segments.find((s) => s.type === 'ftyp-box');
|
|
@@ -198,6 +198,23 @@ const getTrunBoxes = (segment) => {
|
|
|
198
198
|
return trunBoxes;
|
|
199
199
|
};
|
|
200
200
|
exports.getTrunBoxes = getTrunBoxes;
|
|
201
|
+
const getMvexBox = (moovAtom) => {
|
|
202
|
+
const mvexBox = moovAtom.children.find((s) => s.type === 'regular-box' && s.boxType === 'mvex');
|
|
203
|
+
if (!mvexBox || mvexBox.type !== 'regular-box') {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
return mvexBox;
|
|
207
|
+
};
|
|
208
|
+
exports.getMvexBox = getMvexBox;
|
|
209
|
+
const getTrexBoxes = (moovAtom) => {
|
|
210
|
+
const mvexBox = (0, exports.getMvexBox)(moovAtom);
|
|
211
|
+
if (!mvexBox) {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
const trexBoxes = mvexBox.children.filter((c) => c.type === 'trex-box');
|
|
215
|
+
return trexBoxes;
|
|
216
|
+
};
|
|
217
|
+
exports.getTrexBoxes = getTrexBoxes;
|
|
201
218
|
const getTfraBoxesFromMfraBoxChildren = (mfraBoxChildren) => {
|
|
202
219
|
const tfraBoxes = mfraBoxChildren.filter((b) => b.type === 'tfra-box');
|
|
203
220
|
return tfraBoxes;
|
|
@@ -27,6 +27,8 @@ const getSeekingByteForM3u8 = ({ time, currentPosition, m3uState, logLevel, }) =
|
|
|
27
27
|
return {
|
|
28
28
|
type: 'do-seek',
|
|
29
29
|
byte: currentPosition,
|
|
30
|
+
// TODO: This will be imperfect when seeking in playMedia()
|
|
31
|
+
timeInSeconds: time,
|
|
30
32
|
};
|
|
31
33
|
};
|
|
32
34
|
exports.getSeekingByteForM3u8 = getSeekingByteForM3u8;
|
|
@@ -41,9 +41,12 @@ const getSeekingByteForMp3 = ({ time, info, }) => {
|
|
|
41
41
|
type: 'valid-but-must-wait',
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
const byte = Math.max(...candidates);
|
|
45
|
+
const timeInSeconds = byte === (bestAudioSample === null || bestAudioSample === void 0 ? void 0 : bestAudioSample.offset) ? bestAudioSample.timeInSeconds : time;
|
|
44
46
|
return {
|
|
45
47
|
type: 'do-seek',
|
|
46
|
-
byte
|
|
48
|
+
byte,
|
|
49
|
+
timeInSeconds,
|
|
47
50
|
};
|
|
48
51
|
};
|
|
49
52
|
exports.getSeekingByteForMp3 = getSeekingByteForMp3;
|
|
@@ -22,6 +22,7 @@ const getSeekingByteForRiff = async ({ info, time, riffState, avcState, }) => {
|
|
|
22
22
|
return {
|
|
23
23
|
type: 'do-seek',
|
|
24
24
|
byte: lastKeyframe.positionInBytes,
|
|
25
|
+
timeInSeconds: Math.min(lastKeyframe.decodingTimeInSeconds, lastKeyframe.presentationTimeInSeconds),
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
if (idx1Entries.videoTrackIndex === null) {
|
|
@@ -55,6 +56,8 @@ const getSeekingByteForRiff = async ({ info, time, riffState, avcState, }) => {
|
|
|
55
56
|
return {
|
|
56
57
|
type: 'do-seek',
|
|
57
58
|
byte: bestEntry.offset + info.moviOffset - 4,
|
|
59
|
+
timeInSeconds: bestEntry.sampleCounts[idx1Entries.videoTrackIndex] /
|
|
60
|
+
info.samplesPerSecond,
|
|
58
61
|
};
|
|
59
62
|
};
|
|
60
63
|
exports.getSeekingByteForRiff = getSeekingByteForRiff;
|
|
@@ -16,10 +16,11 @@ const parseList = ({ state, }) => {
|
|
|
16
16
|
// Padding
|
|
17
17
|
// https://discord.com/channels/809501355504959528/1308803317480292482/1343979547246333983
|
|
18
18
|
// Indie_Hacker_Podcast (2).wav
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const byte = iterator.getUint8();
|
|
20
|
+
if (byte === 0) {
|
|
21
|
+
continue;
|
|
22
22
|
}
|
|
23
|
+
iterator.counter.decrement(1);
|
|
23
24
|
const key = iterator.getByteString(4, false);
|
|
24
25
|
const size = iterator.getUint32Le();
|
|
25
26
|
const value = iterator.getByteString(size, true);
|
|
@@ -19,7 +19,6 @@ const findBiggestCueBeforeTime = ({ cues, time, track, }) => {
|
|
|
19
19
|
return biggestCueBeforeTime;
|
|
20
20
|
};
|
|
21
21
|
const findKeyframeBeforeTime = ({ keyframes, time, }) => {
|
|
22
|
-
var _a;
|
|
23
22
|
let keyframeBeforeTime;
|
|
24
23
|
for (const keyframe of keyframes) {
|
|
25
24
|
if (keyframe.decodingTimeInSeconds < time &&
|
|
@@ -29,7 +28,7 @@ const findKeyframeBeforeTime = ({ keyframes, time, }) => {
|
|
|
29
28
|
keyframeBeforeTime = keyframe;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
return
|
|
31
|
+
return keyframeBeforeTime !== null && keyframeBeforeTime !== void 0 ? keyframeBeforeTime : null;
|
|
33
32
|
};
|
|
34
33
|
const getByteFromCues = ({ cuesResponse, time, info, logLevel, }) => {
|
|
35
34
|
if (!cuesResponse) {
|
|
@@ -46,10 +45,13 @@ const getByteFromCues = ({ cuesResponse, time, info, logLevel, }) => {
|
|
|
46
45
|
if (!biggestCueBeforeTime) {
|
|
47
46
|
return null;
|
|
48
47
|
}
|
|
49
|
-
return
|
|
48
|
+
return {
|
|
49
|
+
byte: biggestCueBeforeTime.clusterPositionInSegment + segmentOffset,
|
|
50
|
+
timeInSeconds: toSeconds(biggestCueBeforeTime.timeInTimescale, info.track),
|
|
51
|
+
};
|
|
50
52
|
};
|
|
51
53
|
const getSeekingByteFromMatroska = async ({ time, webmState, info, logLevel, mediaSection, }) => {
|
|
52
|
-
var _a, _b, _c;
|
|
54
|
+
var _a, _b, _c, _d, _e;
|
|
53
55
|
if (!info.track) {
|
|
54
56
|
log_1.Log.trace(logLevel, 'No video track found, cannot seek yet');
|
|
55
57
|
return {
|
|
@@ -74,8 +76,8 @@ const getSeekingByteFromMatroska = async ({ time, webmState, info, logLevel, med
|
|
|
74
76
|
// Optimization possibility for later:
|
|
75
77
|
// Don't seek back, if the last seen time is smaller than the time we want to seek to
|
|
76
78
|
const seekPossibilities = [
|
|
77
|
-
byteFromCues,
|
|
78
|
-
byteFromObservedKeyframe,
|
|
79
|
+
(_d = byteFromCues === null || byteFromCues === void 0 ? void 0 : byteFromCues.byte) !== null && _d !== void 0 ? _d : null,
|
|
80
|
+
(_e = byteFromObservedKeyframe === null || byteFromObservedKeyframe === void 0 ? void 0 : byteFromObservedKeyframe.positionInBytes) !== null && _e !== void 0 ? _e : null,
|
|
79
81
|
byteFromFirstMediaSection,
|
|
80
82
|
].filter((n) => n !== null);
|
|
81
83
|
const byteToSeekTo = seekPossibilities.length === 0 ? null : Math.max(...seekPossibilities);
|
|
@@ -92,9 +94,22 @@ const getSeekingByteFromMatroska = async ({ time, webmState, info, logLevel, med
|
|
|
92
94
|
start: byteToSeekTo,
|
|
93
95
|
size: 1,
|
|
94
96
|
});
|
|
97
|
+
const timeInSeconds = (() => {
|
|
98
|
+
if (byteToSeekTo === (byteFromObservedKeyframe === null || byteFromObservedKeyframe === void 0 ? void 0 : byteFromObservedKeyframe.positionInBytes)) {
|
|
99
|
+
return Math.min(byteFromObservedKeyframe.decodingTimeInSeconds, byteFromObservedKeyframe.presentationTimeInSeconds);
|
|
100
|
+
}
|
|
101
|
+
if (byteToSeekTo === (byteFromCues === null || byteFromCues === void 0 ? void 0 : byteFromCues.byte)) {
|
|
102
|
+
return byteFromCues.timeInSeconds;
|
|
103
|
+
}
|
|
104
|
+
if (byteToSeekTo === byteFromFirstMediaSection) {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
throw new Error('Should not happen');
|
|
108
|
+
})();
|
|
95
109
|
return {
|
|
96
110
|
type: 'do-seek',
|
|
97
111
|
byte: byteToSeekTo,
|
|
112
|
+
timeInSeconds,
|
|
98
113
|
};
|
|
99
114
|
};
|
|
100
115
|
exports.getSeekingByteFromMatroska = getSeekingByteFromMatroska;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SeekingHints } from '../seeking-hints';
|
|
2
|
+
import type { SeekResolution } from '../work-on-seek-request';
|
|
2
3
|
import { MediaParserEmitter } from './emitter';
|
|
3
4
|
import type { PauseSignal } from './pause-signal';
|
|
4
5
|
import type { PerformedSeeksSignal } from './performed-seeks-stats';
|
|
@@ -8,6 +9,7 @@ export type MediaParserController = {
|
|
|
8
9
|
pause: PauseSignal['pause'];
|
|
9
10
|
resume: PauseSignal['resume'];
|
|
10
11
|
seek: SeekSignal['seek'];
|
|
12
|
+
simulateSeek: (seekInSeconds: number) => Promise<SeekResolution>;
|
|
11
13
|
addEventListener: MediaParserEmitter['addEventListener'];
|
|
12
14
|
removeEventListener: MediaParserEmitter['removeEventListener'];
|
|
13
15
|
getSeekingHints: () => Promise<SeekingHints | null>;
|
|
@@ -21,6 +23,7 @@ export type MediaParserController = {
|
|
|
21
23
|
markAsReadyToEmitEvents: () => void;
|
|
22
24
|
performedSeeksSignal: PerformedSeeksSignal;
|
|
23
25
|
attachSeekingHintResolution: (callback: () => Promise<SeekingHints | null>) => void;
|
|
26
|
+
attachSimulateSeekResolution: (callback: (seekInSeconds: number) => Promise<SeekResolution>) => void;
|
|
24
27
|
};
|
|
25
28
|
};
|
|
26
29
|
export declare const mediaParserController: () => MediaParserController;
|
|
@@ -23,18 +23,31 @@ const mediaParserController = () => {
|
|
|
23
23
|
await pauseSignal.waitUntilResume();
|
|
24
24
|
};
|
|
25
25
|
let seekingHintResolution = null;
|
|
26
|
+
let simulateSeekResolution = null;
|
|
26
27
|
const getSeekingHints = () => {
|
|
27
28
|
if (!seekingHintResolution) {
|
|
28
29
|
throw new Error('The mediaParserController() was not yet used in a parseMedia() call');
|
|
29
30
|
}
|
|
30
31
|
return seekingHintResolution();
|
|
31
32
|
};
|
|
33
|
+
const simulateSeek = (seekInSeconds) => {
|
|
34
|
+
if (!simulateSeekResolution) {
|
|
35
|
+
throw new Error('The mediaParserController() was not yet used in a parseMedia() call');
|
|
36
|
+
}
|
|
37
|
+
return simulateSeekResolution(seekInSeconds);
|
|
38
|
+
};
|
|
32
39
|
const attachSeekingHintResolution = (callback) => {
|
|
33
40
|
if (seekingHintResolution) {
|
|
34
41
|
throw new Error('The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.');
|
|
35
42
|
}
|
|
36
43
|
seekingHintResolution = callback;
|
|
37
44
|
};
|
|
45
|
+
const attachSimulateSeekResolution = (callback) => {
|
|
46
|
+
if (simulateSeekResolution) {
|
|
47
|
+
throw new Error('The mediaParserController() was used in multiple parseMedia() calls. Create a separate controller for each call.');
|
|
48
|
+
}
|
|
49
|
+
simulateSeekResolution = callback;
|
|
50
|
+
};
|
|
38
51
|
return {
|
|
39
52
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
53
|
abort: (reason) => {
|
|
@@ -42,6 +55,7 @@ const mediaParserController = () => {
|
|
|
42
55
|
emitter.dispatchAbort(reason);
|
|
43
56
|
},
|
|
44
57
|
seek: seekSignal.seek,
|
|
58
|
+
simulateSeek,
|
|
45
59
|
pause: pauseSignal.pause,
|
|
46
60
|
resume: pauseSignal.resume,
|
|
47
61
|
addEventListener: emitter.addEventListener,
|
|
@@ -54,6 +68,7 @@ const mediaParserController = () => {
|
|
|
54
68
|
markAsReadyToEmitEvents: emitter.markAsReady,
|
|
55
69
|
performedSeeksSignal,
|
|
56
70
|
attachSeekingHintResolution,
|
|
71
|
+
attachSimulateSeekResolution,
|
|
57
72
|
},
|
|
58
73
|
};
|
|
59
74
|
};
|