@remotion/media-parser 4.0.230 → 4.0.232
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/add-avc-profile-to-track.d.ts +3 -0
- package/dist/add-avc-profile-to-track.js +35 -0
- package/dist/add-new-matroska-tracks.d.ts +6 -1
- package/dist/add-new-matroska-tracks.js +16 -1
- package/dist/boxes/avc/parse-avc.d.ts +18 -0
- package/dist/boxes/avc/parse-avc.js +96 -0
- package/dist/boxes/iso-base-media/make-track.js +3 -3
- package/dist/boxes/iso-base-media/mdat/mdat.d.ts +2 -2
- package/dist/boxes/iso-base-media/mdat/mdat.js +5 -2
- package/dist/boxes/iso-base-media/moov/moov.js +2 -2
- package/dist/boxes/iso-base-media/process-box.d.ts +5 -5
- package/dist/boxes/iso-base-media/process-box.js +38 -37
- package/dist/boxes/iso-base-media/stsd/mebx.js +2 -2
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -2
- package/dist/boxes/iso-base-media/stsd/samples.js +9 -9
- package/dist/boxes/iso-base-media/trak/trak.js +2 -2
- package/dist/boxes/iso-base-media/traversal.d.ts +1 -1
- package/dist/boxes/riff/expect-riff-box.d.ts +16 -0
- package/dist/boxes/riff/expect-riff-box.js +49 -0
- package/dist/boxes/riff/get-tracks-from-avi.d.ts +21 -0
- package/dist/boxes/riff/get-tracks-from-avi.js +108 -0
- package/dist/boxes/riff/is-movi.d.ts +2 -0
- package/dist/boxes/riff/is-movi.js +12 -0
- package/dist/boxes/riff/parse-avih.d.ts +6 -0
- package/dist/boxes/riff/parse-avih.js +32 -0
- package/dist/boxes/riff/parse-box.d.ts +13 -0
- package/dist/boxes/riff/parse-box.js +113 -0
- package/dist/boxes/riff/parse-fmt-box.d.ts +7 -0
- package/dist/boxes/riff/parse-fmt-box.js +33 -0
- package/dist/boxes/riff/parse-list-box.d.ts +8 -0
- package/dist/boxes/riff/parse-list-box.js +30 -0
- package/dist/boxes/riff/parse-movi.d.ts +17 -0
- package/dist/boxes/riff/parse-movi.js +122 -0
- package/dist/boxes/riff/parse-riff-box.d.ts +10 -0
- package/dist/boxes/riff/parse-riff-box.js +33 -0
- package/dist/boxes/riff/parse-strf.d.ts +7 -0
- package/dist/boxes/riff/parse-strf.js +67 -0
- package/dist/boxes/riff/parse-strh.d.ts +6 -0
- package/dist/boxes/riff/parse-strh.js +46 -0
- package/dist/boxes/riff/riff-box.d.ts +81 -0
- package/dist/boxes/riff/riff-box.js +2 -0
- package/dist/boxes/riff/strf.d.ts +7 -0
- package/dist/boxes/riff/strf.js +67 -0
- package/dist/boxes/riff/timescale.d.ts +1 -0
- package/dist/boxes/riff/timescale.js +4 -0
- package/dist/boxes/riff/traversal.d.ts +8 -0
- package/dist/boxes/riff/traversal.js +36 -0
- package/dist/boxes/webm/parse-ebml.js +2 -2
- package/dist/boxes/webm/parse-webm-header.d.ts +2 -2
- package/dist/boxes/webm/parse-webm-header.js +23 -4
- package/dist/boxes/webm/segments/parse-children.d.ts +12 -7
- package/dist/boxes/webm/segments/parse-children.js +67 -57
- package/dist/boxes/webm/segments.d.ts +8 -3
- package/dist/boxes/webm/segments.js +70 -39
- package/dist/boxes/webm/traversal.d.ts +2 -2
- package/dist/buffer-iterator.d.ts +6 -1
- package/dist/buffer-iterator.js +24 -5
- package/dist/create/iso-base-media/create-iso-base-media.d.ts +1 -1
- package/dist/create/iso-base-media/create-iso-base-media.js +4 -9
- package/dist/create/matroska/cluster.d.ts +7 -1
- package/dist/create/matroska/cluster.js +8 -5
- package/dist/create/matroska/create-matroska-media.d.ts +1 -1
- package/dist/create/matroska/create-matroska-media.js +27 -14
- package/dist/create/media-fn.d.ts +1 -1
- package/dist/create/mp3/create-mp3.d.ts +2 -0
- package/dist/create/mp3/create-mp3.js +49 -0
- package/dist/create/wav/create-wav.d.ts +2 -0
- package/dist/create/wav/create-wav.js +108 -0
- package/dist/emit-available-info.d.ts +2 -2
- package/dist/emit-available-info.js +28 -13
- package/dist/esm/buffer.mjs +2 -2
- package/dist/esm/from-node.mjs +2 -1
- package/dist/esm/index.mjs +1513 -331
- package/dist/esm/web-fs.mjs +2 -2
- package/dist/get-audio-codec.d.ts +3 -3
- package/dist/get-audio-codec.js +1 -6
- package/dist/get-container.d.ts +3 -3
- package/dist/get-container.js +9 -7
- package/dist/get-dimensions.d.ts +3 -3
- package/dist/get-duration.d.ts +8 -3
- package/dist/get-duration.js +37 -15
- package/dist/get-fps.d.ts +3 -3
- package/dist/get-fps.js +36 -2
- package/dist/get-tracks.d.ts +4 -7
- package/dist/get-tracks.js +55 -27
- package/dist/get-video-codec.d.ts +5 -4
- package/dist/get-video-codec.js +39 -15
- package/dist/has-all-info.d.ts +2 -2
- package/dist/has-all-info.js +9 -9
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -1
- package/dist/options.d.ts +17 -10
- package/dist/parse-media.js +43 -14
- package/dist/parse-result.d.ts +35 -6
- package/dist/parse-video.d.ts +3 -3
- package/dist/parse-video.js +8 -16
- package/dist/parser-context.d.ts +1 -0
- package/dist/parser-state.d.ts +11 -0
- package/dist/parser-state.js +30 -0
- package/dist/readers/from-node.js +2 -1
- package/dist/readers/reader.d.ts +2 -2
- package/dist/register-track.d.ts +13 -0
- package/dist/register-track.js +25 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +5 -0
- package/dist/writers/buffer-implementation/writer.d.ts +2 -2
- package/dist/writers/buffer-implementation/writer.js +2 -2
- package/dist/writers/web-fs.js +2 -3
- package/dist/writers/writer.d.ts +5 -3
- package/package.json +3 -3
package/dist/options.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Dimensions } from './get-dimensions';
|
|
2
2
|
import type { AudioTrack, MediaParserAudioCodec, MediaParserVideoCodec, VideoTrack } from './get-tracks';
|
|
3
3
|
import type { LogLevel } from './log';
|
|
4
|
-
import type {
|
|
4
|
+
import type { Structure } from './parse-result';
|
|
5
5
|
import type { InternalStats } from './parser-state';
|
|
6
6
|
import type { ReaderInterface } from './readers/reader';
|
|
7
7
|
import type { OnAudioTrack, OnVideoTrack } from './webcodec-sample-types';
|
|
@@ -9,7 +9,7 @@ export type KnownAudioCodecs = 'aac' | 'mp3' | 'aiff' | 'opus' | 'pcm' | 'vorbis
|
|
|
9
9
|
export type ParseMediaFields = {
|
|
10
10
|
dimensions: boolean;
|
|
11
11
|
durationInSeconds: boolean;
|
|
12
|
-
|
|
12
|
+
structure: boolean;
|
|
13
13
|
fps: boolean;
|
|
14
14
|
videoCodec: boolean;
|
|
15
15
|
audioCodec: boolean;
|
|
@@ -24,7 +24,7 @@ export type ParseMediaFields = {
|
|
|
24
24
|
export type AllParseMediaFields = {
|
|
25
25
|
dimensions: true;
|
|
26
26
|
durationInSeconds: true;
|
|
27
|
-
|
|
27
|
+
structure: true;
|
|
28
28
|
fps: true;
|
|
29
29
|
videoCodec: true;
|
|
30
30
|
audioCodec: true;
|
|
@@ -39,7 +39,7 @@ export type AllParseMediaFields = {
|
|
|
39
39
|
export type Options<Fields extends ParseMediaFields> = {
|
|
40
40
|
dimensions?: Fields['dimensions'];
|
|
41
41
|
durationInSeconds?: Fields['durationInSeconds'];
|
|
42
|
-
|
|
42
|
+
structure?: Fields['structure'];
|
|
43
43
|
fps?: Fields['fps'];
|
|
44
44
|
videoCodec?: Fields['videoCodec'];
|
|
45
45
|
audioCodec?: Fields['audioCodec'];
|
|
@@ -55,13 +55,13 @@ export type TracksField = {
|
|
|
55
55
|
videoTracks: VideoTrack[];
|
|
56
56
|
audioTracks: AudioTrack[];
|
|
57
57
|
};
|
|
58
|
-
export type ParseMediaContainer = 'mp4' | 'webm';
|
|
58
|
+
export type ParseMediaContainer = 'mp4' | 'webm' | 'avi';
|
|
59
59
|
export type ParseMediaCallbacks<Fields extends Options<ParseMediaFields>> = (Fields['dimensions'] extends true ? {
|
|
60
60
|
onDimensions?: (dimensions: Dimensions) => void;
|
|
61
61
|
} : {}) & (Fields['durationInSeconds'] extends true ? {
|
|
62
62
|
onDurationInSeconds?: (durationInSeconds: number | null) => void;
|
|
63
|
-
} : {}) & (Fields['
|
|
64
|
-
|
|
63
|
+
} : {}) & (Fields['structure'] extends true ? {
|
|
64
|
+
onStructure?: (structure: Structure) => void;
|
|
65
65
|
} : {}) & (Fields['fps'] extends true ? {
|
|
66
66
|
onFps?: (fps: number | null) => void;
|
|
67
67
|
} : {}) & (Fields['videoCodec'] extends true ? {
|
|
@@ -87,8 +87,8 @@ export type ParseMediaResult<Fields extends Options<ParseMediaFields>> = (Fields
|
|
|
87
87
|
dimensions: Dimensions;
|
|
88
88
|
} : {}) & (Fields['durationInSeconds'] extends true ? {
|
|
89
89
|
durationInSeconds: number | null;
|
|
90
|
-
} : {}) & (Fields['
|
|
91
|
-
|
|
90
|
+
} : {}) & (Fields['structure'] extends true ? {
|
|
91
|
+
structure: Structure;
|
|
92
92
|
} : {}) & (Fields['fps'] extends true ? {
|
|
93
93
|
fps: number | null;
|
|
94
94
|
} : {}) & (Fields['videoCodec'] extends true ? {
|
|
@@ -111,12 +111,19 @@ export type ParseMediaResult<Fields extends Options<ParseMediaFields>> = (Fields
|
|
|
111
111
|
export type ParseMediaDynamicOptions<F extends Options<ParseMediaFields>> = {
|
|
112
112
|
fields?: F;
|
|
113
113
|
} & ParseMediaCallbacks<F>;
|
|
114
|
+
export type ParseMediaProgress = {
|
|
115
|
+
bytes: number;
|
|
116
|
+
percentage: number | null;
|
|
117
|
+
totalBytes: number | null;
|
|
118
|
+
};
|
|
119
|
+
export type ParseMediaOnProgress = (progress: ParseMediaProgress) => void | Promise<void>;
|
|
114
120
|
export type ParseMediaOptions<F extends Options<ParseMediaFields>> = {
|
|
115
|
-
src: string |
|
|
121
|
+
src: string | Blob;
|
|
116
122
|
reader?: ReaderInterface;
|
|
117
123
|
onAudioTrack?: OnAudioTrack;
|
|
118
124
|
onVideoTrack?: OnVideoTrack;
|
|
119
125
|
signal?: AbortSignal;
|
|
120
126
|
logLevel?: LogLevel;
|
|
127
|
+
onParseProgress?: ParseMediaOnProgress;
|
|
121
128
|
} & ParseMediaDynamicOptions<F>;
|
|
122
129
|
export type ParseMedia = <F extends Options<ParseMediaFields>>(options: ParseMediaOptions<F>) => Promise<ParseMediaResult<F>>;
|
package/dist/parse-media.js
CHANGED
|
@@ -4,10 +4,11 @@ exports.parseMedia = void 0;
|
|
|
4
4
|
const buffer_iterator_1 = require("./buffer-iterator");
|
|
5
5
|
const emit_available_info_1 = require("./emit-available-info");
|
|
6
6
|
const has_all_info_1 = require("./has-all-info");
|
|
7
|
+
const log_1 = require("./log");
|
|
7
8
|
const parse_video_1 = require("./parse-video");
|
|
8
9
|
const parser_state_1 = require("./parser-state");
|
|
9
10
|
const from_fetch_1 = require("./readers/from-fetch");
|
|
10
|
-
const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, logLevel = 'info', ...more }) => {
|
|
11
|
+
const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, logLevel = 'info', onParseProgress, ...more }) => {
|
|
11
12
|
const state = (0, parser_state_1.makeParserState)({
|
|
12
13
|
hasAudioCallbacks: onAudioTrack !== null,
|
|
13
14
|
hasVideoCallbacks: onVideoTrack !== null,
|
|
@@ -23,8 +24,16 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
23
24
|
const moreFields = more;
|
|
24
25
|
let iterator = null;
|
|
25
26
|
let parseResult = null;
|
|
27
|
+
// TODO: Should be possible to skip if `null` is returned
|
|
28
|
+
const canSkipVideoData = !onVideoTrack && !onAudioTrack;
|
|
29
|
+
if (canSkipVideoData) {
|
|
30
|
+
log_1.Log.verbose(logLevel, 'Only parsing metadata, because no onVideoTrack and onAudioTrack callbacks were passed.');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
log_1.Log.verbose(logLevel, 'Parsing video data, because onVideoTrack/onAudioTrack callbacks were passed.');
|
|
34
|
+
}
|
|
26
35
|
const options = {
|
|
27
|
-
canSkipVideoData
|
|
36
|
+
canSkipVideoData,
|
|
28
37
|
onAudioTrack: onAudioTrack !== null && onAudioTrack !== void 0 ? onAudioTrack : null,
|
|
29
38
|
onVideoTrack: onVideoTrack !== null && onVideoTrack !== void 0 ? onVideoTrack : null,
|
|
30
39
|
parserState: state,
|
|
@@ -32,7 +41,28 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
32
41
|
typeof process.env !== 'undefined' &&
|
|
33
42
|
process.env.KEEP_SAMPLES === 'true'),
|
|
34
43
|
supportsContentRange,
|
|
44
|
+
nextTrackIndex: 0,
|
|
45
|
+
};
|
|
46
|
+
const hasAllInfo = () => {
|
|
47
|
+
if (parseResult === null) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const availableInfo = (0, has_all_info_1.getAvailableInfo)(fields !== null && fields !== void 0 ? fields : {}, parseResult, state);
|
|
51
|
+
return Object.values(availableInfo).every(Boolean);
|
|
52
|
+
};
|
|
53
|
+
const triggerInfoEmit = () => {
|
|
54
|
+
const availableInfo = (0, has_all_info_1.getAvailableInfo)(fields !== null && fields !== void 0 ? fields : {}, parseResult, state);
|
|
55
|
+
(0, emit_available_info_1.emitAvailableInfo)({
|
|
56
|
+
hasInfo: availableInfo,
|
|
57
|
+
moreFields,
|
|
58
|
+
parseResult,
|
|
59
|
+
state,
|
|
60
|
+
returnValue,
|
|
61
|
+
contentLength,
|
|
62
|
+
name,
|
|
63
|
+
});
|
|
35
64
|
};
|
|
65
|
+
triggerInfoEmit();
|
|
36
66
|
while (parseResult === null || parseResult.status === 'incomplete') {
|
|
37
67
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
38
68
|
throw new Error('Aborted');
|
|
@@ -60,7 +90,16 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
60
90
|
if (!iterator) {
|
|
61
91
|
throw new Error('Unexpected null');
|
|
62
92
|
}
|
|
93
|
+
await (onParseProgress === null || onParseProgress === void 0 ? void 0 : onParseProgress({
|
|
94
|
+
bytes: iterator.counter.getOffset(),
|
|
95
|
+
percentage: contentLength
|
|
96
|
+
? iterator.counter.getOffset() / contentLength
|
|
97
|
+
: null,
|
|
98
|
+
totalBytes: contentLength,
|
|
99
|
+
}));
|
|
100
|
+
triggerInfoEmit();
|
|
63
101
|
if (parseResult && parseResult.status === 'incomplete') {
|
|
102
|
+
log_1.Log.verbose(logLevel, 'Continuing parsing of file, currently at position', iterator.counter.getOffset(), (0, has_all_info_1.getAvailableInfo)(fields !== null && fields !== void 0 ? fields : {}, parseResult, state));
|
|
64
103
|
parseResult = await parseResult.continueParsing();
|
|
65
104
|
}
|
|
66
105
|
else {
|
|
@@ -71,20 +110,9 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
71
110
|
logLevel,
|
|
72
111
|
});
|
|
73
112
|
}
|
|
74
|
-
const availableInfo = (0, has_all_info_1.getAvailableInfo)(fields !== null && fields !== void 0 ? fields : {}, parseResult, state);
|
|
75
|
-
const hasAllInfo = Object.values(availableInfo).every(Boolean);
|
|
76
|
-
(0, emit_available_info_1.emitAvailableInfo)({
|
|
77
|
-
hasInfo: availableInfo,
|
|
78
|
-
moreFields,
|
|
79
|
-
parseResult,
|
|
80
|
-
state,
|
|
81
|
-
returnValue,
|
|
82
|
-
contentLength,
|
|
83
|
-
name,
|
|
84
|
-
});
|
|
85
113
|
// TODO Better: Check if no active listeners are registered
|
|
86
114
|
// Also maybe check for canSkipVideoData
|
|
87
|
-
if (hasAllInfo && !onVideoTrack && !onAudioTrack) {
|
|
115
|
+
if (hasAllInfo() && !onVideoTrack && !onAudioTrack) {
|
|
88
116
|
break;
|
|
89
117
|
}
|
|
90
118
|
if (parseResult &&
|
|
@@ -99,6 +127,7 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
99
127
|
iterator.skipTo(parseResult.skipTo, true);
|
|
100
128
|
}
|
|
101
129
|
}
|
|
130
|
+
log_1.Log.verbose(logLevel, 'Finished parsing file');
|
|
102
131
|
// Force assign
|
|
103
132
|
(0, emit_available_info_1.emitAvailableInfo)({
|
|
104
133
|
hasInfo: Object.keys(fields !== null && fields !== void 0 ? fields : {}).reduce((acc, key) => {
|
package/dist/parse-result.d.ts
CHANGED
|
@@ -25,22 +25,51 @@ import type { TkhdBox } from './boxes/iso-base-media/tkhd';
|
|
|
25
25
|
import type { TrakBox } from './boxes/iso-base-media/trak/trak';
|
|
26
26
|
import type { TrunBox } from './boxes/iso-base-media/trun';
|
|
27
27
|
import type { VoidBox } from './boxes/iso-base-media/void-box';
|
|
28
|
+
import type { RiffBox } from './boxes/riff/riff-box';
|
|
28
29
|
import type { MatroskaSegment } from './boxes/webm/segments';
|
|
29
30
|
export interface RegularBox extends BaseBox {
|
|
30
31
|
boxType: string;
|
|
31
32
|
boxSize: number;
|
|
32
|
-
children:
|
|
33
|
+
children: IsoBaseMediaBox[];
|
|
33
34
|
offset: number;
|
|
34
35
|
type: 'regular-box';
|
|
35
36
|
}
|
|
36
37
|
export type IsoBaseMediaBox = RegularBox | FtypBox | MvhdBox | TkhdBox | StsdBox | MebxBox | KeysBox | MoovBox | TrakBox | SttsBox | MdhdBox | EsdsBox | MdatBox | StszBox | StcoBox | StscBox | AvccBox | HvccBox | VoidBox | StssBox | PaspBox | CttsBox | Av1CBox | TrunBox | ColorParameterBox | TfdtBox | TfhdBox;
|
|
37
|
-
export type AnySegment = MatroskaSegment | IsoBaseMediaBox;
|
|
38
|
-
export type
|
|
38
|
+
export type AnySegment = MatroskaSegment | IsoBaseMediaBox | RiffBox;
|
|
39
|
+
export type IsoBaseMediaStructure = {
|
|
40
|
+
type: 'iso-base-media';
|
|
41
|
+
boxes: IsoBaseMediaBox[];
|
|
42
|
+
};
|
|
43
|
+
export type RiffStructure = {
|
|
44
|
+
type: 'riff';
|
|
45
|
+
boxes: RiffBox[];
|
|
46
|
+
};
|
|
47
|
+
export type MatroskaStructure = {
|
|
48
|
+
type: 'matroska';
|
|
49
|
+
boxes: MatroskaSegment[];
|
|
50
|
+
};
|
|
51
|
+
export type Structure = IsoBaseMediaStructure | RiffStructure | MatroskaStructure;
|
|
52
|
+
export type ParseResult<TStructure extends Structure> = {
|
|
53
|
+
status: 'done';
|
|
54
|
+
segments: TStructure;
|
|
55
|
+
} | {
|
|
56
|
+
status: 'incomplete';
|
|
57
|
+
segments: TStructure;
|
|
58
|
+
skipTo: number | null;
|
|
59
|
+
continueParsing: () => Promise<ParseResult<TStructure>>;
|
|
60
|
+
};
|
|
61
|
+
export type MatroskaParseResult = {
|
|
39
62
|
status: 'done';
|
|
40
|
-
segments: AnySegment[];
|
|
41
63
|
} | {
|
|
42
64
|
status: 'incomplete';
|
|
43
|
-
segments: AnySegment[];
|
|
44
65
|
skipTo: number | null;
|
|
45
|
-
continueParsing: () => Promise<
|
|
66
|
+
continueParsing: () => Promise<MatroskaParseResult>;
|
|
67
|
+
};
|
|
68
|
+
export type ExpectSegmentParseResult = {
|
|
69
|
+
status: 'done';
|
|
70
|
+
segment: MatroskaSegment;
|
|
71
|
+
} | {
|
|
72
|
+
status: 'incomplete';
|
|
73
|
+
segment: MatroskaSegment | null;
|
|
74
|
+
continueParsing: () => Promise<ExpectSegmentParseResult>;
|
|
46
75
|
};
|
package/dist/parse-video.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BufferIterator } from './buffer-iterator';
|
|
2
|
-
import type
|
|
3
|
-
import type { IsoBaseMediaBox, ParseResult } from './parse-result';
|
|
2
|
+
import { type LogLevel } from './log';
|
|
3
|
+
import type { IsoBaseMediaBox, ParseResult, Structure } from './parse-result';
|
|
4
4
|
import type { ParserContext } from './parser-context';
|
|
5
5
|
export type PartialMdatBox = {
|
|
6
6
|
type: 'partial-mdat-box';
|
|
@@ -20,4 +20,4 @@ export declare const parseVideo: ({ iterator, options, signal, logLevel, }: {
|
|
|
20
20
|
options: ParserContext;
|
|
21
21
|
signal: AbortSignal | null;
|
|
22
22
|
logLevel: LogLevel;
|
|
23
|
-
}) => Promise<ParseResult
|
|
23
|
+
}) => Promise<ParseResult<Structure>>;
|
package/dist/parse-video.js
CHANGED
|
@@ -2,28 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseVideo = void 0;
|
|
4
4
|
const process_box_1 = require("./boxes/iso-base-media/process-box");
|
|
5
|
+
const parse_box_1 = require("./boxes/riff/parse-box");
|
|
5
6
|
const parse_webm_header_1 = require("./boxes/webm/parse-webm-header");
|
|
7
|
+
const log_1 = require("./log");
|
|
6
8
|
const parseVideo = ({ iterator, options, signal, logLevel, }) => {
|
|
7
9
|
if (iterator.bytesRemaining() === 0) {
|
|
8
|
-
return Promise.
|
|
9
|
-
status: 'incomplete',
|
|
10
|
-
segments: [],
|
|
11
|
-
continueParsing: () => {
|
|
12
|
-
return (0, exports.parseVideo)({
|
|
13
|
-
iterator,
|
|
14
|
-
options,
|
|
15
|
-
signal,
|
|
16
|
-
logLevel,
|
|
17
|
-
});
|
|
18
|
-
},
|
|
19
|
-
skipTo: null,
|
|
20
|
-
});
|
|
10
|
+
return Promise.reject(new Error('no bytes'));
|
|
21
11
|
}
|
|
22
12
|
if (iterator.isRiff()) {
|
|
23
|
-
|
|
13
|
+
return Promise.resolve((0, parse_box_1.parseRiff)({ iterator, options }));
|
|
24
14
|
}
|
|
25
15
|
if (iterator.isIsoBaseMedia()) {
|
|
26
|
-
|
|
16
|
+
log_1.Log.verbose(logLevel, 'Detected ISO Base Media container');
|
|
17
|
+
return (0, process_box_1.parseIsoBaseMediaBoxes)({
|
|
27
18
|
iterator,
|
|
28
19
|
maxBytes: Infinity,
|
|
29
20
|
allowIncompleteBoxes: true,
|
|
@@ -35,7 +26,8 @@ const parseVideo = ({ iterator, options, signal, logLevel, }) => {
|
|
|
35
26
|
});
|
|
36
27
|
}
|
|
37
28
|
if (iterator.isWebm()) {
|
|
38
|
-
|
|
29
|
+
log_1.Log.verbose(logLevel, 'Detected Matroska container');
|
|
30
|
+
return (0, parse_webm_header_1.parseWebm)(iterator, options);
|
|
39
31
|
}
|
|
40
32
|
if (iterator.isMp3()) {
|
|
41
33
|
return Promise.reject(new Error('MP3 files are not yet supported'));
|
package/dist/parser-context.d.ts
CHANGED
package/dist/parser-state.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
+
import type { AvcPPs, AvcProfileInfo } from './boxes/avc/parse-avc';
|
|
1
2
|
import type { OnTrackEntrySegment } from './boxes/webm/segments';
|
|
2
3
|
import type { TrackInfo } from './boxes/webm/segments/track-entry';
|
|
3
4
|
import type { AudioOrVideoSample, OnAudioSample, OnVideoSample } from './webcodec-sample-types';
|
|
4
5
|
export type InternalStats = {};
|
|
6
|
+
export type SpsAndPps = {
|
|
7
|
+
sps: AvcProfileInfo;
|
|
8
|
+
pps: AvcPPs;
|
|
9
|
+
};
|
|
10
|
+
type AvcProfileInfoCallback = (profile: SpsAndPps) => Promise<void>;
|
|
5
11
|
export declare const makeParserState: ({ hasAudioCallbacks, hasVideoCallbacks, signal, }: {
|
|
6
12
|
hasAudioCallbacks: boolean;
|
|
7
13
|
hasVideoCallbacks: boolean;
|
|
8
14
|
signal: AbortSignal | undefined;
|
|
9
15
|
}) => {
|
|
10
16
|
onTrackEntrySegment: OnTrackEntrySegment;
|
|
17
|
+
onProfile: (profile: SpsAndPps) => Promise<void>;
|
|
18
|
+
registerOnAvcProfileCallback: (callback: AvcProfileInfoCallback) => void;
|
|
11
19
|
getTrackInfoByNumber: (id: number) => TrackInfo;
|
|
12
20
|
registerVideoSampleCallback: (id: number, callback: OnVideoSample | null) => Promise<void>;
|
|
13
21
|
setTimestampOffset: (byteOffset: number, timestamp: number) => void;
|
|
@@ -18,5 +26,8 @@ export declare const makeParserState: ({ hasAudioCallbacks, hasVideoCallbacks, s
|
|
|
18
26
|
getInternalStats: () => {};
|
|
19
27
|
getTimescale: () => number;
|
|
20
28
|
setTimescale: (newTimescale: number) => void;
|
|
29
|
+
getSamplesForTrack: (trackId: number) => number;
|
|
30
|
+
getAvcProfile: () => SpsAndPps | null;
|
|
21
31
|
};
|
|
22
32
|
export type ParserState = ReturnType<typeof makeParserState>;
|
|
33
|
+
export {};
|
package/dist/parser-state.js
CHANGED
|
@@ -59,8 +59,23 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, signal, }) => {
|
|
|
59
59
|
}
|
|
60
60
|
return timestampMap.get(byteOffset);
|
|
61
61
|
};
|
|
62
|
+
const samplesForTrack = {};
|
|
63
|
+
const profileCallbacks = [];
|
|
64
|
+
const registerOnAvcProfileCallback = (callback) => {
|
|
65
|
+
profileCallbacks.push(callback);
|
|
66
|
+
};
|
|
67
|
+
let avcProfile = null;
|
|
68
|
+
const onProfile = async (profile) => {
|
|
69
|
+
avcProfile = profile;
|
|
70
|
+
for (const callback of profileCallbacks) {
|
|
71
|
+
await callback(profile);
|
|
72
|
+
}
|
|
73
|
+
profileCallbacks.length = 0;
|
|
74
|
+
};
|
|
62
75
|
return {
|
|
63
76
|
onTrackEntrySegment,
|
|
77
|
+
onProfile,
|
|
78
|
+
registerOnAvcProfileCallback,
|
|
64
79
|
getTrackInfoByNumber: (id) => trackEntries[id],
|
|
65
80
|
registerVideoSampleCallback: async (id, callback) => {
|
|
66
81
|
var _a;
|
|
@@ -94,6 +109,10 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, signal, }) => {
|
|
|
94
109
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
95
110
|
throw new Error('Aborted');
|
|
96
111
|
}
|
|
112
|
+
if (typeof samplesForTrack[trackId] === 'undefined') {
|
|
113
|
+
samplesForTrack[trackId] = 0;
|
|
114
|
+
}
|
|
115
|
+
samplesForTrack[trackId]++;
|
|
97
116
|
const callback = audioSampleCallbacks[trackId];
|
|
98
117
|
if (callback) {
|
|
99
118
|
await callback(audioSample);
|
|
@@ -111,6 +130,10 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, signal, }) => {
|
|
|
111
130
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
112
131
|
throw new Error('Aborted');
|
|
113
132
|
}
|
|
133
|
+
if (typeof samplesForTrack[trackId] === 'undefined') {
|
|
134
|
+
samplesForTrack[trackId] = 0;
|
|
135
|
+
}
|
|
136
|
+
samplesForTrack[trackId]++;
|
|
114
137
|
const callback = videoSampleCallbacks[trackId];
|
|
115
138
|
if (callback) {
|
|
116
139
|
await callback(videoSample);
|
|
@@ -127,6 +150,13 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, signal, }) => {
|
|
|
127
150
|
getInternalStats: () => ({}),
|
|
128
151
|
getTimescale,
|
|
129
152
|
setTimescale,
|
|
153
|
+
getSamplesForTrack: (trackId) => {
|
|
154
|
+
var _a;
|
|
155
|
+
return (_a = samplesForTrack[trackId]) !== null && _a !== void 0 ? _a : 0;
|
|
156
|
+
},
|
|
157
|
+
getAvcProfile: () => {
|
|
158
|
+
return avcProfile;
|
|
159
|
+
},
|
|
130
160
|
};
|
|
131
161
|
};
|
|
132
162
|
exports.makeParserState = makeParserState;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.nodeReader = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const promises_1 = require("node:fs/promises");
|
|
6
|
+
const path_1 = require("path");
|
|
6
7
|
const stream_1 = require("stream");
|
|
7
8
|
exports.nodeReader = {
|
|
8
9
|
read: async (src, range, signal) => {
|
|
@@ -37,7 +38,7 @@ exports.nodeReader = {
|
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
40
|
contentLength: stats.size,
|
|
40
|
-
name: src.split(
|
|
41
|
+
name: src.split(path_1.sep).pop(),
|
|
41
42
|
supportsContentRange: true,
|
|
42
43
|
};
|
|
43
44
|
},
|
package/dist/readers/reader.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ type ReadResult = {
|
|
|
8
8
|
name: string;
|
|
9
9
|
supportsContentRange: boolean;
|
|
10
10
|
};
|
|
11
|
-
type ReadContent = (src: string |
|
|
12
|
-
type GetLength = (src: string |
|
|
11
|
+
type ReadContent = (src: string | Blob, range: [number, number] | number | null, signal: AbortSignal | undefined) => Promise<ReadResult>;
|
|
12
|
+
type GetLength = (src: string | Blob) => Promise<number>;
|
|
13
13
|
export type ReaderInterface = {
|
|
14
14
|
read: ReadContent;
|
|
15
15
|
getLength: GetLength;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Track, VideoTrack } from './get-tracks';
|
|
2
|
+
import type { ParserContext } from './parser-context';
|
|
3
|
+
import type { ParserState } from './parser-state';
|
|
4
|
+
export declare const registerTrack: ({ state, options, track, }: {
|
|
5
|
+
state: ParserState;
|
|
6
|
+
options: ParserContext;
|
|
7
|
+
track: Track;
|
|
8
|
+
}) => Promise<void>;
|
|
9
|
+
export declare const registerVideoTrackWhenProfileIsAvailable: ({ options, state, track, }: {
|
|
10
|
+
state: ParserState;
|
|
11
|
+
options: ParserContext;
|
|
12
|
+
track: VideoTrack;
|
|
13
|
+
}) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerVideoTrackWhenProfileIsAvailable = exports.registerTrack = void 0;
|
|
4
|
+
const add_avc_profile_to_track_1 = require("./add-avc-profile-to-track");
|
|
5
|
+
const registerTrack = async ({ state, options, track, }) => {
|
|
6
|
+
if (track.type === 'video' && options.onVideoTrack) {
|
|
7
|
+
const callback = await options.onVideoTrack(track);
|
|
8
|
+
await state.registerVideoSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
|
|
9
|
+
}
|
|
10
|
+
if (track.type === 'audio' && options.onAudioTrack) {
|
|
11
|
+
const callback = await options.onAudioTrack(track);
|
|
12
|
+
await state.registerAudioSampleCallback(track.trackId, callback !== null && callback !== void 0 ? callback : null);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
exports.registerTrack = registerTrack;
|
|
16
|
+
const registerVideoTrackWhenProfileIsAvailable = ({ options, state, track, }) => {
|
|
17
|
+
state.registerOnAvcProfileCallback(async (profile) => {
|
|
18
|
+
await (0, exports.registerTrack)({
|
|
19
|
+
options,
|
|
20
|
+
state,
|
|
21
|
+
track: (0, add_avc_profile_to_track_1.addAvcProfileToTrack)(track, profile),
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
exports.registerVideoTrackWhenProfileIsAvailable = registerVideoTrackWhenProfileIsAvailable;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "4.0.232";
|
package/dist/version.js
ADDED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const createContent:
|
|
1
|
+
import type { CreateContent } from '../writer';
|
|
2
|
+
export declare const createContent: CreateContent;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createContent = void 0;
|
|
4
|
-
const createContent = () => {
|
|
4
|
+
const createContent = ({ filename, mimeType }) => {
|
|
5
5
|
const buf = new ArrayBuffer(0, {
|
|
6
6
|
// TODO: Educate that the buffer is limited to 2GB
|
|
7
7
|
maxByteLength: 2000000000,
|
|
@@ -34,7 +34,7 @@ const createContent = () => {
|
|
|
34
34
|
const arr = new Uint8Array(buf);
|
|
35
35
|
return Promise.resolve(
|
|
36
36
|
// TODO: Unhardcode MIME type and file name
|
|
37
|
-
new File([arr.slice()],
|
|
37
|
+
new File([arr.slice()], filename, { type: mimeType }));
|
|
38
38
|
},
|
|
39
39
|
remove() {
|
|
40
40
|
removed = true;
|
package/dist/writers/web-fs.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.canUseWebFsWriter = exports.webFsWriter = void 0;
|
|
4
|
-
const createContent = async () => {
|
|
4
|
+
const createContent = async ({ filename }) => {
|
|
5
5
|
const directoryHandle = await navigator.storage.getDirectory();
|
|
6
|
-
|
|
7
|
-
const filename = `media-parser-${Math.random().toString().replace('0.', '')}.webm`;
|
|
6
|
+
directoryHandle.removeEntry(filename);
|
|
8
7
|
const fileHandle = await directoryHandle.getFileHandle(filename, {
|
|
9
8
|
create: true,
|
|
10
9
|
});
|
package/dist/writers/writer.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export type Writer = {
|
|
2
2
|
write: (arr: Uint8Array) => Promise<void>;
|
|
3
|
-
save: () => Promise<
|
|
3
|
+
save: () => Promise<Blob>;
|
|
4
4
|
getWrittenByteCount: () => number;
|
|
5
5
|
updateDataAt: (position: number, data: Uint8Array) => Promise<void>;
|
|
6
6
|
waitForFinish: () => Promise<void>;
|
|
7
7
|
remove: () => Promise<void>;
|
|
8
8
|
};
|
|
9
|
-
type CreateContent = (
|
|
9
|
+
export type CreateContent = (options: {
|
|
10
|
+
filename: string;
|
|
11
|
+
mimeType: string;
|
|
12
|
+
}) => Promise<Writer>;
|
|
10
13
|
export type WriterInterface = {
|
|
11
14
|
createContent: CreateContent;
|
|
12
15
|
};
|
|
13
|
-
export {};
|
package/package.json
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
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.232",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@types/wicg-file-system-access": "2023.10.5",
|
|
11
11
|
"eslint": "9.14.0",
|
|
12
|
-
"@remotion/example-videos": "4.0.
|
|
13
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
12
|
+
"@remotion/example-videos": "4.0.232",
|
|
13
|
+
"@remotion/eslint-config-internal": "4.0.232"
|
|
14
14
|
},
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|