@remotion/media-parser 4.0.192 → 4.0.194
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/boxes.json +1 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds/esds.js +27 -0
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds.js +27 -0
- package/dist/boxes/iso-base-media/mdat/mdat.d.ts +12 -0
- package/dist/boxes/iso-base-media/mdat/mdat.js +13 -0
- package/dist/boxes/iso-base-media/process-box.js +67 -0
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -0
- package/dist/boxes/iso-base-media/stsd/samples.js +27 -8
- package/dist/boxes/iso-base-media/stsd/stco.d.ts +14 -0
- package/dist/boxes/iso-base-media/stsd/stco.js +30 -0
- package/dist/boxes/iso-base-media/stsd/stsc.d.ts +19 -0
- package/dist/boxes/iso-base-media/stsd/stsc.js +34 -0
- package/dist/boxes/iso-base-media/stsd/stsz.d.ts +15 -0
- package/dist/boxes/iso-base-media/stsd/stsz.js +32 -0
- package/dist/boxes/webm/parse-webm-header.js +3 -3
- package/dist/boxes/webm/segments/track-entry.d.ts +20 -0
- package/dist/boxes/webm/segments/track-entry.js +37 -2
- package/dist/boxes/webm/segments.d.ts +2 -2
- package/dist/boxes/webm/segments.js +12 -0
- package/dist/buffer-iterator.d.ts +3 -1
- package/dist/buffer-iterator.js +41 -8
- package/dist/from-node.js +12 -4
- package/dist/from-web.js +12 -4
- package/dist/get-audio-codec.d.ts +4 -0
- package/dist/get-audio-codec.js +106 -0
- package/dist/get-dimensions.js +6 -2
- package/dist/get-fps.d.ts +1 -0
- package/dist/get-fps.js +34 -1
- package/dist/get-sample-positions.d.ts +12 -0
- package/dist/get-sample-positions.js +25 -0
- package/dist/get-samples.d.ts +0 -0
- package/dist/get-samples.js +1 -0
- package/dist/get-tracks.d.ts +10 -0
- package/dist/get-tracks.js +66 -0
- package/dist/get-video-codec.js +3 -0
- package/dist/has-all-info.d.ts +1 -1
- package/dist/has-all-info.js +4 -0
- package/dist/options.d.ts +7 -3
- package/dist/parse-media.js +37 -9
- package/dist/parse-result.d.ts +3 -1
- package/dist/parse-video.d.ts +1 -0
- package/dist/parse-video.js +1 -0
- package/dist/reader.d.ts +5 -1
- package/dist/traversal.d.ts +19 -0
- package/dist/traversal.js +88 -0
- package/package.json +2 -2
- package/src/boxes/iso-base-media/esds/esds-descriptors.ts +104 -0
- package/src/boxes/iso-base-media/esds/esds.ts +49 -0
- package/src/boxes/iso-base-media/process-box.ts +75 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +35 -8
- package/src/boxes/webm/parse-webm-header.ts +3 -3
- package/src/boxes/webm/segments/track-entry.ts +66 -1
- package/src/boxes/webm/segments.ts +29 -1
- package/src/buffer-iterator.ts +54 -10
- package/src/from-node.ts +13 -6
- package/src/from-web.ts +14 -4
- package/src/get-audio-codec.ts +143 -0
- package/src/get-dimensions.ts +11 -4
- package/src/get-fps.ts +48 -0
- package/src/get-video-codec.ts +4 -0
- package/src/has-all-info.ts +14 -2
- package/src/options.ts +18 -3
- package/src/parse-media.ts +51 -10
- package/src/parse-result.ts +4 -1
- package/src/parse-video.ts +2 -0
- package/src/reader.ts +6 -2
- package/src/test/matroska.test.ts +6 -7
- package/src/test/parse-esds.test.ts +75 -0
- package/src/test/stream-local.test.ts +80 -3
- package/src/test/stsd.test.ts +52 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStsc = void 0;
|
|
4
|
+
const parseStsc = ({ iterator, offset, size, }) => {
|
|
5
|
+
const version = iterator.getUint8();
|
|
6
|
+
if (version !== 0) {
|
|
7
|
+
throw new Error(`Unsupported STSD version ${version}`);
|
|
8
|
+
}
|
|
9
|
+
const flags = iterator.getSlice(3);
|
|
10
|
+
const entryCount = iterator.getUint32();
|
|
11
|
+
const entries = [];
|
|
12
|
+
for (let i = 0; i < entryCount; i++) {
|
|
13
|
+
const firstChunk = iterator.getUint32();
|
|
14
|
+
const samplesPerChunk = iterator.getUint32();
|
|
15
|
+
const sampleDescriptionIndex = iterator.getUint32();
|
|
16
|
+
if (sampleDescriptionIndex !== 1) {
|
|
17
|
+
throw new Error(`Expected sampleDescriptionIndex to be 1, but got ${sampleDescriptionIndex}`);
|
|
18
|
+
}
|
|
19
|
+
entries.push({
|
|
20
|
+
firstChunk,
|
|
21
|
+
samplesPerChunk,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
type: 'stsc-box',
|
|
26
|
+
boxSize: size,
|
|
27
|
+
offset,
|
|
28
|
+
version,
|
|
29
|
+
flags: [...flags],
|
|
30
|
+
entryCount,
|
|
31
|
+
entries,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
exports.parseStsc = parseStsc;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../../buffer-iterator';
|
|
2
|
+
import type { BaseBox } from '../base-type';
|
|
3
|
+
export type StszBox = BaseBox & {
|
|
4
|
+
type: 'stsz-box';
|
|
5
|
+
version: number;
|
|
6
|
+
flags: number[];
|
|
7
|
+
sampleSize: number;
|
|
8
|
+
sampleCount: number;
|
|
9
|
+
samples: number[];
|
|
10
|
+
};
|
|
11
|
+
export declare const parseStsz: ({ iterator, offset, size, }: {
|
|
12
|
+
iterator: BufferIterator;
|
|
13
|
+
offset: number;
|
|
14
|
+
size: number;
|
|
15
|
+
}) => StszBox;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStsz = void 0;
|
|
4
|
+
const parseStsz = ({ iterator, offset, size, }) => {
|
|
5
|
+
const version = iterator.getUint8();
|
|
6
|
+
if (version !== 0) {
|
|
7
|
+
throw new Error(`Unsupported STSD version ${version}`);
|
|
8
|
+
}
|
|
9
|
+
const flags = iterator.getSlice(3);
|
|
10
|
+
const sampleSize = iterator.getUint32();
|
|
11
|
+
const sampleCount = iterator.getUint32();
|
|
12
|
+
const samples = [];
|
|
13
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
14
|
+
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
15
|
+
if (bytesRemaining < 4) {
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
samples.push(iterator.getUint32());
|
|
19
|
+
}
|
|
20
|
+
iterator.discard(size - (iterator.counter.getOffset() - offset));
|
|
21
|
+
return {
|
|
22
|
+
type: 'stsz-box',
|
|
23
|
+
boxSize: size,
|
|
24
|
+
offset,
|
|
25
|
+
version,
|
|
26
|
+
flags: [...flags],
|
|
27
|
+
sampleSize,
|
|
28
|
+
sampleCount,
|
|
29
|
+
samples,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
exports.parseStsz = parseStsz;
|
|
@@ -6,11 +6,11 @@ const segments_1 = require("./segments");
|
|
|
6
6
|
const parseWebm = (counter) => {
|
|
7
7
|
counter.discard(4);
|
|
8
8
|
const length = counter.getVint();
|
|
9
|
-
if (length !== 31) {
|
|
10
|
-
throw new Error(`Expected header length 31, got ${length}`);
|
|
9
|
+
if (length !== 31 && length !== 35) {
|
|
10
|
+
throw new Error(`Expected header length 31 or 25, got ${length}`);
|
|
11
11
|
}
|
|
12
12
|
// Discard header for now
|
|
13
|
-
counter.discard(
|
|
13
|
+
counter.discard(length);
|
|
14
14
|
return { status: 'done', segments: [(0, segments_1.expectSegment)(counter)] };
|
|
15
15
|
};
|
|
16
16
|
exports.parseWebm = parseWebm;
|
|
@@ -79,3 +79,23 @@ export type InterlacedSegment = {
|
|
|
79
79
|
interlaced: boolean;
|
|
80
80
|
};
|
|
81
81
|
export declare const parseInterlacedSegment: (iterator: BufferIterator) => InterlacedSegment;
|
|
82
|
+
export type CodecPrivateSegment = {
|
|
83
|
+
type: 'codec-private-segment';
|
|
84
|
+
codecPrivateData: number[];
|
|
85
|
+
};
|
|
86
|
+
export declare const parseCodecPrivateSegment: (iterator: BufferIterator) => CodecPrivateSegment;
|
|
87
|
+
export type Crc32Segment = {
|
|
88
|
+
type: 'crc32-segment';
|
|
89
|
+
crc32: number[];
|
|
90
|
+
};
|
|
91
|
+
export declare const parseCrc32Segment: (iterator: BufferIterator) => Crc32Segment;
|
|
92
|
+
export type SegmentUUIDSegment = {
|
|
93
|
+
type: 'segment-uuid-segment';
|
|
94
|
+
segmentUUID: string;
|
|
95
|
+
};
|
|
96
|
+
export declare const parseSegmentUUIDSegment: (iterator: BufferIterator) => SegmentUUIDSegment;
|
|
97
|
+
export type DefaultFlagSegment = {
|
|
98
|
+
type: 'default-flag-segment';
|
|
99
|
+
defaultFlag: boolean;
|
|
100
|
+
};
|
|
101
|
+
export declare const parseDefaultFlagSegment: (iterator: BufferIterator) => DefaultFlagSegment;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseInterlacedSegment = exports.parseTitleSegment = exports.parseColorSegment = exports.parseMaxBlockAdditionId = exports.parseAlphaModeSegment = exports.parseHeightSegment = exports.parseWidthSegment = exports.parseVideoSegment = exports.parseDefaultDurationSegment = exports.parseTrackTypeSegment = exports.parseCodecSegment = exports.parseLanguageSegment = exports.parseFlagLacing = exports.parseTrackUID = exports.parseTrackNumber = exports.parseTrackEntry = void 0;
|
|
3
|
+
exports.parseDefaultFlagSegment = exports.parseSegmentUUIDSegment = exports.parseCrc32Segment = exports.parseCodecPrivateSegment = exports.parseInterlacedSegment = exports.parseTitleSegment = exports.parseColorSegment = exports.parseMaxBlockAdditionId = exports.parseAlphaModeSegment = exports.parseHeightSegment = exports.parseWidthSegment = exports.parseVideoSegment = exports.parseDefaultDurationSegment = exports.parseTrackTypeSegment = exports.parseCodecSegment = exports.parseLanguageSegment = exports.parseFlagLacing = exports.parseTrackUID = exports.parseTrackNumber = exports.parseTrackEntry = void 0;
|
|
4
4
|
const parse_children_1 = require("./parse-children");
|
|
5
5
|
const parseTrackEntry = (iterator) => {
|
|
6
6
|
const offset = iterator.counter.getOffset();
|
|
@@ -162,7 +162,7 @@ const parseMaxBlockAdditionId = (iterator) => {
|
|
|
162
162
|
exports.parseMaxBlockAdditionId = parseMaxBlockAdditionId;
|
|
163
163
|
const parseColorSegment = (iterator) => {
|
|
164
164
|
const length = iterator.getVint();
|
|
165
|
-
iterator.discard(length
|
|
165
|
+
iterator.discard(length);
|
|
166
166
|
return {
|
|
167
167
|
type: 'color-segment',
|
|
168
168
|
};
|
|
@@ -189,3 +189,38 @@ const parseInterlacedSegment = (iterator) => {
|
|
|
189
189
|
};
|
|
190
190
|
};
|
|
191
191
|
exports.parseInterlacedSegment = parseInterlacedSegment;
|
|
192
|
+
const parseCodecPrivateSegment = (iterator) => {
|
|
193
|
+
const length = iterator.getVint();
|
|
194
|
+
return {
|
|
195
|
+
type: 'codec-private-segment',
|
|
196
|
+
codecPrivateData: [...iterator.getSlice(length)],
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
exports.parseCodecPrivateSegment = parseCodecPrivateSegment;
|
|
200
|
+
const parseCrc32Segment = (iterator) => {
|
|
201
|
+
const length = iterator.getVint();
|
|
202
|
+
return {
|
|
203
|
+
type: 'crc32-segment',
|
|
204
|
+
crc32: [...iterator.getSlice(length)],
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
exports.parseCrc32Segment = parseCrc32Segment;
|
|
208
|
+
const parseSegmentUUIDSegment = (iterator) => {
|
|
209
|
+
const length = iterator.getVint();
|
|
210
|
+
return {
|
|
211
|
+
type: 'segment-uuid-segment',
|
|
212
|
+
segmentUUID: iterator.getSlice(length).toString(),
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
exports.parseSegmentUUIDSegment = parseSegmentUUIDSegment;
|
|
216
|
+
const parseDefaultFlagSegment = (iterator) => {
|
|
217
|
+
const length = iterator.getVint();
|
|
218
|
+
if (length !== 1) {
|
|
219
|
+
throw new Error('Expected default flag segment to be 1 byte');
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
type: 'default-flag-segment',
|
|
223
|
+
defaultFlag: Boolean(iterator.getUint8()),
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
exports.parseDefaultFlagSegment = parseDefaultFlagSegment;
|
|
@@ -7,10 +7,10 @@ import { type SeekSegment } from './segments/seek';
|
|
|
7
7
|
import type { SeekHeadSegment } from './segments/seek-head';
|
|
8
8
|
import { type SeekPositionSegment } from './segments/seek-position';
|
|
9
9
|
import type { TimestampScaleSegment } from './segments/timestamp-scale';
|
|
10
|
-
import type { AlphaModeSegment, CodecSegment, ColorSegment, DefaultDurationSegment, FlagLacingSegment, HeightSegment, InterlacedSegment, LanguageSegment, MaxBlockAdditionId, TitleSegment, TrackEntrySegment, TrackNumberSegment, TrackTypeSegment, TrackUIDSegment, VideoSegment, WidthSegment } from './segments/track-entry';
|
|
10
|
+
import type { AlphaModeSegment, CodecPrivateSegment, CodecSegment, ColorSegment, Crc32Segment, DefaultDurationSegment, DefaultFlagSegment, FlagLacingSegment, HeightSegment, InterlacedSegment, LanguageSegment, MaxBlockAdditionId, SegmentUUIDSegment, TitleSegment, TrackEntrySegment, TrackNumberSegment, TrackTypeSegment, TrackUIDSegment, VideoSegment, WidthSegment } from './segments/track-entry';
|
|
11
11
|
import type { TracksSegment } from './segments/tracks';
|
|
12
12
|
import type { UnknownSegment } from './segments/unknown';
|
|
13
13
|
import type { VoidSegment } from './segments/void';
|
|
14
14
|
import type { WritingAppSegment } from './segments/writing';
|
|
15
|
-
export type MatroskaSegment = MainSegment | UnknownSegment | SeekHeadSegment | SeekSegment | SeekPositionSegment | VoidSegment | InfoSegment | TimestampScaleSegment | MuxingAppSegment | WritingAppSegment | DurationSegment | TracksSegment | TrackEntrySegment | TrackNumberSegment | TrackUIDSegment | FlagLacingSegment | LanguageSegment | CodecSegment | TrackTypeSegment | DefaultDurationSegment | VideoSegment | WidthSegment | HeightSegment | AlphaModeSegment | MaxBlockAdditionId | ColorSegment | TitleSegment | InterlacedSegment;
|
|
15
|
+
export type MatroskaSegment = MainSegment | UnknownSegment | SeekHeadSegment | SeekSegment | SeekPositionSegment | VoidSegment | InfoSegment | TimestampScaleSegment | MuxingAppSegment | WritingAppSegment | DurationSegment | TracksSegment | TrackEntrySegment | TrackNumberSegment | TrackUIDSegment | FlagLacingSegment | LanguageSegment | CodecSegment | TrackTypeSegment | DefaultDurationSegment | VideoSegment | WidthSegment | HeightSegment | AlphaModeSegment | MaxBlockAdditionId | ColorSegment | TitleSegment | InterlacedSegment | CodecPrivateSegment | Crc32Segment | SegmentUUIDSegment | DefaultFlagSegment;
|
|
16
16
|
export declare const expectSegment: (iterator: BufferIterator) => MatroskaSegment;
|
|
@@ -100,9 +100,21 @@ const expectSegment = (iterator) => {
|
|
|
100
100
|
if (segmentId === '0x53c0') {
|
|
101
101
|
return (0, track_entry_1.parseAlphaModeSegment)(iterator);
|
|
102
102
|
}
|
|
103
|
+
if (segmentId === '0x63a2') {
|
|
104
|
+
return (0, track_entry_1.parseCodecPrivateSegment)(iterator);
|
|
105
|
+
}
|
|
103
106
|
if (segmentId === '0x7ba9') {
|
|
104
107
|
return (0, track_entry_1.parseTitleSegment)(iterator);
|
|
105
108
|
}
|
|
109
|
+
if (segmentId === '0xbf') {
|
|
110
|
+
return (0, track_entry_1.parseCrc32Segment)(iterator);
|
|
111
|
+
}
|
|
112
|
+
if (segmentId === '0x73a4') {
|
|
113
|
+
return (0, track_entry_1.parseSegmentUUIDSegment)(iterator);
|
|
114
|
+
}
|
|
115
|
+
if (segmentId === '0x88') {
|
|
116
|
+
return (0, track_entry_1.parseDefaultFlagSegment)(iterator);
|
|
117
|
+
}
|
|
106
118
|
const length = iterator.getVint();
|
|
107
119
|
const bytesRemaining = iterator.byteLength() - iterator.counter.getOffset();
|
|
108
120
|
const toDiscard = Math.min(bytesRemaining, length > 0 ? length : bytesRemaining);
|
|
@@ -7,7 +7,8 @@ export declare class OffsetCounter {
|
|
|
7
7
|
discardBytes(amount: number): void;
|
|
8
8
|
decrement(amount: number): void;
|
|
9
9
|
}
|
|
10
|
-
export declare const getArrayBufferIterator: (initialData: Uint8Array) => {
|
|
10
|
+
export declare const getArrayBufferIterator: (initialData: Uint8Array, maxBytes?: number) => {
|
|
11
|
+
skipTo: (offset: number) => void;
|
|
11
12
|
addData: (newData: Uint8Array) => void;
|
|
12
13
|
counter: OffsetCounter;
|
|
13
14
|
byteLength: () => number;
|
|
@@ -19,6 +20,7 @@ export declare const getArrayBufferIterator: (initialData: Uint8Array) => {
|
|
|
19
20
|
getFourByteNumber: () => number;
|
|
20
21
|
getSlice: (amount: number) => Uint8Array;
|
|
21
22
|
getAtom: () => string;
|
|
23
|
+
getPaddedFourByteNumber: () => number;
|
|
22
24
|
getMatroskaSegmentId: () => string;
|
|
23
25
|
getVint: () => number;
|
|
24
26
|
getUint8: () => number;
|
package/dist/buffer-iterator.js
CHANGED
|
@@ -54,8 +54,15 @@ const matchesPattern = (pattern) => {
|
|
|
54
54
|
const makeOffsetCounter = () => {
|
|
55
55
|
return new OffsetCounter(0);
|
|
56
56
|
};
|
|
57
|
-
const getArrayBufferIterator = (initialData) => {
|
|
58
|
-
|
|
57
|
+
const getArrayBufferIterator = (initialData, maxBytes) => {
|
|
58
|
+
const buf = new ArrayBuffer(initialData.byteLength, {
|
|
59
|
+
maxByteLength: maxBytes !== null && maxBytes !== void 0 ? maxBytes : 1000000000,
|
|
60
|
+
});
|
|
61
|
+
if (!buf.resize) {
|
|
62
|
+
throw new Error('`ArrayBuffer.resize` is not supported in this Runtime. Use at least Node.js 20 or Bun.');
|
|
63
|
+
}
|
|
64
|
+
let data = new Uint8Array(buf);
|
|
65
|
+
data.set(initialData);
|
|
59
66
|
let view = new DataView(data.buffer);
|
|
60
67
|
const counter = makeOffsetCounter();
|
|
61
68
|
const getSlice = (amount) => {
|
|
@@ -71,15 +78,24 @@ const getArrayBufferIterator = (initialData) => {
|
|
|
71
78
|
const getFourByteNumber = () => {
|
|
72
79
|
return ((getUint8() << 24) | (getUint8() << 16) | (getUint8() << 8) | getUint8());
|
|
73
80
|
};
|
|
81
|
+
const getPaddedFourByteNumber = () => {
|
|
82
|
+
let lastInt = 128;
|
|
83
|
+
while (((lastInt = getUint8()), lastInt === 128)) {
|
|
84
|
+
// Do nothing
|
|
85
|
+
}
|
|
86
|
+
return lastInt;
|
|
87
|
+
};
|
|
74
88
|
const getUint32 = () => {
|
|
75
89
|
const val = view.getUint32(counter.getDiscardedOffset());
|
|
76
90
|
counter.increment(4);
|
|
77
91
|
return val;
|
|
78
92
|
};
|
|
79
93
|
const addData = (newData) => {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
const oldLength = buf.byteLength;
|
|
95
|
+
const newLength = oldLength + newData.byteLength;
|
|
96
|
+
buf.resize(newLength);
|
|
97
|
+
const newArray = new Uint8Array(buf);
|
|
98
|
+
newArray.set(newData, oldLength);
|
|
83
99
|
data = newArray;
|
|
84
100
|
view = new DataView(data.buffer);
|
|
85
101
|
};
|
|
@@ -97,13 +113,24 @@ const getArrayBufferIterator = (initialData) => {
|
|
|
97
113
|
};
|
|
98
114
|
const removeBytesRead = () => {
|
|
99
115
|
const bytesToRemove = counter.getDiscardedOffset();
|
|
116
|
+
// Only to this operation if it is really worth it 😇
|
|
117
|
+
if (bytesToRemove < 100000) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
100
120
|
counter.discardBytes(bytesToRemove);
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
121
|
+
const newData = data.slice(bytesToRemove);
|
|
122
|
+
data.set(newData);
|
|
123
|
+
buf.resize(newData.byteLength);
|
|
104
124
|
view = new DataView(data.buffer);
|
|
105
125
|
};
|
|
126
|
+
const skipTo = (offset) => {
|
|
127
|
+
buf.resize(offset);
|
|
128
|
+
const currentOffset = counter.getOffset();
|
|
129
|
+
counter.increment(offset - currentOffset);
|
|
130
|
+
removeBytesRead();
|
|
131
|
+
};
|
|
106
132
|
return {
|
|
133
|
+
skipTo,
|
|
107
134
|
addData,
|
|
108
135
|
counter,
|
|
109
136
|
byteLength,
|
|
@@ -120,6 +147,7 @@ const getArrayBufferIterator = (initialData) => {
|
|
|
120
147
|
const atom = getSlice(4);
|
|
121
148
|
return new TextDecoder().decode(atom);
|
|
122
149
|
},
|
|
150
|
+
getPaddedFourByteNumber,
|
|
123
151
|
getMatroskaSegmentId: () => {
|
|
124
152
|
const first = getSlice(1);
|
|
125
153
|
const firstOneString = `0x${Array.from(new Uint8Array(first))
|
|
@@ -140,6 +168,9 @@ const getArrayBufferIterator = (initialData) => {
|
|
|
140
168
|
'0xb0',
|
|
141
169
|
'0xba',
|
|
142
170
|
'0x9a',
|
|
171
|
+
'0xe1',
|
|
172
|
+
'0xbf',
|
|
173
|
+
'0x88',
|
|
143
174
|
];
|
|
144
175
|
if (knownIdsWithOneLength.includes(firstOneString)) {
|
|
145
176
|
return firstOneString;
|
|
@@ -157,6 +188,8 @@ const getArrayBufferIterator = (initialData) => {
|
|
|
157
188
|
'0x55ee',
|
|
158
189
|
'0x55b0',
|
|
159
190
|
'0x7ba9',
|
|
191
|
+
'0x63a2',
|
|
192
|
+
'0x73a4',
|
|
160
193
|
];
|
|
161
194
|
const firstTwoString = `${firstOneString}${Array.from(new Uint8Array(firstTwo))
|
|
162
195
|
.map((b) => {
|
package/dist/from-node.js
CHANGED
|
@@ -5,12 +5,20 @@ const fs_1 = require("fs");
|
|
|
5
5
|
const promises_1 = require("node:fs/promises");
|
|
6
6
|
const stream_1 = require("stream");
|
|
7
7
|
exports.nodeReader = {
|
|
8
|
-
read: (src, range) => {
|
|
8
|
+
read: async (src, range) => {
|
|
9
9
|
const stream = (0, fs_1.createReadStream)(src, {
|
|
10
|
-
start: range === null ? 0 : range[0],
|
|
11
|
-
end: range === null
|
|
10
|
+
start: range === null ? 0 : typeof range === 'number' ? range : range[0],
|
|
11
|
+
end: range === null
|
|
12
|
+
? Infinity
|
|
13
|
+
: typeof range === 'number'
|
|
14
|
+
? Infinity
|
|
15
|
+
: range[1],
|
|
12
16
|
});
|
|
13
|
-
|
|
17
|
+
const stats = await (0, promises_1.stat)(src);
|
|
18
|
+
return {
|
|
19
|
+
reader: stream_1.Readable.toWeb(stream).getReader(),
|
|
20
|
+
contentLength: stats.size,
|
|
21
|
+
};
|
|
14
22
|
},
|
|
15
23
|
getLength: async (src) => {
|
|
16
24
|
const stats = await (0, promises_1.stat)(src);
|
package/dist/from-web.js
CHANGED
|
@@ -14,15 +14,23 @@ exports.webReader = {
|
|
|
14
14
|
const res = await fetch(resolvedUrl, {
|
|
15
15
|
headers: range === null
|
|
16
16
|
? {}
|
|
17
|
-
:
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
: typeof range === 'number'
|
|
18
|
+
? {
|
|
19
|
+
Range: `bytes=${range}`,
|
|
20
|
+
}
|
|
21
|
+
: {
|
|
22
|
+
Range: `bytes=${`${range[0]}-${range[1]}`}`,
|
|
23
|
+
},
|
|
24
|
+
// Disable Next.js caching
|
|
25
|
+
cache: 'no-store',
|
|
20
26
|
});
|
|
21
27
|
if (!res.body) {
|
|
22
28
|
throw new Error('No body');
|
|
23
29
|
}
|
|
30
|
+
const length = res.headers.get('content-length');
|
|
31
|
+
const contentLength = length === null ? null : parseInt(length, 10);
|
|
24
32
|
const reader = res.body.getReader();
|
|
25
|
-
return reader;
|
|
33
|
+
return { reader, contentLength };
|
|
26
34
|
},
|
|
27
35
|
getLength: async (src) => {
|
|
28
36
|
const res = await fetch(src, {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAudioCodec = exports.hasAudioCodec = void 0;
|
|
4
|
+
const get_fps_1 = require("./get-fps");
|
|
5
|
+
const hasAudioCodec = (boxes) => {
|
|
6
|
+
try {
|
|
7
|
+
return (0, exports.getAudioCodec)(boxes) !== null;
|
|
8
|
+
}
|
|
9
|
+
catch (e) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
exports.hasAudioCodec = hasAudioCodec;
|
|
14
|
+
const onEsdsBox = (child) => {
|
|
15
|
+
if (child && child.type === 'esds-box') {
|
|
16
|
+
const descriptor = child.descriptors.find((d) => d.type === 'decoder-config-descriptor');
|
|
17
|
+
if (descriptor && descriptor.type === 'decoder-config-descriptor') {
|
|
18
|
+
return descriptor.objectTypeIndication;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
const onSample = (sample) => {
|
|
24
|
+
if (!sample) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (sample.type !== 'audio') {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (sample.format === 'sowt') {
|
|
31
|
+
return 'aiff';
|
|
32
|
+
}
|
|
33
|
+
const child = sample.children.find((c) => c.type === 'esds-box');
|
|
34
|
+
if (child && child.type === 'esds-box') {
|
|
35
|
+
const ret = onEsdsBox(child);
|
|
36
|
+
if (ret) {
|
|
37
|
+
return ret;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const getAudioCodec = (boxes) => {
|
|
42
|
+
const moovBox = boxes.find((b) => b.type === 'moov-box');
|
|
43
|
+
if (moovBox && moovBox.type === 'moov-box') {
|
|
44
|
+
const trakBox = moovBox.children.find((b) => b.type === 'trak-box' && (0, get_fps_1.trakBoxContainsAudio)(b));
|
|
45
|
+
if (trakBox && trakBox.type === 'trak-box') {
|
|
46
|
+
const mdiaBox = trakBox.children.find((b) => b.type === 'regular-box' && b.boxType === 'mdia');
|
|
47
|
+
if (mdiaBox &&
|
|
48
|
+
mdiaBox.type === 'regular-box' &&
|
|
49
|
+
mdiaBox.boxType === 'mdia') {
|
|
50
|
+
const minfBox = mdiaBox === null || mdiaBox === void 0 ? void 0 : mdiaBox.children.find((b) => b.type === 'regular-box' && b.boxType === 'minf');
|
|
51
|
+
if (minfBox &&
|
|
52
|
+
minfBox.type === 'regular-box' &&
|
|
53
|
+
minfBox.boxType === 'minf') {
|
|
54
|
+
const stblBox = minfBox === null || minfBox === void 0 ? void 0 : minfBox.children.find((b) => b.type === 'regular-box' && b.boxType === 'stbl');
|
|
55
|
+
if (stblBox && stblBox.type === 'regular-box') {
|
|
56
|
+
const stsdBox = stblBox === null || stblBox === void 0 ? void 0 : stblBox.children.find((b) => b.type === 'stsd-box');
|
|
57
|
+
if (stsdBox && stsdBox.type === 'stsd-box') {
|
|
58
|
+
const sample = stsdBox.samples.find((s) => s.type === 'audio');
|
|
59
|
+
if (sample && sample.type === 'audio') {
|
|
60
|
+
const ret = onSample(sample);
|
|
61
|
+
if (ret) {
|
|
62
|
+
return ret;
|
|
63
|
+
}
|
|
64
|
+
const waveBox = sample.children.find((b) => b.type === 'regular-box' && b.boxType === 'wave');
|
|
65
|
+
if (waveBox &&
|
|
66
|
+
waveBox.type === 'regular-box' &&
|
|
67
|
+
waveBox.boxType === 'wave') {
|
|
68
|
+
const esdsBox = waveBox.children.find((b) => b.type === 'esds-box');
|
|
69
|
+
if (esdsBox && esdsBox.type === 'esds-box') {
|
|
70
|
+
const ret2 = onEsdsBox(esdsBox);
|
|
71
|
+
if (ret2) {
|
|
72
|
+
return ret2;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const mainSegment = boxes.find((b) => b.type === 'main-segment');
|
|
84
|
+
if (!mainSegment || mainSegment.type !== 'main-segment') {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const tracksSegment = mainSegment.children.find((b) => b.type === 'tracks-segment');
|
|
88
|
+
if (!tracksSegment || tracksSegment.type !== 'tracks-segment') {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
for (const track of tracksSegment.children) {
|
|
92
|
+
if (track.type === 'track-entry-segment') {
|
|
93
|
+
const trackType = track.children.find((b) => b.type === 'codec-segment');
|
|
94
|
+
if (trackType && trackType.type === 'codec-segment') {
|
|
95
|
+
if (trackType.codec === 'A_OPUS') {
|
|
96
|
+
return 'opus';
|
|
97
|
+
}
|
|
98
|
+
if (trackType.codec === 'A_PCM/INT/LIT') {
|
|
99
|
+
return 'pcm';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
};
|
|
106
|
+
exports.getAudioCodec = getAudioCodec;
|
package/dist/get-dimensions.js
CHANGED
|
@@ -6,8 +6,12 @@ const getDimensionsFromMatroska = (segments) => {
|
|
|
6
6
|
if (!tracksSegment || tracksSegment.type !== 'tracks-segment') {
|
|
7
7
|
throw new Error('No tracks segment');
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const trackEntrySegment = tracksSegment.children.find((b) => {
|
|
10
|
+
if (b.type !== 'track-entry-segment') {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return (b.children.find((c) => c.type === 'codec-segment' && c.codec.startsWith('V_')) !== undefined);
|
|
14
|
+
});
|
|
11
15
|
if (!trackEntrySegment || trackEntrySegment.type !== 'track-entry-segment') {
|
|
12
16
|
throw new Error('No track entry segment');
|
|
13
17
|
}
|
package/dist/get-fps.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ type TimescaleAndDuration = {
|
|
|
3
3
|
timescale: number;
|
|
4
4
|
duration: number;
|
|
5
5
|
};
|
|
6
|
+
export declare const trakBoxContainsAudio: (trakBox: AnySegment) => boolean;
|
|
6
7
|
export declare const trakBoxContainsVideo: (trakBox: AnySegment) => boolean;
|
|
7
8
|
export declare const getTimescaleAndDuration: (boxes: AnySegment[]) => TimescaleAndDuration | null;
|
|
8
9
|
export declare const getFps: (segments: AnySegment[]) => number | null;
|
package/dist/get-fps.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasFps = exports.getFps = exports.getTimescaleAndDuration = exports.trakBoxContainsVideo = void 0;
|
|
3
|
+
exports.hasFps = exports.getFps = exports.getTimescaleAndDuration = exports.trakBoxContainsVideo = exports.trakBoxContainsAudio = void 0;
|
|
4
4
|
const calculateFps = ({ sttsBox, timeScale, durationInSamples, }) => {
|
|
5
5
|
let totalSamples = 0;
|
|
6
6
|
for (const sample of sttsBox.sampleDistribution) {
|
|
@@ -10,6 +10,39 @@ const calculateFps = ({ sttsBox, timeScale, durationInSamples, }) => {
|
|
|
10
10
|
const fps = totalSamples / durationInSeconds;
|
|
11
11
|
return fps;
|
|
12
12
|
};
|
|
13
|
+
const trakBoxContainsAudio = (trakBox) => {
|
|
14
|
+
if (trakBox.type !== 'trak-box') {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const { children } = trakBox;
|
|
18
|
+
const mediaBoxes = children.filter((c) => c.type === 'regular-box' && c.boxType === 'mdia');
|
|
19
|
+
if (!mediaBoxes || mediaBoxes.length === 0) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
const firstMediaBox = mediaBoxes[0];
|
|
23
|
+
if (firstMediaBox.type !== 'regular-box' ||
|
|
24
|
+
firstMediaBox.boxType !== 'mdia') {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const minf = firstMediaBox.children.find((c) => c.type === 'regular-box' && c.boxType === 'minf');
|
|
28
|
+
if (!minf || minf.type !== 'regular-box' || minf.boxType !== 'minf') {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const stbl = minf.children.find((c) => c.type === 'regular-box' && c.boxType === 'stbl');
|
|
32
|
+
if (!stbl || stbl.type !== 'regular-box' || stbl.boxType !== 'stbl') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
const stsd = stbl.children.find((c) => c.type === 'stsd-box');
|
|
36
|
+
if (!stsd || stsd.type !== 'stsd-box') {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const videoSample = stsd.samples.find((s) => s.type === 'audio');
|
|
40
|
+
if (!videoSample || videoSample.type !== 'audio') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
exports.trakBoxContainsAudio = trakBoxContainsAudio;
|
|
13
46
|
const trakBoxContainsVideo = (trakBox) => {
|
|
14
47
|
if (trakBox.type !== 'trak-box') {
|
|
15
48
|
return false;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StcoBox } from './boxes/iso-base-media/stsd/stco';
|
|
2
|
+
import type { StscBox } from './boxes/iso-base-media/stsd/stsc';
|
|
3
|
+
import type { StszBox } from './boxes/iso-base-media/stsd/stsz';
|
|
4
|
+
export type SamplePosition = {
|
|
5
|
+
offset: number;
|
|
6
|
+
size: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const getSamplePositions: ({ stcoBox, stszBox, stscBox, }: {
|
|
9
|
+
stcoBox: StcoBox;
|
|
10
|
+
stszBox: StszBox;
|
|
11
|
+
stscBox: StscBox;
|
|
12
|
+
}) => SamplePosition[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSamplePositions = void 0;
|
|
4
|
+
const getSamplePositions = ({ stcoBox, stszBox, stscBox, }) => {
|
|
5
|
+
const chunks = stcoBox.entries;
|
|
6
|
+
const samples = [];
|
|
7
|
+
let samplesPerChunk = 1;
|
|
8
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
9
|
+
const hasEntry = stscBox.entries.find((entry) => entry.firstChunk === i + 1);
|
|
10
|
+
if (hasEntry) {
|
|
11
|
+
samplesPerChunk = hasEntry.samplesPerChunk;
|
|
12
|
+
}
|
|
13
|
+
let offsetInThisChunk = 0;
|
|
14
|
+
for (let j = 0; j < samplesPerChunk; j++) {
|
|
15
|
+
const size = stszBox.samples[samples.length];
|
|
16
|
+
samples.push({
|
|
17
|
+
offset: chunks[i] + offsetInThisChunk,
|
|
18
|
+
size,
|
|
19
|
+
});
|
|
20
|
+
offsetInThisChunk += size;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return samples;
|
|
24
|
+
};
|
|
25
|
+
exports.getSamplePositions = getSamplePositions;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SamplePosition } from './get-sample-positions';
|
|
2
|
+
import type { AnySegment } from './parse-result';
|
|
3
|
+
type Track = {
|
|
4
|
+
type: 'audio' | 'video';
|
|
5
|
+
samplePositions: SamplePosition[];
|
|
6
|
+
trackId: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const getNumberOfTracks: (segments: AnySegment[]) => number;
|
|
9
|
+
export declare const getTracks: (segments: AnySegment[]) => Track[];
|
|
10
|
+
export {};
|