@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,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTracks = exports.getNumberOfTracks = void 0;
|
|
4
|
+
const get_fps_1 = require("./get-fps");
|
|
5
|
+
const get_sample_positions_1 = require("./get-sample-positions");
|
|
6
|
+
const traversal_1 = require("./traversal");
|
|
7
|
+
// TODO: Use this to determine if all tracks are present
|
|
8
|
+
const getNumberOfTracks = (segments) => {
|
|
9
|
+
const moovBox = (0, traversal_1.getMoovBox)(segments);
|
|
10
|
+
if (!moovBox) {
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
const mvHdBox = (0, traversal_1.getMvhdBox)(moovBox);
|
|
14
|
+
if (!mvHdBox) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
return mvHdBox.nextTrackId - 1;
|
|
18
|
+
};
|
|
19
|
+
exports.getNumberOfTracks = getNumberOfTracks;
|
|
20
|
+
const getTracks = (segments) => {
|
|
21
|
+
const moovBox = (0, traversal_1.getMoovBox)(segments);
|
|
22
|
+
if (!moovBox) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const foundTracks = [];
|
|
26
|
+
const tracks = (0, traversal_1.getTraks)(moovBox);
|
|
27
|
+
for (const track of tracks) {
|
|
28
|
+
const stszBox = (0, traversal_1.getStszBox)(track);
|
|
29
|
+
const stcoBox = (0, traversal_1.getStcoBox)(track);
|
|
30
|
+
const stscBox = (0, traversal_1.getStscBox)(track);
|
|
31
|
+
const tkhdBox = (0, traversal_1.getTkhdBox)(track);
|
|
32
|
+
if (!tkhdBox) {
|
|
33
|
+
throw new Error('Expected tkhd box in trak box');
|
|
34
|
+
}
|
|
35
|
+
if (!stszBox) {
|
|
36
|
+
throw new Error('Expected stsz box in trak box');
|
|
37
|
+
}
|
|
38
|
+
if (!stcoBox) {
|
|
39
|
+
throw new Error('Expected stco box in trak box');
|
|
40
|
+
}
|
|
41
|
+
if (!stscBox) {
|
|
42
|
+
throw new Error('Expected stsc box in trak box');
|
|
43
|
+
}
|
|
44
|
+
const samplePositions = (0, get_sample_positions_1.getSamplePositions)({
|
|
45
|
+
stcoBox,
|
|
46
|
+
stscBox,
|
|
47
|
+
stszBox,
|
|
48
|
+
});
|
|
49
|
+
if ((0, get_fps_1.trakBoxContainsAudio)(track)) {
|
|
50
|
+
foundTracks.push({
|
|
51
|
+
type: 'audio',
|
|
52
|
+
samplePositions,
|
|
53
|
+
trackId: tkhdBox.trackId,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if ((0, get_fps_1.trakBoxContainsVideo)(track)) {
|
|
57
|
+
foundTracks.push({
|
|
58
|
+
type: 'video',
|
|
59
|
+
samplePositions,
|
|
60
|
+
trackId: tkhdBox.trackId,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return foundTracks;
|
|
65
|
+
};
|
|
66
|
+
exports.getTracks = getTracks;
|
package/dist/get-video-codec.js
CHANGED
package/dist/has-all-info.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Options } from './options';
|
|
2
2
|
import type { ParseResult } from './parse-result';
|
|
3
|
-
export declare const hasAllInfo: (options: Options<boolean, boolean, boolean, boolean, boolean>, parseResult: ParseResult) => boolean;
|
|
3
|
+
export declare const hasAllInfo: (options: Options<boolean, boolean, boolean, boolean, boolean, boolean>, parseResult: ParseResult) => boolean;
|
package/dist/has-all-info.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hasAllInfo = void 0;
|
|
4
|
+
const get_audio_codec_1 = require("./get-audio-codec");
|
|
4
5
|
const get_dimensions_1 = require("./get-dimensions");
|
|
5
6
|
const get_duration_1 = require("./get-duration");
|
|
6
7
|
const get_fps_1 = require("./get-fps");
|
|
@@ -25,6 +26,9 @@ const hasAllInfo = (options, parseResult) => {
|
|
|
25
26
|
if (key === 'videoCodec') {
|
|
26
27
|
return (0, get_video_codec_1.hasVideoCodec)(parseResult.segments) !== null;
|
|
27
28
|
}
|
|
29
|
+
if (key === 'audioCodec') {
|
|
30
|
+
return (0, get_audio_codec_1.hasAudioCodec)(parseResult.segments) !== null;
|
|
31
|
+
}
|
|
28
32
|
throw new Error(`Unknown key: ${key}`);
|
|
29
33
|
});
|
|
30
34
|
};
|
package/dist/options.d.ts
CHANGED
|
@@ -2,14 +2,16 @@ import type { Dimensions } from './get-dimensions';
|
|
|
2
2
|
import type { AnySegment } from './parse-result';
|
|
3
3
|
import type { ReaderInterface } from './reader';
|
|
4
4
|
export type KnownVideoCodecs = 'h264' | 'h265' | 'vp8' | 'vp9' | 'av1' | 'prores';
|
|
5
|
-
export type
|
|
5
|
+
export type KnownAudioCodecs = 'aac' | 'mp3' | 'aiff' | 'opus' | 'pcm' | 'unknown';
|
|
6
|
+
export type Options<EnableDimensions extends boolean, EnableDuration extends boolean, EnableBoxes extends boolean, EnableFps extends boolean, EnableVideoCodec extends boolean, EnableAudioCodec extends boolean> = {
|
|
6
7
|
dimensions?: EnableDimensions;
|
|
7
8
|
durationInSeconds?: EnableDuration;
|
|
8
9
|
boxes?: EnableBoxes;
|
|
9
10
|
fps?: EnableFps;
|
|
10
11
|
videoCodec?: EnableVideoCodec;
|
|
12
|
+
audioCodec?: EnableAudioCodec;
|
|
11
13
|
};
|
|
12
|
-
export type Metadata<EnableDimensions extends boolean, EnableDuration extends boolean, EnableBoxes extends boolean, EnableFps extends boolean, EnableVideoCodec extends boolean> = (EnableDimensions extends true ? {
|
|
14
|
+
export type Metadata<EnableDimensions extends boolean, EnableDuration extends boolean, EnableBoxes extends boolean, EnableFps extends boolean, EnableVideoCodec extends boolean, EnableAudioCodec extends boolean> = (EnableDimensions extends true ? {
|
|
13
15
|
dimensions: Dimensions;
|
|
14
16
|
} : {}) & (EnableDuration extends true ? {
|
|
15
17
|
durationInSeconds: number | null;
|
|
@@ -19,5 +21,7 @@ export type Metadata<EnableDimensions extends boolean, EnableDuration extends bo
|
|
|
19
21
|
fps: number | null;
|
|
20
22
|
} : {}) & (EnableVideoCodec extends true ? {
|
|
21
23
|
videoCodec: KnownVideoCodecs | null;
|
|
24
|
+
} : {}) & (EnableAudioCodec extends true ? {
|
|
25
|
+
audioCodec: KnownAudioCodecs | null;
|
|
22
26
|
} : {});
|
|
23
|
-
export type ParseMedia = <EnableDimensions extends boolean, EnableDuration extends boolean, EnableBoxes extends boolean, EnableFps extends boolean, EnableVideoCodec extends boolean>(src: string, options: Options<EnableDimensions, EnableDuration, EnableBoxes, EnableFps, EnableVideoCodec>, readerInterface?: ReaderInterface) => Promise<Metadata<EnableDimensions, EnableDuration, EnableBoxes, EnableFps, EnableVideoCodec>>;
|
|
27
|
+
export type ParseMedia = <EnableDimensions extends boolean, EnableDuration extends boolean, EnableBoxes extends boolean, EnableFps extends boolean, EnableVideoCodec extends boolean, EnableAudioCodec extends boolean>(src: string, options: Options<EnableDimensions, EnableDuration, EnableBoxes, EnableFps, EnableVideoCodec, EnableAudioCodec>, readerInterface?: ReaderInterface) => Promise<Metadata<EnableDimensions, EnableDuration, EnableBoxes, EnableFps, EnableVideoCodec, EnableAudioCodec>>;
|
package/dist/parse-media.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseMedia = void 0;
|
|
4
4
|
const buffer_iterator_1 = require("./buffer-iterator");
|
|
5
5
|
const from_web_1 = require("./from-web");
|
|
6
|
+
const get_audio_codec_1 = require("./get-audio-codec");
|
|
6
7
|
const get_dimensions_1 = require("./get-dimensions");
|
|
7
8
|
const get_duration_1 = require("./get-duration");
|
|
8
9
|
const get_fps_1 = require("./get-fps");
|
|
@@ -10,23 +11,47 @@ const get_video_codec_1 = require("./get-video-codec");
|
|
|
10
11
|
const has_all_info_1 = require("./has-all-info");
|
|
11
12
|
const parse_video_1 = require("./parse-video");
|
|
12
13
|
const parseMedia = async (src, options, readerInterface = from_web_1.webReader) => {
|
|
13
|
-
const reader = await readerInterface.read(src, null);
|
|
14
|
+
const { reader, contentLength } = await readerInterface.read(src, null);
|
|
15
|
+
let currentReader = reader;
|
|
14
16
|
const returnValue = {};
|
|
15
|
-
|
|
16
|
-
let parseResult =
|
|
17
|
-
while (parseResult.status === 'incomplete') {
|
|
18
|
-
const result = await
|
|
17
|
+
let iterator = null;
|
|
18
|
+
let parseResult = null;
|
|
19
|
+
while (parseResult === null || parseResult.status === 'incomplete') {
|
|
20
|
+
const result = await currentReader.read();
|
|
19
21
|
if (result.done) {
|
|
20
22
|
break;
|
|
21
23
|
}
|
|
22
|
-
iterator
|
|
23
|
-
|
|
24
|
+
if (iterator) {
|
|
25
|
+
iterator.addData(result.value);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
iterator = (0, buffer_iterator_1.getArrayBufferIterator)(result.value, contentLength !== null && contentLength !== void 0 ? contentLength : undefined);
|
|
29
|
+
}
|
|
30
|
+
if (parseResult) {
|
|
31
|
+
parseResult = parseResult.continueParsing();
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
parseResult = (0, parse_video_1.parseVideo)(iterator);
|
|
35
|
+
}
|
|
24
36
|
if ((0, has_all_info_1.hasAllInfo)(options, parseResult)) {
|
|
25
|
-
if (!
|
|
26
|
-
|
|
37
|
+
if (!currentReader.closed) {
|
|
38
|
+
currentReader.cancel(new Error('has all information'));
|
|
27
39
|
}
|
|
28
40
|
break;
|
|
29
41
|
}
|
|
42
|
+
if (parseResult &&
|
|
43
|
+
parseResult.status === 'incomplete' &&
|
|
44
|
+
parseResult.skipTo !== null) {
|
|
45
|
+
if (!currentReader.closed) {
|
|
46
|
+
currentReader.cancel(new Error('skipped ahead'));
|
|
47
|
+
}
|
|
48
|
+
const { reader: newReader } = await readerInterface.read(src, parseResult.skipTo);
|
|
49
|
+
currentReader = newReader;
|
|
50
|
+
iterator.skipTo(parseResult.skipTo);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (!parseResult) {
|
|
54
|
+
throw new Error('Could not parse video');
|
|
30
55
|
}
|
|
31
56
|
if (options.dimensions) {
|
|
32
57
|
returnValue.dimensions = (0, get_dimensions_1.getDimensions)(parseResult.segments);
|
|
@@ -40,6 +65,9 @@ const parseMedia = async (src, options, readerInterface = from_web_1.webReader)
|
|
|
40
65
|
if (options.videoCodec) {
|
|
41
66
|
returnValue.videoCodec = (0, get_video_codec_1.getVideoCodec)(parseResult.segments);
|
|
42
67
|
}
|
|
68
|
+
if (options.audioCodec) {
|
|
69
|
+
returnValue.audioCodec = (0, get_audio_codec_1.getAudioCodec)(parseResult.segments);
|
|
70
|
+
}
|
|
43
71
|
if (options.boxes) {
|
|
44
72
|
returnValue.boxes = parseResult.segments;
|
|
45
73
|
}
|
package/dist/parse-result.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseBox } from './boxes/iso-base-media/base-type';
|
|
2
|
+
import type { EsdsBox } from './boxes/iso-base-media/esds/esds';
|
|
2
3
|
import type { FtypBox } from './boxes/iso-base-media/ftyp';
|
|
3
4
|
import type { MdhdBox } from './boxes/iso-base-media/mdhd';
|
|
4
5
|
import type { MoovBox } from './boxes/iso-base-media/moov/moov';
|
|
@@ -17,7 +18,7 @@ interface RegularBox extends BaseBox {
|
|
|
17
18
|
offset: number;
|
|
18
19
|
type: 'regular-box';
|
|
19
20
|
}
|
|
20
|
-
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox;
|
|
21
|
+
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | EsdsBox;
|
|
21
22
|
export type AnySegment = MatroskaSegment | IsoBaseMediaBox;
|
|
22
23
|
export type ParseResult = {
|
|
23
24
|
status: 'done';
|
|
@@ -25,6 +26,7 @@ export type ParseResult = {
|
|
|
25
26
|
} | {
|
|
26
27
|
status: 'incomplete';
|
|
27
28
|
segments: AnySegment[];
|
|
29
|
+
skipTo: number | null;
|
|
28
30
|
continueParsing: () => ParseResult;
|
|
29
31
|
};
|
|
30
32
|
export {};
|
package/dist/parse-video.d.ts
CHANGED
package/dist/parse-video.js
CHANGED
package/dist/reader.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
type
|
|
1
|
+
type ReadResult = {
|
|
2
|
+
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
3
|
+
contentLength: number | null;
|
|
4
|
+
};
|
|
5
|
+
type ReadContent = (src: string, range: [number, number] | number | null) => Promise<ReadResult>;
|
|
2
6
|
type GetLength = (src: string) => Promise<number>;
|
|
3
7
|
export type ReaderInterface = {
|
|
4
8
|
read: ReadContent;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MoovBox } from './boxes/iso-base-media/moov/moov';
|
|
2
|
+
import type { MvhdBox } from './boxes/iso-base-media/mvhd';
|
|
3
|
+
import type { StcoBox } from './boxes/iso-base-media/stsd/stco';
|
|
4
|
+
import type { StscBox } from './boxes/iso-base-media/stsd/stsc';
|
|
5
|
+
import type { StsdBox } from './boxes/iso-base-media/stsd/stsd';
|
|
6
|
+
import type { StszBox } from './boxes/iso-base-media/stsd/stsz';
|
|
7
|
+
import type { TkhdBox } from './boxes/iso-base-media/tkhd';
|
|
8
|
+
import type { TrakBox } from './boxes/iso-base-media/trak/trak';
|
|
9
|
+
import type { AnySegment, RegularBox } from './parse-result';
|
|
10
|
+
export declare const getMoovBox: (segments: AnySegment[]) => MoovBox | null;
|
|
11
|
+
export declare const getMvhdBox: (moovBox: MoovBox) => MvhdBox | null;
|
|
12
|
+
export declare const getTraks: (moovBox: MoovBox) => TrakBox[];
|
|
13
|
+
export declare const getTkhdBox: (trakBox: TrakBox) => TkhdBox | null;
|
|
14
|
+
export declare const getMdiaBox: (trakBox: TrakBox) => RegularBox | null;
|
|
15
|
+
export declare const getStblBox: (trakBox: TrakBox) => RegularBox | null;
|
|
16
|
+
export declare const getStsdBox: (trakBox: TrakBox) => StsdBox | null;
|
|
17
|
+
export declare const getStcoBox: (trakBox: TrakBox) => StcoBox | null;
|
|
18
|
+
export declare const getStszBox: (trakBox: TrakBox) => StszBox | null;
|
|
19
|
+
export declare const getStscBox: (trakBox: TrakBox) => StscBox | null;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getStscBox = exports.getStszBox = exports.getStcoBox = exports.getStsdBox = exports.getStblBox = exports.getMdiaBox = exports.getTkhdBox = exports.getTraks = exports.getMvhdBox = exports.getMoovBox = void 0;
|
|
4
|
+
const getMoovBox = (segments) => {
|
|
5
|
+
const moovBox = segments.find((s) => s.type === 'moov-box');
|
|
6
|
+
if (!moovBox || moovBox.type !== 'moov-box') {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return moovBox;
|
|
10
|
+
};
|
|
11
|
+
exports.getMoovBox = getMoovBox;
|
|
12
|
+
const getMvhdBox = (moovBox) => {
|
|
13
|
+
const mvHdBox = moovBox.children.find((s) => s.type === 'mvhd-box');
|
|
14
|
+
if (!mvHdBox || mvHdBox.type !== 'mvhd-box') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return mvHdBox;
|
|
18
|
+
};
|
|
19
|
+
exports.getMvhdBox = getMvhdBox;
|
|
20
|
+
const getTraks = (moovBox) => {
|
|
21
|
+
return moovBox.children.filter((s) => s.type === 'trak-box');
|
|
22
|
+
};
|
|
23
|
+
exports.getTraks = getTraks;
|
|
24
|
+
const getTkhdBox = (trakBox) => {
|
|
25
|
+
const tkhdBox = trakBox.children.find((s) => s.type === 'tkhd-box');
|
|
26
|
+
return tkhdBox;
|
|
27
|
+
};
|
|
28
|
+
exports.getTkhdBox = getTkhdBox;
|
|
29
|
+
const getMdiaBox = (trakBox) => {
|
|
30
|
+
const mdiaBox = trakBox.children.find((s) => s.type === 'regular-box' && s.boxType === 'mdia');
|
|
31
|
+
if (!mdiaBox || mdiaBox.type !== 'regular-box') {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return mdiaBox;
|
|
35
|
+
};
|
|
36
|
+
exports.getMdiaBox = getMdiaBox;
|
|
37
|
+
const getStblBox = (trakBox) => {
|
|
38
|
+
const mdiaBox = (0, exports.getMdiaBox)(trakBox);
|
|
39
|
+
if (!mdiaBox) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const minfBox = mdiaBox.children.find((s) => s.type === 'regular-box' && s.boxType === 'minf');
|
|
43
|
+
if (!minfBox || minfBox.type !== 'regular-box') {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const stblBox = minfBox.children.find((s) => s.type === 'regular-box' && s.boxType === 'stbl');
|
|
47
|
+
if (!stblBox || stblBox.type !== 'regular-box') {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return stblBox;
|
|
51
|
+
};
|
|
52
|
+
exports.getStblBox = getStblBox;
|
|
53
|
+
const getStsdBox = (trakBox) => {
|
|
54
|
+
const stblBox = (0, exports.getStblBox)(trakBox);
|
|
55
|
+
if (!stblBox || stblBox.type !== 'regular-box') {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const stsdBox = stblBox.children.find((s) => s.type === 'stsd-box');
|
|
59
|
+
return stsdBox;
|
|
60
|
+
};
|
|
61
|
+
exports.getStsdBox = getStsdBox;
|
|
62
|
+
const getStcoBox = (trakBox) => {
|
|
63
|
+
const stblBox = (0, exports.getStblBox)(trakBox);
|
|
64
|
+
if (!stblBox || stblBox.type !== 'regular-box') {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const stcoBox = stblBox.children.find((s) => s.type === 'stco-box');
|
|
68
|
+
return stcoBox;
|
|
69
|
+
};
|
|
70
|
+
exports.getStcoBox = getStcoBox;
|
|
71
|
+
const getStszBox = (trakBox) => {
|
|
72
|
+
const stblBox = (0, exports.getStblBox)(trakBox);
|
|
73
|
+
if (!stblBox || stblBox.type !== 'regular-box') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const stszBox = stblBox.children.find((s) => s.type === 'stsz-box');
|
|
77
|
+
return stszBox;
|
|
78
|
+
};
|
|
79
|
+
exports.getStszBox = getStszBox;
|
|
80
|
+
const getStscBox = (trakBox) => {
|
|
81
|
+
const stblBox = (0, exports.getStblBox)(trakBox);
|
|
82
|
+
if (!stblBox || stblBox.type !== 'regular-box') {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const stcoBox = stblBox.children.find((b) => b.type === 'stsc-box');
|
|
86
|
+
return stcoBox;
|
|
87
|
+
};
|
|
88
|
+
exports.getStscBox = getStscBox;
|
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/media-parser",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.194",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@remotion/renderer": "4.0.
|
|
10
|
+
"@remotion/renderer": "4.0.194"
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
|
|
3
|
+
type AudioObjectType = 'aac' | 'mp3' | 'unknown';
|
|
4
|
+
|
|
5
|
+
type DecoderConfigDescriptor = {
|
|
6
|
+
type: 'decoder-config-descriptor';
|
|
7
|
+
objectTypeIndication: AudioObjectType;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const mapToObjectAudioIndicator = (num: number): AudioObjectType => {
|
|
11
|
+
// https://chromium.googlesource.com/chromium/src/media/+/master/formats/mp4/es_descriptor.h
|
|
12
|
+
// http://netmedia.zju.edu.cn/multimedia2013/mpeg-4/ISO%20IEC%2014496-1%20MPEG-4%20System%20Standard.pdf
|
|
13
|
+
// Page 42, table 8
|
|
14
|
+
if (num === 0x40) {
|
|
15
|
+
return 'aac';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (num === 0x6b) {
|
|
19
|
+
return 'mp3';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return 'unknown';
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type SlConfigDescriptor = {
|
|
26
|
+
type: 'sl-config-descriptor';
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type UnknownDescriptor = {
|
|
30
|
+
type: 'unknown-descriptor';
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type Descriptor =
|
|
34
|
+
| DecoderConfigDescriptor
|
|
35
|
+
| SlConfigDescriptor
|
|
36
|
+
| UnknownDescriptor;
|
|
37
|
+
|
|
38
|
+
type DescriptorAndNext = {
|
|
39
|
+
descriptor: Descriptor | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const processDescriptor = ({
|
|
43
|
+
iterator,
|
|
44
|
+
}: {
|
|
45
|
+
iterator: BufferIterator;
|
|
46
|
+
}): DescriptorAndNext => {
|
|
47
|
+
const tag = iterator.getUint8();
|
|
48
|
+
|
|
49
|
+
if (tag === 4) {
|
|
50
|
+
const size = iterator.getPaddedFourByteNumber();
|
|
51
|
+
const initialOffset = iterator.counter.getOffset();
|
|
52
|
+
|
|
53
|
+
const objectTypeIndication = iterator.getUint8();
|
|
54
|
+
|
|
55
|
+
const remaining = size - (iterator.counter.getOffset() - initialOffset);
|
|
56
|
+
iterator.discard(remaining);
|
|
57
|
+
return {
|
|
58
|
+
descriptor: {
|
|
59
|
+
type: 'decoder-config-descriptor',
|
|
60
|
+
objectTypeIndication: mapToObjectAudioIndicator(objectTypeIndication),
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (tag === 6) {
|
|
66
|
+
const size = iterator.getPaddedFourByteNumber();
|
|
67
|
+
|
|
68
|
+
iterator.discard(size);
|
|
69
|
+
return {
|
|
70
|
+
descriptor: {
|
|
71
|
+
type: 'sl-config-descriptor',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
descriptor: null,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const parseDescriptors = (
|
|
82
|
+
iterator: BufferIterator,
|
|
83
|
+
maxBytes: number,
|
|
84
|
+
): Descriptor[] => {
|
|
85
|
+
const descriptors: Descriptor[] = [];
|
|
86
|
+
const initialOffset = iterator.counter.getOffset();
|
|
87
|
+
|
|
88
|
+
while (
|
|
89
|
+
iterator.bytesRemaining() > 0 &&
|
|
90
|
+
iterator.counter.getOffset() - initialOffset < maxBytes
|
|
91
|
+
) {
|
|
92
|
+
const {descriptor} = processDescriptor({
|
|
93
|
+
iterator,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (descriptor) {
|
|
97
|
+
descriptors.push(descriptor);
|
|
98
|
+
} else {
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return descriptors;
|
|
104
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
import type {Descriptor} from './esds-descriptors';
|
|
3
|
+
import {parseDescriptors} from './esds-descriptors';
|
|
4
|
+
|
|
5
|
+
export interface EsdsBox {
|
|
6
|
+
type: 'esds-box';
|
|
7
|
+
version: number;
|
|
8
|
+
tag: number;
|
|
9
|
+
sizeOfInstance: number;
|
|
10
|
+
esId: number;
|
|
11
|
+
descriptors: Descriptor[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const parseEsds = ({
|
|
15
|
+
data,
|
|
16
|
+
size,
|
|
17
|
+
fileOffset,
|
|
18
|
+
}: {
|
|
19
|
+
data: BufferIterator;
|
|
20
|
+
size: number;
|
|
21
|
+
fileOffset: number;
|
|
22
|
+
}): EsdsBox => {
|
|
23
|
+
const version = data.getUint8();
|
|
24
|
+
// Flags, we discard them
|
|
25
|
+
data.discard(3);
|
|
26
|
+
const tag = data.getUint8();
|
|
27
|
+
|
|
28
|
+
const sizeOfInstance = data.getPaddedFourByteNumber();
|
|
29
|
+
const esId = data.getUint16();
|
|
30
|
+
|
|
31
|
+
// disard 1 byte, currently unknown
|
|
32
|
+
data.discard(1);
|
|
33
|
+
|
|
34
|
+
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
35
|
+
const descriptors = parseDescriptors(data, remaining);
|
|
36
|
+
|
|
37
|
+
const remainingNow = size - (data.counter.getOffset() - fileOffset);
|
|
38
|
+
|
|
39
|
+
data.discard(remainingNow);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
type: 'esds-box',
|
|
43
|
+
version,
|
|
44
|
+
tag,
|
|
45
|
+
sizeOfInstance,
|
|
46
|
+
esId,
|
|
47
|
+
descriptors,
|
|
48
|
+
};
|
|
49
|
+
};
|