@remotion/media-parser 4.0.248 → 4.0.249
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/boxes/avc/key.d.ts +1 -1
- package/dist/boxes/iso-base-media/get-children.d.ts +14 -0
- package/dist/boxes/iso-base-media/get-children.js +39 -0
- package/dist/boxes/iso-base-media/mdat/mdat.d.ts +2 -1
- package/dist/boxes/iso-base-media/mdat/mdat.js +10 -1
- package/dist/boxes/iso-base-media/moov/moov.js +2 -3
- package/dist/boxes/iso-base-media/parse-boxes.d.ts +15 -0
- package/dist/boxes/iso-base-media/parse-boxes.js +129 -0
- package/dist/boxes/iso-base-media/parse-mdat-partially.d.ts +12 -0
- package/dist/boxes/iso-base-media/parse-mdat-partially.js +33 -0
- package/dist/boxes/iso-base-media/process-box.d.ts +2 -21
- package/dist/boxes/iso-base-media/process-box.js +53 -270
- package/dist/boxes/iso-base-media/stsd/mebx.js +2 -3
- package/dist/boxes/iso-base-media/stsd/samples.js +5 -9
- package/dist/boxes/iso-base-media/trak/trak.js +2 -3
- package/dist/boxes/mp3/get-duration.d.ts +2 -0
- package/dist/boxes/mp3/get-duration.js +30 -0
- package/dist/boxes/mp3/get-frame-length.d.ts +13 -0
- package/dist/boxes/mp3/get-frame-length.js +33 -0
- package/dist/boxes/mp3/get-metadata-from-mp3.d.ts +3 -0
- package/dist/boxes/mp3/get-metadata-from-mp3.js +8 -0
- package/dist/boxes/mp3/get-tracks-from-mp3.d.ts +4 -0
- package/dist/boxes/mp3/get-tracks-from-mp3.js +25 -0
- package/dist/boxes/mp3/id3-v1.d.ts +2 -0
- package/dist/boxes/mp3/id3-v1.js +12 -0
- package/dist/boxes/mp3/id3-v2.d.ts +0 -0
- package/dist/boxes/mp3/id3-v2.js +1 -0
- package/dist/boxes/mp3/id3.d.ts +8 -0
- package/dist/boxes/mp3/id3.js +78 -0
- package/dist/boxes/mp3/parse-mp3.d.ts +8 -0
- package/dist/boxes/mp3/parse-mp3.js +57 -0
- package/dist/boxes/mp3/parse-mpeg-header.d.ts +6 -0
- package/dist/boxes/mp3/parse-mpeg-header.js +274 -0
- package/dist/boxes/mp3/samples-per-mpeg-file.d.ts +4 -0
- package/dist/boxes/mp3/samples-per-mpeg-file.js +26 -0
- package/dist/boxes/riff/continue-after-riff-result.d.ts +13 -0
- package/dist/boxes/riff/continue-after-riff-result.js +34 -0
- package/dist/boxes/riff/expect-riff-box.d.ts +3 -1
- package/dist/boxes/riff/expect-riff-box.js +4 -3
- package/dist/boxes/riff/parse-box.d.ts +1 -7
- package/dist/boxes/riff/parse-box.js +4 -120
- package/dist/boxes/riff/parse-list-box.d.ts +3 -1
- package/dist/boxes/riff/parse-list-box.js +4 -3
- package/dist/boxes/riff/parse-riff-body.d.ts +11 -0
- package/dist/boxes/riff/parse-riff-body.js +105 -0
- package/dist/boxes/riff/parse-riff-box.d.ts +3 -1
- package/dist/boxes/riff/parse-riff-box.js +2 -2
- package/dist/boxes/transport-stream/parse-transport-stream.js +30 -41
- package/dist/buffer-iterator.d.ts +6 -0
- package/dist/buffer-iterator.js +21 -0
- package/dist/continue-mdat-routine.d.ts +17 -0
- package/dist/continue-mdat-routine.js +92 -0
- package/dist/emit-available-info.js +38 -24
- package/dist/esm/index.mjs +1820 -1046
- package/dist/file-types/detect-file-type.js +4 -2
- package/dist/get-audio-codec.js +1 -1
- package/dist/get-container.js +5 -1
- package/dist/get-dimensions.d.ts +1 -1
- package/dist/get-dimensions.js +3 -0
- package/dist/get-duration.js +5 -1
- package/dist/get-fields-from-callbacks.js +1 -0
- package/dist/get-fps.js +3 -0
- package/dist/get-is-hdr.js +1 -1
- package/dist/get-keyframes.js +1 -1
- package/dist/get-tracks.d.ts +1 -1
- package/dist/get-tracks.js +10 -3
- package/dist/get-video-codec.js +1 -1
- package/dist/has-all-info.js +4 -3
- package/dist/index.d.ts +20 -2
- package/dist/may-skip-video-data/need-samples-for-fields.js +1 -0
- package/dist/metadata/get-metadata.d.ts +1 -0
- package/dist/metadata/get-metadata.js +16 -1
- package/dist/options.d.ts +12 -5
- package/dist/parse-media.js +48 -43
- package/dist/parse-result.d.ts +16 -1
- package/dist/parse-video.js +9 -10
- package/dist/state/can-skip-tracks.js +1 -0
- package/dist/state/emitted-fields.js +1 -0
- package/dist/state/images.d.ts +9 -0
- package/dist/state/images.js +14 -0
- package/dist/state/mp3.d.ts +11 -0
- package/dist/state/mp3.js +13 -0
- package/dist/state/parser-state.d.ts +13 -2
- package/dist/state/parser-state.js +8 -1
- package/dist/state/sample-callbacks.js +4 -1
- package/dist/state/slow-duration-fps.d.ts +2 -1
- package/dist/state/slow-duration-fps.js +52 -18
- package/dist/throttled-progress.d.ts +14 -0
- package/dist/throttled-progress.js +44 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
|
@@ -43,10 +43,12 @@ const isTransportStream = (data) => {
|
|
|
43
43
|
exports.isTransportStream = isTransportStream;
|
|
44
44
|
const isMp3 = (data) => {
|
|
45
45
|
const mpegPattern = new Uint8Array([0xff, 0xf3, 0xe4, 0x64]);
|
|
46
|
-
const
|
|
46
|
+
const id3v3Pattern = new Uint8Array([73, 68, 51, 3]);
|
|
47
|
+
const id3v2Pattern = new Uint8Array([73, 68, 51, 2]);
|
|
47
48
|
const subarray = data.subarray(0, 4);
|
|
48
49
|
return ((0, exports.matchesPattern)(mpegPattern)(subarray) ||
|
|
49
|
-
(0, exports.matchesPattern)(
|
|
50
|
+
(0, exports.matchesPattern)(id3v3Pattern)(subarray) ||
|
|
51
|
+
(0, exports.matchesPattern)(id3v2Pattern)(subarray));
|
|
50
52
|
};
|
|
51
53
|
exports.isMp3 = isMp3;
|
|
52
54
|
const isGif = (data) => {
|
package/dist/get-audio-codec.js
CHANGED
|
@@ -23,7 +23,7 @@ const getAudioCodec = (boxes, parserState) => {
|
|
|
23
23
|
};
|
|
24
24
|
exports.getAudioCodec = getAudioCodec;
|
|
25
25
|
const hasAudioCodec = (boxes, state) => {
|
|
26
|
-
return (0, get_tracks_1.
|
|
26
|
+
return (0, get_tracks_1.getHasTracks)(boxes, state);
|
|
27
27
|
};
|
|
28
28
|
exports.hasAudioCodec = hasAudioCodec;
|
|
29
29
|
const getCodecSpecificatorFromEsdsBox = ({ child, }) => {
|
package/dist/get-container.js
CHANGED
|
@@ -12,12 +12,16 @@ const getContainer = (segments) => {
|
|
|
12
12
|
if (segments.type === 'transport-stream') {
|
|
13
13
|
return 'transport-stream';
|
|
14
14
|
}
|
|
15
|
+
if (segments.type === 'mp3') {
|
|
16
|
+
return 'mp3';
|
|
17
|
+
}
|
|
15
18
|
if (segments.type === 'riff') {
|
|
16
19
|
if ((0, traversal_1.isRiffAvi)(segments)) {
|
|
17
20
|
return 'avi';
|
|
18
21
|
}
|
|
22
|
+
throw new Error('Unknown RIFF container ' + segments.type);
|
|
19
23
|
}
|
|
20
|
-
throw new Error('Unknown container');
|
|
24
|
+
throw new Error('Unknown container ' + segments);
|
|
21
25
|
};
|
|
22
26
|
exports.getContainer = getContainer;
|
|
23
27
|
const hasContainer = (boxes) => {
|
package/dist/get-dimensions.d.ts
CHANGED
|
@@ -9,5 +9,5 @@ export type ExpandedDimensions = Dimensions & {
|
|
|
9
9
|
unrotatedWidth: number;
|
|
10
10
|
unrotatedHeight: number;
|
|
11
11
|
};
|
|
12
|
-
export declare const getDimensions: (boxes: Structure, state: ParserState) => ExpandedDimensions;
|
|
12
|
+
export declare const getDimensions: (boxes: Structure, state: ParserState) => ExpandedDimensions | null;
|
|
13
13
|
export declare const hasDimensions: (boxes: Structure, state: ParserState) => boolean;
|
package/dist/get-dimensions.js
CHANGED
|
@@ -5,6 +5,9 @@ const get_tracks_1 = require("./get-tracks");
|
|
|
5
5
|
const getDimensions = (boxes, state) => {
|
|
6
6
|
const { videoTracks } = (0, get_tracks_1.getTracks)(boxes, state);
|
|
7
7
|
if (!videoTracks.length) {
|
|
8
|
+
if (boxes.type === 'mp3') {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
8
11
|
throw new Error('Expected video track');
|
|
9
12
|
}
|
|
10
13
|
const firstVideoTrack = videoTracks[0];
|
package/dist/get-duration.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.hasSlowDuration = exports.hasDuration = exports.getDuration = exports.isMatroska = void 0;
|
|
4
4
|
const get_sample_positions_from_track_1 = require("./boxes/iso-base-media/get-sample-positions-from-track");
|
|
5
5
|
const traversal_1 = require("./boxes/iso-base-media/traversal");
|
|
6
|
+
const get_duration_1 = require("./boxes/mp3/get-duration");
|
|
6
7
|
const traversal_2 = require("./boxes/riff/traversal");
|
|
7
8
|
const get_tracks_1 = require("./get-tracks");
|
|
8
9
|
const getDurationFromMatroska = (segments) => {
|
|
@@ -92,13 +93,16 @@ const getDuration = (structure, parserState) => {
|
|
|
92
93
|
if (structure.type === 'transport-stream') {
|
|
93
94
|
return null;
|
|
94
95
|
}
|
|
96
|
+
if (structure.type === 'mp3') {
|
|
97
|
+
return (0, get_duration_1.getDurationFromMp3)(parserState);
|
|
98
|
+
}
|
|
95
99
|
throw new Error('Has no duration ' + structure);
|
|
96
100
|
};
|
|
97
101
|
exports.getDuration = getDuration;
|
|
98
102
|
// `duration` just grabs from metadata, and otherwise returns null
|
|
99
103
|
// Therefore just checking if we have tracks
|
|
100
104
|
const hasDuration = (structure, parserState) => {
|
|
101
|
-
return (0, get_tracks_1.
|
|
105
|
+
return (0, get_tracks_1.getHasTracks)(structure, parserState);
|
|
102
106
|
};
|
|
103
107
|
exports.hasDuration = hasDuration;
|
|
104
108
|
// `slowDuration` does through everything, and therefore is false
|
|
@@ -25,6 +25,7 @@ const getFieldsFromCallback = ({ fields, callbacks, }) => {
|
|
|
25
25
|
slowFps: Boolean(callbacks.onSlowFps),
|
|
26
26
|
slowNumberOfFrames: Boolean(callbacks.onSlowNumberOfFrames),
|
|
27
27
|
keyframes: Boolean(callbacks.onKeyframes),
|
|
28
|
+
images: Boolean(callbacks.onImages),
|
|
28
29
|
...fields,
|
|
29
30
|
};
|
|
30
31
|
return newFields;
|
package/dist/get-fps.js
CHANGED
|
@@ -101,6 +101,9 @@ const getFps = (segments) => {
|
|
|
101
101
|
if (segments.type === 'transport-stream') {
|
|
102
102
|
return null;
|
|
103
103
|
}
|
|
104
|
+
if (segments.type === 'mp3') {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
104
107
|
throw new Error('Cannot get fps, not implemented');
|
|
105
108
|
};
|
|
106
109
|
exports.getFps = getFps;
|
package/dist/get-is-hdr.js
CHANGED
package/dist/get-keyframes.js
CHANGED
|
@@ -12,7 +12,7 @@ const getKeyframes = (structure) => {
|
|
|
12
12
|
exports.getKeyframes = getKeyframes;
|
|
13
13
|
const hasKeyframes = (structure, parserState) => {
|
|
14
14
|
if (structure.type === 'iso-base-media') {
|
|
15
|
-
return (0, get_tracks_1.
|
|
15
|
+
return (0, get_tracks_1.getHasTracks)(structure, parserState);
|
|
16
16
|
}
|
|
17
17
|
// Has, but will be null
|
|
18
18
|
return true;
|
package/dist/get-tracks.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export type OtherTrack = {
|
|
|
57
57
|
export type Track = VideoTrack | AudioTrack | OtherTrack;
|
|
58
58
|
export declare const getNumberOfTracks: (moovBox: MoovBox) => number;
|
|
59
59
|
export declare const isoBaseMediaHasTracks: (structure: IsoBaseMediaStructure) => boolean;
|
|
60
|
-
export declare const
|
|
60
|
+
export declare const getHasTracks: (structure: Structure, state: ParserState) => boolean;
|
|
61
61
|
export declare const getTracksFromIsoBaseMedia: (segments: IsoBaseMediaBox[]) => {
|
|
62
62
|
videoTracks: VideoTrack[];
|
|
63
63
|
audioTracks: AudioTrack[];
|
package/dist/get-tracks.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTracks = exports.getTracksFromIsoBaseMedia = exports.
|
|
3
|
+
exports.getTracks = exports.getTracksFromIsoBaseMedia = exports.getHasTracks = exports.isoBaseMediaHasTracks = exports.getNumberOfTracks = void 0;
|
|
4
4
|
const make_track_1 = require("./boxes/iso-base-media/make-track");
|
|
5
5
|
const traversal_1 = require("./boxes/iso-base-media/traversal");
|
|
6
|
+
const get_tracks_from_mp3_1 = require("./boxes/mp3/get-tracks-from-mp3");
|
|
6
7
|
const get_tracks_from_avi_1 = require("./boxes/riff/get-tracks-from-avi");
|
|
7
8
|
const get_tracks_1 = require("./boxes/transport-stream/get-tracks");
|
|
8
9
|
const get_ready_tracks_1 = require("./boxes/webm/get-ready-tracks");
|
|
@@ -25,7 +26,7 @@ const isoBaseMediaHasTracks = (structure) => {
|
|
|
25
26
|
return tracks.length === numberOfTracks;
|
|
26
27
|
};
|
|
27
28
|
exports.isoBaseMediaHasTracks = isoBaseMediaHasTracks;
|
|
28
|
-
const
|
|
29
|
+
const getHasTracks = (structure, state) => {
|
|
29
30
|
if (structure.type === 'matroska') {
|
|
30
31
|
const mainSegment = (0, traversal_2.getMainSegment)(structure.boxes);
|
|
31
32
|
if (!mainSegment) {
|
|
@@ -42,9 +43,12 @@ const hasTracks = (structure, state) => {
|
|
|
42
43
|
if (structure.type === 'transport-stream') {
|
|
43
44
|
return (0, get_tracks_1.hasAllTracksFromTransportStream)(structure, state);
|
|
44
45
|
}
|
|
46
|
+
if (structure.type === 'mp3') {
|
|
47
|
+
return state.callbacks.tracks.getTracks().length > 0;
|
|
48
|
+
}
|
|
45
49
|
throw new Error('Unknown container ' + structure);
|
|
46
50
|
};
|
|
47
|
-
exports.
|
|
51
|
+
exports.getHasTracks = getHasTracks;
|
|
48
52
|
const getTracksFromMa = (segments, state) => {
|
|
49
53
|
const videoTracks = [];
|
|
50
54
|
const audioTracks = [];
|
|
@@ -119,6 +123,9 @@ const getTracks = (segments, state) => {
|
|
|
119
123
|
if (segments.type === 'transport-stream') {
|
|
120
124
|
return (0, get_tracks_1.getTracksFromTransportStream)(segments, state);
|
|
121
125
|
}
|
|
126
|
+
if (segments.type === 'mp3') {
|
|
127
|
+
return (0, get_tracks_from_mp3_1.getTracksFromMp3)(state);
|
|
128
|
+
}
|
|
122
129
|
throw new Error(`Unknown container${segments}`);
|
|
123
130
|
};
|
|
124
131
|
exports.getTracks = getTracks;
|
package/dist/get-video-codec.js
CHANGED
|
@@ -12,7 +12,7 @@ const getVideoCodec = (boxes, state) => {
|
|
|
12
12
|
};
|
|
13
13
|
exports.getVideoCodec = getVideoCodec;
|
|
14
14
|
const hasVideoCodec = (boxes, state) => {
|
|
15
|
-
return (0, get_tracks_1.
|
|
15
|
+
return (0, get_tracks_1.getHasTracks)(boxes, state);
|
|
16
16
|
};
|
|
17
17
|
exports.hasVideoCodec = hasVideoCodec;
|
|
18
18
|
const getVideoPrivateData = (trakBox) => {
|
package/dist/has-all-info.js
CHANGED
|
@@ -11,6 +11,7 @@ const get_keyframes_1 = require("./get-keyframes");
|
|
|
11
11
|
const get_tracks_1 = require("./get-tracks");
|
|
12
12
|
const get_video_codec_1 = require("./get-video-codec");
|
|
13
13
|
const may_skip_video_data_1 = require("./may-skip-video-data/may-skip-video-data");
|
|
14
|
+
const get_metadata_1 = require("./metadata/get-metadata");
|
|
14
15
|
const getAvailableInfo = ({ fieldsToFetch, state, }) => {
|
|
15
16
|
const keys = Object.entries(fieldsToFetch).filter(([, value]) => value);
|
|
16
17
|
const structure = state.structure.getStructureOrNull();
|
|
@@ -47,7 +48,7 @@ const getAvailableInfo = ({ fieldsToFetch, state, }) => {
|
|
|
47
48
|
return Boolean(structure && (0, get_audio_codec_1.hasAudioCodec)(structure, state));
|
|
48
49
|
}
|
|
49
50
|
if (key === 'tracks') {
|
|
50
|
-
return Boolean(structure && (0, get_tracks_1.
|
|
51
|
+
return Boolean(structure && (0, get_tracks_1.getHasTracks)(structure, state));
|
|
51
52
|
}
|
|
52
53
|
if (key === 'keyframes') {
|
|
53
54
|
return Boolean(structure && (0, get_keyframes_1.hasKeyframes)(structure, state));
|
|
@@ -67,8 +68,8 @@ const getAvailableInfo = ({ fieldsToFetch, state, }) => {
|
|
|
67
68
|
if (key === 'container') {
|
|
68
69
|
return Boolean(structure && (0, get_container_1.hasContainer)(structure));
|
|
69
70
|
}
|
|
70
|
-
if (key === 'metadata' || key === 'location') {
|
|
71
|
-
return
|
|
71
|
+
if (key === 'metadata' || key === 'location' || key === 'images') {
|
|
72
|
+
return Boolean(structure && (0, get_metadata_1.hasMetadata)(structure));
|
|
72
73
|
}
|
|
73
74
|
if (key === 'slowKeyframes') {
|
|
74
75
|
return false;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { IsAGifError, IsAnImageError, IsAnUnsupportedAudioTypeError, IsAnUnsuppo
|
|
|
5
5
|
export type { SamplePosition } from './get-sample-positions';
|
|
6
6
|
export { MetadataEntry } from './metadata/get-metadata';
|
|
7
7
|
export { MediaParserKeyframe } from './options';
|
|
8
|
+
export type { MediaParserEmbeddedImage } from './state/images';
|
|
8
9
|
export { AudioTrack, MediaParserAudioCodec, MediaParserVideoCodec, OtherTrack, Track, VideoTrack, VideoTrackColorParams, } from './get-tracks';
|
|
9
10
|
export type { Options, ParseMediaContainer, ParseMediaDynamicOptions, ParseMediaFields, ParseMediaOnProgress, ParseMediaOptions, ParseMediaProgress, ParseMediaResult, TracksField, } from './options';
|
|
10
11
|
export { parseMedia } from './parse-media';
|
|
@@ -694,6 +695,9 @@ export declare const MediaParserInternals: {
|
|
|
694
695
|
getPascalString: () => number[];
|
|
695
696
|
getUint(length: number): number;
|
|
696
697
|
getByteString(length: number, trimTrailingZeroes: boolean): string;
|
|
698
|
+
planBytes: (size: number) => {
|
|
699
|
+
discardRest: () => Uint8Array;
|
|
700
|
+
};
|
|
697
701
|
getFloat64: () => number;
|
|
698
702
|
readUntilNullTerminator: () => string;
|
|
699
703
|
getFloat32: () => number;
|
|
@@ -708,6 +712,9 @@ export declare const MediaParserInternals: {
|
|
|
708
712
|
expectNoMoreBytes: () => void;
|
|
709
713
|
};
|
|
710
714
|
readExpGolomb: () => number;
|
|
715
|
+
startCheckpoint: () => {
|
|
716
|
+
returnToCheckpoint: () => void;
|
|
717
|
+
};
|
|
711
718
|
};
|
|
712
719
|
parseStsd: ({ iterator, offset, size, state, signal, fields, }: {
|
|
713
720
|
iterator: import("./buffer-iterator").BufferIterator;
|
|
@@ -717,7 +724,7 @@ export declare const MediaParserInternals: {
|
|
|
717
724
|
signal: AbortSignal | null;
|
|
718
725
|
fields: import("./options").Options<import("./options").ParseMediaFields>;
|
|
719
726
|
}) => Promise<import("./boxes/iso-base-media/stsd/stsd").StsdBox>;
|
|
720
|
-
makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHandlers, signal, getIterator, fields, onAudioTrack, onVideoTrack, supportsContentRange, }: {
|
|
727
|
+
makeParserState: ({ hasAudioTrackHandlers, hasVideoTrackHandlers, signal, getIterator, fields, onAudioTrack, onVideoTrack, supportsContentRange, contentLength, }: {
|
|
721
728
|
hasAudioTrackHandlers: boolean;
|
|
722
729
|
hasVideoTrackHandlers: boolean;
|
|
723
730
|
signal: AbortSignal | undefined;
|
|
@@ -726,6 +733,7 @@ export declare const MediaParserInternals: {
|
|
|
726
733
|
supportsContentRange: boolean;
|
|
727
734
|
onAudioTrack: import("./webcodec-sample-types").OnAudioTrack | null;
|
|
728
735
|
onVideoTrack: import("./webcodec-sample-types").OnVideoTrack | null;
|
|
736
|
+
contentLength: number | null;
|
|
729
737
|
}) => {
|
|
730
738
|
riff: {
|
|
731
739
|
getAvcProfile: () => import("./state/parser-state").SpsAndPps | null;
|
|
@@ -780,11 +788,21 @@ export declare const MediaParserInternals: {
|
|
|
780
788
|
emittedFields: import("./options").AllOptions<import("./options").ParseMediaFields>;
|
|
781
789
|
fields: Partial<import("./options").AllOptions<import("./options").ParseMediaFields>>;
|
|
782
790
|
slowDurationAndFps: {
|
|
783
|
-
|
|
791
|
+
addVideoSample: (videoSample: import("./webcodec-sample-types").AudioOrVideoSample) => void;
|
|
792
|
+
addAudioSample: (audioSample: import("./webcodec-sample-types").AudioOrVideoSample) => void;
|
|
784
793
|
getSlowDurationInSeconds: () => number;
|
|
785
794
|
getFps: () => number;
|
|
786
795
|
getSlowNumberOfFrames: () => number;
|
|
787
796
|
};
|
|
797
|
+
mp3Info: {
|
|
798
|
+
getMp3Info: () => import("./state/mp3").Mp3Info | null;
|
|
799
|
+
setMp3Info: (info: import("./state/mp3").Mp3Info) => void;
|
|
800
|
+
};
|
|
801
|
+
contentLength: number | null;
|
|
802
|
+
images: {
|
|
803
|
+
images: import("./state/images").MediaParserEmbeddedImage[];
|
|
804
|
+
addImage: (image: import("./state/images").MediaParserEmbeddedImage) => void;
|
|
805
|
+
};
|
|
788
806
|
};
|
|
789
807
|
processSample: ({ iterator, state: options, signal, logLevel, fields, }: {
|
|
790
808
|
iterator: import("./buffer-iterator").BufferIterator;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getMetadata = void 0;
|
|
3
|
+
exports.hasMetadata = exports.getMetadata = void 0;
|
|
4
|
+
const get_metadata_from_mp3_1 = require("../boxes/mp3/get-metadata-from-mp3");
|
|
4
5
|
const metadata_from_iso_1 = require("./metadata-from-iso");
|
|
5
6
|
const metadata_from_matroska_1 = require("./metadata-from-matroska");
|
|
6
7
|
const metadata_from_riff_1 = require("./metadata-from-riff");
|
|
@@ -14,6 +15,20 @@ const getMetadata = (structure) => {
|
|
|
14
15
|
if (structure.type === 'transport-stream') {
|
|
15
16
|
return [];
|
|
16
17
|
}
|
|
18
|
+
if (structure.type === 'mp3') {
|
|
19
|
+
const tags = (0, get_metadata_from_mp3_1.getMetadataFromMp3)(structure);
|
|
20
|
+
if (tags === null) {
|
|
21
|
+
throw new Error('Failed to get metadata from mp3');
|
|
22
|
+
}
|
|
23
|
+
return tags;
|
|
24
|
+
}
|
|
17
25
|
return (0, metadata_from_iso_1.getMetadataFromIsoBase)(structure);
|
|
18
26
|
};
|
|
19
27
|
exports.getMetadata = getMetadata;
|
|
28
|
+
const hasMetadata = (structure) => {
|
|
29
|
+
if (structure.type === 'mp3') {
|
|
30
|
+
return (0, get_metadata_from_mp3_1.getMetadataFromMp3)(structure) !== null;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
exports.hasMetadata = hasMetadata;
|
package/dist/options.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { LogLevel } from './log';
|
|
|
5
5
|
import type { MetadataEntry } from './metadata/get-metadata';
|
|
6
6
|
import type { Structure } from './parse-result';
|
|
7
7
|
import type { ReaderInterface } from './readers/reader';
|
|
8
|
+
import type { MediaParserEmbeddedImage } from './state/images';
|
|
8
9
|
import type { InternalStats } from './state/parser-state';
|
|
9
10
|
import type { OnAudioTrack, OnVideoTrack } from './webcodec-sample-types';
|
|
10
11
|
export type KnownAudioCodecs = 'aac' | 'mp3' | 'aiff' | 'opus' | 'pcm' | 'vorbis' | 'unknown';
|
|
@@ -31,6 +32,7 @@ export type ParseMediaFields = {
|
|
|
31
32
|
keyframes: boolean;
|
|
32
33
|
slowKeyframes: boolean;
|
|
33
34
|
slowNumberOfFrames: boolean;
|
|
35
|
+
images: boolean;
|
|
34
36
|
};
|
|
35
37
|
export type AllParseMediaFields = {
|
|
36
38
|
dimensions: true;
|
|
@@ -55,6 +57,7 @@ export type AllParseMediaFields = {
|
|
|
55
57
|
mimeType: true;
|
|
56
58
|
keyframes: true;
|
|
57
59
|
slowKeyframes: true;
|
|
60
|
+
images: true;
|
|
58
61
|
};
|
|
59
62
|
export type AllOptions<Fields extends ParseMediaFields> = {
|
|
60
63
|
dimensions: Fields['dimensions'];
|
|
@@ -79,13 +82,14 @@ export type AllOptions<Fields extends ParseMediaFields> = {
|
|
|
79
82
|
keyframes: Fields['keyframes'];
|
|
80
83
|
slowKeyframes: Fields['slowKeyframes'];
|
|
81
84
|
slowNumberOfFrames: Fields['slowNumberOfFrames'];
|
|
85
|
+
images: Fields['images'];
|
|
82
86
|
};
|
|
83
87
|
export type Options<Fields extends ParseMediaFields> = Partial<AllOptions<Fields>>;
|
|
84
88
|
export type TracksField = {
|
|
85
89
|
videoTracks: VideoTrack[];
|
|
86
90
|
audioTracks: AudioTrack[];
|
|
87
91
|
};
|
|
88
|
-
export type ParseMediaContainer = 'mp4' | 'webm' | 'avi' | 'transport-stream';
|
|
92
|
+
export type ParseMediaContainer = 'mp4' | 'webm' | 'avi' | 'transport-stream' | 'mp3';
|
|
89
93
|
export type MediaParserKeyframe = {
|
|
90
94
|
positionInBytes: number;
|
|
91
95
|
sizeInBytes: number;
|
|
@@ -94,7 +98,7 @@ export type MediaParserKeyframe = {
|
|
|
94
98
|
trackId: number;
|
|
95
99
|
};
|
|
96
100
|
export interface ParseMediaCallbacks {
|
|
97
|
-
onDimensions?: (dimensions: Dimensions) => void;
|
|
101
|
+
onDimensions?: (dimensions: Dimensions | null) => void;
|
|
98
102
|
onDurationInSeconds?: (durationInSeconds: number | null) => void;
|
|
99
103
|
onSlowDurationInSeconds?: (durationInSeconds: number) => void;
|
|
100
104
|
onSlowFps?: (fps: number) => void;
|
|
@@ -104,7 +108,7 @@ export interface ParseMediaCallbacks {
|
|
|
104
108
|
onAudioCodec?: (codec: MediaParserAudioCodec | null) => void;
|
|
105
109
|
onTracks?: (tracks: TracksField) => void;
|
|
106
110
|
onRotation?: (rotation: number | null) => void;
|
|
107
|
-
onUnrotatedDimensions?: (dimensions: Dimensions) => void;
|
|
111
|
+
onUnrotatedDimensions?: (dimensions: Dimensions | null) => void;
|
|
108
112
|
onInternalStats?: (internalStats: InternalStats) => void;
|
|
109
113
|
onSize?: (size: number | null) => void;
|
|
110
114
|
onName?: (name: string) => void;
|
|
@@ -116,9 +120,10 @@ export interface ParseMediaCallbacks {
|
|
|
116
120
|
onKeyframes?: (keyframes: MediaParserKeyframe[] | null) => void;
|
|
117
121
|
onSlowKeyframes?: (keyframes: MediaParserKeyframe[]) => void;
|
|
118
122
|
onSlowNumberOfFrames?: (samples: number) => void;
|
|
123
|
+
onImages?: (images: MediaParserEmbeddedImage[]) => void;
|
|
119
124
|
}
|
|
120
125
|
export interface ParseMediaData {
|
|
121
|
-
dimensions: Dimensions;
|
|
126
|
+
dimensions: Dimensions | null;
|
|
122
127
|
durationInSeconds: number | null;
|
|
123
128
|
slowDurationInSeconds: number;
|
|
124
129
|
slowFps: number;
|
|
@@ -128,7 +133,7 @@ export interface ParseMediaData {
|
|
|
128
133
|
audioCodec: MediaParserAudioCodec | null;
|
|
129
134
|
tracks: TracksField;
|
|
130
135
|
rotation: number | null;
|
|
131
|
-
unrotatedDimensions: Dimensions;
|
|
136
|
+
unrotatedDimensions: Dimensions | null;
|
|
132
137
|
isHdr: boolean;
|
|
133
138
|
internalStats: InternalStats;
|
|
134
139
|
size: number | null;
|
|
@@ -140,6 +145,7 @@ export interface ParseMediaData {
|
|
|
140
145
|
keyframes: MediaParserKeyframe[] | null;
|
|
141
146
|
slowKeyframes: MediaParserKeyframe[];
|
|
142
147
|
slowNumberOfFrames: number;
|
|
148
|
+
images: MediaParserEmbeddedImage[];
|
|
143
149
|
}
|
|
144
150
|
export type ParseMediaResult<T extends Partial<ParseMediaFields>> = {
|
|
145
151
|
[K in keyof T]: T[K] extends true ? K extends keyof ParseMediaData ? ParseMediaData[K] : never : never;
|
|
@@ -161,5 +167,6 @@ export type ParseMediaOptions<F extends Options<ParseMediaFields>> = {
|
|
|
161
167
|
signal?: AbortSignal;
|
|
162
168
|
logLevel?: LogLevel;
|
|
163
169
|
onParseProgress?: ParseMediaOnProgress;
|
|
170
|
+
progressIntervalInMs?: number;
|
|
164
171
|
} & ParseMediaDynamicOptions<F>;
|
|
165
172
|
export type ParseMedia = <F extends Options<ParseMediaFields>>(options: ParseMediaOptions<F>) => Promise<ParseMediaResult<F>>;
|
package/dist/parse-media.js
CHANGED
|
@@ -9,8 +9,9 @@ const log_1 = require("./log");
|
|
|
9
9
|
const parse_video_1 = require("./parse-video");
|
|
10
10
|
const from_fetch_1 = require("./readers/from-fetch");
|
|
11
11
|
const parser_state_1 = require("./state/parser-state");
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const throttled_progress_1 = require("./throttled-progress");
|
|
13
|
+
const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, logLevel = 'info', onParseProgress: onParseProgressDoNotCallDirectly, progressIntervalInMs, ...more }) {
|
|
14
|
+
var _a;
|
|
14
15
|
let parseResult = null;
|
|
15
16
|
const fieldsInReturnValue = _fieldsInReturnValue !== null && _fieldsInReturnValue !== void 0 ? _fieldsInReturnValue : {};
|
|
16
17
|
const fields = (0, get_fields_from_callbacks_1.getFieldsFromCallback)({
|
|
@@ -18,6 +19,7 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
|
|
|
18
19
|
callbacks: more,
|
|
19
20
|
});
|
|
20
21
|
const { reader, contentLength, name, contentType, supportsContentRange: readerSupportsContentRange, } = await readerInterface.read(src, null, signal);
|
|
22
|
+
const iterator = (0, buffer_iterator_1.getArrayBufferIterator)(new Uint8Array([]), contentLength !== null && contentLength !== void 0 ? contentLength : 1000000000);
|
|
21
23
|
const supportsContentRange = readerSupportsContentRange &&
|
|
22
24
|
!(typeof process !== 'undefined' &&
|
|
23
25
|
typeof process.env !== 'undefined' &&
|
|
@@ -31,10 +33,17 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
|
|
|
31
33
|
onAudioTrack: onAudioTrack !== null && onAudioTrack !== void 0 ? onAudioTrack : null,
|
|
32
34
|
onVideoTrack: onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : null,
|
|
33
35
|
supportsContentRange,
|
|
36
|
+
contentLength,
|
|
34
37
|
});
|
|
35
38
|
let currentReader = reader;
|
|
36
39
|
const returnValue = {};
|
|
37
40
|
const moreFields = more;
|
|
41
|
+
const throttledState = (0, throttled_progress_1.throttledStateUpdate)({
|
|
42
|
+
updateFn: onParseProgressDoNotCallDirectly !== null && onParseProgressDoNotCallDirectly !== void 0 ? onParseProgressDoNotCallDirectly : null,
|
|
43
|
+
everyMilliseconds: progressIntervalInMs !== null && progressIntervalInMs !== void 0 ? progressIntervalInMs : 100,
|
|
44
|
+
signal,
|
|
45
|
+
totalBytes: contentLength,
|
|
46
|
+
});
|
|
38
47
|
const triggerInfoEmit = () => {
|
|
39
48
|
const availableInfo = (0, has_all_info_1.getAvailableInfo)({
|
|
40
49
|
fieldsToFetch: fields,
|
|
@@ -52,35 +61,41 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
|
|
|
52
61
|
mimeType: contentType,
|
|
53
62
|
});
|
|
54
63
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
const checkIfDone = () => {
|
|
65
|
+
if ((0, has_all_info_1.hasAllInfo)({
|
|
66
|
+
fields,
|
|
67
|
+
state,
|
|
68
|
+
})) {
|
|
69
|
+
log_1.Log.verbose(logLevel, 'Got all info, skipping to the end.');
|
|
70
|
+
if (contentLength !== null) {
|
|
71
|
+
state.increaseSkippedBytes(contentLength - iterator.counter.getOffset());
|
|
60
72
|
}
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
};
|
|
77
|
+
triggerInfoEmit();
|
|
78
|
+
let didProgress = false;
|
|
79
|
+
while (!checkIfDone() &&
|
|
80
|
+
(parseResult === null || parseResult.status === 'incomplete')) {
|
|
81
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
82
|
+
throw new Error('Aborted');
|
|
83
|
+
}
|
|
84
|
+
const offsetBefore = iterator.counter.getOffset();
|
|
85
|
+
const fetchMoreData = async () => {
|
|
61
86
|
const result = await currentReader.reader.read();
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
iterator.addData(result.value);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
if (result.done) {
|
|
69
|
-
throw new Error('Unexpectedly reached EOF');
|
|
70
|
-
}
|
|
71
|
-
iterator = (0, buffer_iterator_1.getArrayBufferIterator)(result.value, contentLength !== null && contentLength !== void 0 ? contentLength : 1000000000);
|
|
72
|
-
}
|
|
73
|
-
if (iterator.bytesRemaining() >= 0) {
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
if (result.done) {
|
|
77
|
-
break;
|
|
87
|
+
if (result.value) {
|
|
88
|
+
iterator.addData(result.value);
|
|
78
89
|
}
|
|
90
|
+
};
|
|
91
|
+
while (iterator.bytesRemaining() < 0) {
|
|
92
|
+
await fetchMoreData();
|
|
79
93
|
}
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
const hasBigBuffer = iterator.bytesRemaining() > 100000;
|
|
95
|
+
if (!didProgress || !hasBigBuffer) {
|
|
96
|
+
await fetchMoreData();
|
|
82
97
|
}
|
|
83
|
-
|
|
98
|
+
(_a = throttledState.update) === null || _a === void 0 ? void 0 : _a.call(throttledState, () => ({
|
|
84
99
|
bytes: iterator.counter.getOffset(),
|
|
85
100
|
percentage: contentLength
|
|
86
101
|
? iterator.counter.getOffset() / contentLength
|
|
@@ -107,16 +122,6 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
|
|
|
107
122
|
if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
|
|
108
123
|
state.increaseSkippedBytes(parseResult.skipTo - iterator.counter.getOffset());
|
|
109
124
|
}
|
|
110
|
-
if ((0, has_all_info_1.hasAllInfo)({
|
|
111
|
-
fields,
|
|
112
|
-
state,
|
|
113
|
-
})) {
|
|
114
|
-
log_1.Log.verbose(logLevel, 'Got all info, skipping to the end.');
|
|
115
|
-
if (contentLength !== null) {
|
|
116
|
-
state.increaseSkippedBytes(contentLength - iterator.counter.getOffset());
|
|
117
|
-
}
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
125
|
if (parseResult.status === 'incomplete' && parseResult.skipTo !== null) {
|
|
121
126
|
if (!supportsContentRange) {
|
|
122
127
|
throw new Error('Content-Range header is not supported by the reader, but was asked to seek');
|
|
@@ -131,17 +136,17 @@ const parseMedia = async function ({ src, fields: _fieldsInReturnValue, reader:
|
|
|
131
136
|
currentReader = newReader;
|
|
132
137
|
iterator.skipTo(parseResult.skipTo, true);
|
|
133
138
|
}
|
|
139
|
+
didProgress = iterator.counter.getOffset() > offsetBefore;
|
|
134
140
|
}
|
|
135
141
|
log_1.Log.verbose(logLevel, 'Finished parsing file');
|
|
136
|
-
const hasInfo = Object.keys(fields).reduce((acc, key) => {
|
|
137
|
-
if (fields === null || fields === void 0 ? void 0 : fields[key]) {
|
|
138
|
-
acc[key] = true;
|
|
139
|
-
}
|
|
140
|
-
return acc;
|
|
141
|
-
}, {});
|
|
142
142
|
// Force assign
|
|
143
143
|
(0, emit_available_info_1.emitAvailableInfo)({
|
|
144
|
-
hasInfo,
|
|
144
|
+
hasInfo: Object.keys(fields).reduce((acc, key) => {
|
|
145
|
+
if (fields === null || fields === void 0 ? void 0 : fields[key]) {
|
|
146
|
+
acc[key] = true;
|
|
147
|
+
}
|
|
148
|
+
return acc;
|
|
149
|
+
}, {}),
|
|
145
150
|
callbacks: moreFields,
|
|
146
151
|
fieldsInReturnValue,
|
|
147
152
|
parseResult,
|
package/dist/parse-result.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ import type { VoidBox } from './boxes/iso-base-media/void-box';
|
|
|
30
30
|
import type { RiffBox } from './boxes/riff/riff-box';
|
|
31
31
|
import type { TransportStreamBox } from './boxes/transport-stream/boxes';
|
|
32
32
|
import type { MatroskaSegment } from './boxes/webm/segments';
|
|
33
|
+
import type { MetadataEntry } from './metadata/get-metadata';
|
|
33
34
|
export interface RegularBox extends BaseBox {
|
|
34
35
|
boxType: string;
|
|
35
36
|
boxSize: number;
|
|
@@ -38,6 +39,15 @@ export interface RegularBox extends BaseBox {
|
|
|
38
39
|
type: 'regular-box';
|
|
39
40
|
}
|
|
40
41
|
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | IlstBox | EsdsBox | MdatBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | HdlrBox | ColorParameterBox | TfdtBox | TfhdBox;
|
|
42
|
+
type Mp3Id3Header = {
|
|
43
|
+
type: 'id3-header';
|
|
44
|
+
versionMajor: number;
|
|
45
|
+
versionMinor: number;
|
|
46
|
+
flags: number;
|
|
47
|
+
size: number;
|
|
48
|
+
metatags: MetadataEntry[];
|
|
49
|
+
};
|
|
50
|
+
export type Mp3Box = Mp3Id3Header;
|
|
41
51
|
export type AnySegment = MatroskaSegment | IsoBaseMediaBox | RiffBox | TransportStreamBox;
|
|
42
52
|
export type IsoBaseMediaStructure = {
|
|
43
53
|
type: 'iso-base-media';
|
|
@@ -55,7 +65,11 @@ export type TransportStreamStructure = {
|
|
|
55
65
|
type: 'transport-stream';
|
|
56
66
|
boxes: TransportStreamBox[];
|
|
57
67
|
};
|
|
58
|
-
export type
|
|
68
|
+
export type Mp3Structure = {
|
|
69
|
+
type: 'mp3';
|
|
70
|
+
boxes: Mp3Box[];
|
|
71
|
+
};
|
|
72
|
+
export type Structure = IsoBaseMediaStructure | RiffStructure | MatroskaStructure | TransportStreamStructure | Mp3Structure;
|
|
59
73
|
export type ParseResult = {
|
|
60
74
|
status: 'done';
|
|
61
75
|
} | {
|
|
@@ -78,3 +92,4 @@ export type ExpectSegmentParseResult = {
|
|
|
78
92
|
segment: MatroskaSegment | null;
|
|
79
93
|
continueParsing: () => Promise<ExpectSegmentParseResult>;
|
|
80
94
|
};
|
|
95
|
+
export {};
|