@remotion/media-parser 4.0.201 → 4.0.202
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/iso-base-media/mvhd.js +2 -2
- package/dist/boxes/iso-base-media/stsd/keys.js +1 -1
- package/dist/boxes/webm/av1-codec-private.js +1 -1
- package/dist/boxes/webm/description.d.ts +2 -2
- package/dist/boxes/webm/description.js +2 -2
- package/dist/boxes/webm/ebml.d.ts +2 -2
- package/dist/boxes/webm/ebml.js +23 -1
- package/dist/boxes/webm/get-ready-tracks.d.ts +1 -1
- package/dist/boxes/webm/get-ready-tracks.js +3 -3
- package/dist/boxes/webm/get-sample-from-block.d.ts +17 -0
- package/dist/boxes/webm/get-sample-from-block.js +78 -0
- package/dist/boxes/webm/get-track.d.ts +2 -2
- package/dist/boxes/webm/get-track.js +26 -25
- package/dist/boxes/webm/make-header.d.ts +3 -8
- package/dist/boxes/webm/make-header.js +43 -20
- package/dist/boxes/webm/parse-ebml.d.ts +9 -4
- package/dist/boxes/webm/parse-ebml.js +122 -13
- package/dist/boxes/webm/segments/all-segments.d.ts +421 -107
- package/dist/boxes/webm/segments/all-segments.js +260 -33
- package/dist/boxes/webm/segments/seek-position.js +1 -1
- package/dist/boxes/webm/segments/seek.d.ts +1 -1
- package/dist/boxes/webm/segments/seek.js +2 -8
- package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
- package/dist/boxes/webm/segments/track-entry.d.ts +3 -191
- package/dist/boxes/webm/segments/track-entry.js +2 -456
- package/dist/boxes/webm/segments.d.ts +3 -16
- package/dist/boxes/webm/segments.js +12 -196
- package/dist/boxes/webm/traversal.d.ts +5 -6
- package/dist/boxes/webm/traversal.js +6 -6
- package/dist/buffer-iterator.d.ts +1 -1
- package/dist/buffer-iterator.js +3 -3
- package/dist/create/create-media.d.ts +2 -0
- package/dist/create/create-media.js +36 -0
- package/dist/create/matroska-header.d.ts +1 -0
- package/dist/create/matroska-header.js +66 -0
- package/dist/create/matroska-info.d.ts +4 -0
- package/dist/create/matroska-info.js +39 -0
- package/dist/create/matroska-segment.d.ts +1 -0
- package/dist/create/matroska-segment.js +12 -0
- package/dist/create/matroska-trackentry.d.ts +21 -0
- package/dist/create/matroska-trackentry.js +191 -0
- package/dist/create-media.d.ts +1 -0
- package/dist/create-media.js +78 -0
- package/dist/get-audio-codec.d.ts +1 -1
- package/dist/get-audio-codec.js +13 -13
- package/dist/get-duration.js +12 -14
- package/dist/get-tracks.js +2 -2
- package/dist/get-video-codec.js +13 -13
- package/dist/parse-media.js +4 -1
- package/dist/parser-context.d.ts +1 -0
- package/dist/parser-state.js +3 -2
- package/dist/readers/from-fetch.d.ts +2 -0
- package/dist/readers/from-fetch.js +64 -0
- package/dist/readers/from-node.d.ts +2 -0
- package/dist/readers/from-node.js +40 -0
- package/dist/readers/from-web-file.d.ts +2 -0
- package/dist/readers/from-web-file.js +39 -0
- package/dist/readers/reader.d.ts +11 -0
- package/dist/readers/reader.js +2 -0
- package/dist/traversal.d.ts +19 -17
- package/dist/traversal.js +38 -39
- package/dist/writers/web-fs.d.ts +2 -0
- package/dist/writers/web-fs.js +28 -0
- package/dist/writers/writer.d.ts +9 -0
- package/dist/writers/writer.js +2 -0
- package/input.webm +0 -0
- package/package.json +2 -2
- package/src/boxes/iso-base-media/mvhd.ts +2 -2
- package/src/boxes/iso-base-media/stsd/keys.ts +1 -1
- package/src/boxes/webm/av1-codec-private.ts +1 -1
- package/src/boxes/webm/description.ts +7 -4
- package/src/boxes/webm/ebml.ts +24 -4
- package/src/boxes/webm/get-ready-tracks.ts +4 -4
- package/src/boxes/webm/get-sample-from-block.ts +125 -0
- package/src/boxes/webm/get-track.ts +38 -31
- package/src/boxes/webm/make-header.ts +58 -51
- package/src/boxes/webm/parse-ebml.ts +170 -16
- package/src/boxes/webm/segments/all-segments.ts +379 -62
- package/src/boxes/webm/segments/track-entry.ts +3 -846
- package/src/boxes/webm/segments.ts +18 -410
- package/src/boxes/webm/traversal.ts +17 -17
- package/src/buffer-iterator.ts +5 -4
- package/src/get-audio-codec.ts +14 -16
- package/src/get-duration.ts +15 -16
- package/src/get-tracks.ts +2 -2
- package/src/get-video-codec.ts +13 -15
- package/src/parse-media.ts +6 -1
- package/src/parser-context.ts +1 -0
- package/src/parser-state.ts +2 -2
- package/src/test/create-matroska.test.ts +237 -23
- package/src/test/matroska.test.ts +283 -348
- package/src/test/mvhd.test.ts +1 -1
- package/src/test/parse-esds.test.ts +2 -2
- package/src/test/parse-stco.test.ts +2 -2
- package/src/test/parse-stsc.test.ts +2 -2
- package/src/test/parse-stsz.test.ts +2 -2
- package/src/test/parse-stts.test.ts +1 -1
- package/src/test/stsd.test.ts +4 -2
- package/src/test/tkhd.test.ts +1 -1
- package/src/traversal.ts +62 -85
- package/tsconfig.tsbuildinfo +1 -1
- package/src/boxes/webm/segments/duration.ts +0 -29
- package/src/boxes/webm/segments/info.ts +0 -34
- package/src/boxes/webm/segments/main.ts +0 -6
- package/src/boxes/webm/segments/muxing.ts +0 -18
- package/src/boxes/webm/segments/seek-head.ts +0 -34
- package/src/boxes/webm/segments/seek-position.ts +0 -18
- package/src/boxes/webm/segments/seek.ts +0 -55
- package/src/boxes/webm/segments/timestamp-scale.ts +0 -17
- package/src/boxes/webm/segments/tracks.ts +0 -32
- package/src/boxes/webm/segments/void.ts +0 -18
- package/src/boxes/webm/segments/writing.ts +0 -18
- package/src/combine-uint8array.ts +0 -13
package/src/get-video-codec.ts
CHANGED
|
@@ -76,39 +76,37 @@ export const getVideoCodec = (boxes: AnySegment[]): KnownVideoCodecs | null => {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
const mainSegment = boxes.find((b) => b.type === '
|
|
80
|
-
if (!mainSegment || mainSegment.type !== '
|
|
79
|
+
const mainSegment = boxes.find((b) => b.type === 'Segment');
|
|
80
|
+
if (!mainSegment || mainSegment.type !== 'Segment') {
|
|
81
81
|
return null;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const tracksSegment = mainSegment.
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
if (!tracksSegment || tracksSegment.type !== 'tracks-segment') {
|
|
84
|
+
const tracksSegment = mainSegment.value.find((b) => b.type === 'Tracks');
|
|
85
|
+
if (!tracksSegment || tracksSegment.type !== 'Tracks') {
|
|
88
86
|
return null;
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
for (const track of tracksSegment.
|
|
92
|
-
if (track.type === '
|
|
93
|
-
const trackType = track.
|
|
94
|
-
if (trackType && trackType.type === '
|
|
95
|
-
if (trackType.
|
|
89
|
+
for (const track of tracksSegment.value) {
|
|
90
|
+
if (track.type === 'TrackEntry') {
|
|
91
|
+
const trackType = track.value.find((b) => b.type === 'CodecID');
|
|
92
|
+
if (trackType && trackType.type === 'CodecID') {
|
|
93
|
+
if (trackType.value === 'V_VP8') {
|
|
96
94
|
return 'vp8';
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
if (trackType.
|
|
97
|
+
if (trackType.value === 'V_VP9') {
|
|
100
98
|
return 'vp9';
|
|
101
99
|
}
|
|
102
100
|
|
|
103
|
-
if (trackType.
|
|
101
|
+
if (trackType.value === 'V_AV1') {
|
|
104
102
|
return 'av1';
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
if (trackType.
|
|
105
|
+
if (trackType.value === 'V_MPEG4/ISO/AVC') {
|
|
108
106
|
return 'h264';
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
if (trackType.
|
|
109
|
+
if (trackType.value === 'V_MPEGH/ISO/HEVC') {
|
|
112
110
|
return 'h265';
|
|
113
111
|
}
|
|
114
112
|
}
|
package/src/parse-media.ts
CHANGED
|
@@ -52,6 +52,11 @@ export const parseMedia: ParseMedia = async ({
|
|
|
52
52
|
onAudioTrack: onAudioTrack ?? null,
|
|
53
53
|
onVideoTrack: onVideoTrack ?? null,
|
|
54
54
|
parserState: state,
|
|
55
|
+
nullifySamples: !(
|
|
56
|
+
typeof process !== 'undefined' &&
|
|
57
|
+
typeof process.env !== 'undefined' &&
|
|
58
|
+
process.env.KEEP_SAMPLES === 'true'
|
|
59
|
+
),
|
|
55
60
|
};
|
|
56
61
|
|
|
57
62
|
while (parseResult === null || parseResult.status === 'incomplete') {
|
|
@@ -72,7 +77,7 @@ export const parseMedia: ParseMedia = async ({
|
|
|
72
77
|
|
|
73
78
|
iterator = getArrayBufferIterator(
|
|
74
79
|
result.value,
|
|
75
|
-
contentLength ??
|
|
80
|
+
contentLength ?? 1_000_000_000,
|
|
76
81
|
);
|
|
77
82
|
}
|
|
78
83
|
|
package/src/parser-context.ts
CHANGED
package/src/parser-state.ts
CHANGED
|
@@ -40,8 +40,8 @@ export const makeParserState = ({
|
|
|
40
40
|
const trackTimescale = getTrackTimestampScale(trackEntry);
|
|
41
41
|
|
|
42
42
|
trackEntries[trackId] = {
|
|
43
|
-
codec: codec.
|
|
44
|
-
trackTimescale,
|
|
43
|
+
codec: codec.value,
|
|
44
|
+
trackTimescale: trackTimescale?.value ?? null,
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
47
|
|
|
@@ -1,29 +1,121 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable padding-line-between-statements */
|
|
2
|
+
/* eslint-disable max-depth */
|
|
2
3
|
import {expect, test} from 'bun:test';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import {combineUint8Arrays, makeMatroskaBytes} from '../boxes/webm/make-header';
|
|
5
|
+
import {parseEbml} from '../boxes/webm/parse-ebml';
|
|
6
|
+
import type {MatroskaSegment} from '../boxes/webm/segments';
|
|
7
|
+
import type {
|
|
8
|
+
MainSegment,
|
|
9
|
+
TrackEntry,
|
|
8
10
|
} from '../boxes/webm/segments/all-segments';
|
|
11
|
+
import {getArrayBufferIterator} from '../buffer-iterator';
|
|
12
|
+
import {nodeReader} from '../from-node';
|
|
13
|
+
import {parseMedia} from '../parse-media';
|
|
14
|
+
import type {AnySegment} from '../parse-result';
|
|
15
|
+
import type {ParserContext} from '../parser-context';
|
|
16
|
+
import {makeParserState} from '../parser-state';
|
|
9
17
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
const state = makeParserState({
|
|
19
|
+
hasAudioCallbacks: false,
|
|
20
|
+
hasVideoCallbacks: false,
|
|
21
|
+
signal: undefined,
|
|
22
|
+
});
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
const options: ParserContext = {
|
|
25
|
+
canSkipVideoData: true,
|
|
26
|
+
onAudioTrack: null,
|
|
27
|
+
onVideoTrack: null,
|
|
28
|
+
parserState: state,
|
|
29
|
+
nullifySamples: false,
|
|
30
|
+
};
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
test('Should make Matroska header that is same as input', async () => {
|
|
33
|
+
const headerOutput = makeMatroskaBytes({
|
|
34
|
+
type: 'Header',
|
|
35
|
+
minVintWidth: 1,
|
|
36
|
+
value: [
|
|
37
|
+
{
|
|
38
|
+
type: 'EBMLVersion',
|
|
39
|
+
value: {value: 1, byteLength: 1},
|
|
40
|
+
minVintWidth: 1,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'EBMLReadVersion',
|
|
44
|
+
value: {value: 1, byteLength: 1},
|
|
45
|
+
minVintWidth: 1,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: 'EBMLMaxIDLength',
|
|
49
|
+
value: {value: 4, byteLength: 1},
|
|
50
|
+
minVintWidth: 1,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: 'EBMLMaxSizeLength',
|
|
54
|
+
value: {value: 8, byteLength: 1},
|
|
55
|
+
minVintWidth: 1,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: 'DocType',
|
|
59
|
+
value: 'webm',
|
|
60
|
+
minVintWidth: 1,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'DocTypeVersion',
|
|
64
|
+
value: {value: 4, byteLength: 1},
|
|
65
|
+
minVintWidth: 1,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: 'DocTypeReadVersion',
|
|
69
|
+
value: {value: 2, byteLength: 1},
|
|
70
|
+
minVintWidth: 1,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
24
73
|
});
|
|
25
74
|
|
|
26
|
-
|
|
75
|
+
const iterator = getArrayBufferIterator(headerOutput, headerOutput.length);
|
|
76
|
+
const parsed = await parseEbml(iterator, options);
|
|
77
|
+
|
|
78
|
+
expect(parsed).toEqual({
|
|
79
|
+
type: 'Header',
|
|
80
|
+
minVintWidth: 1,
|
|
81
|
+
value: [
|
|
82
|
+
{
|
|
83
|
+
type: 'EBMLVersion',
|
|
84
|
+
value: {value: 1, byteLength: 1},
|
|
85
|
+
minVintWidth: 1,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
type: 'EBMLReadVersion',
|
|
89
|
+
value: {value: 1, byteLength: 1},
|
|
90
|
+
minVintWidth: 1,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'EBMLMaxIDLength',
|
|
94
|
+
value: {value: 4, byteLength: 1},
|
|
95
|
+
minVintWidth: 1,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'EBMLMaxSizeLength',
|
|
99
|
+
value: {value: 8, byteLength: 1},
|
|
100
|
+
minVintWidth: 1,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'DocType',
|
|
104
|
+
value: 'webm',
|
|
105
|
+
minVintWidth: 1,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: 'DocTypeVersion',
|
|
109
|
+
value: {value: 4, byteLength: 1},
|
|
110
|
+
minVintWidth: 1,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'DocTypeReadVersion',
|
|
114
|
+
value: {value: 2, byteLength: 1},
|
|
115
|
+
minVintWidth: 1,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
});
|
|
27
119
|
});
|
|
28
120
|
|
|
29
121
|
test('Should be able to create SeekIdBox', async () => {
|
|
@@ -31,7 +123,11 @@ test('Should be able to create SeekIdBox', async () => {
|
|
|
31
123
|
await Bun.file('vp8-segments/56-0x53ab').arrayBuffer(),
|
|
32
124
|
);
|
|
33
125
|
|
|
34
|
-
const custom =
|
|
126
|
+
const custom = makeMatroskaBytes({
|
|
127
|
+
type: 'SeekID',
|
|
128
|
+
value: '0x1549a966',
|
|
129
|
+
minVintWidth: 1,
|
|
130
|
+
});
|
|
35
131
|
expect(custom).toEqual(file);
|
|
36
132
|
});
|
|
37
133
|
|
|
@@ -39,10 +135,128 @@ test('Should be able to create Seek', async () => {
|
|
|
39
135
|
const file = new Uint8Array(
|
|
40
136
|
await Bun.file('vp8-segments/53-0x4dbb').arrayBuffer(),
|
|
41
137
|
);
|
|
138
|
+
const parsed = await parseEbml(getArrayBufferIterator(file, null), options);
|
|
139
|
+
expect(parsed).toEqual({
|
|
140
|
+
type: 'Seek',
|
|
141
|
+
value: [
|
|
142
|
+
{
|
|
143
|
+
type: 'SeekID',
|
|
144
|
+
value: '0x1549a966',
|
|
145
|
+
minVintWidth: 1,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'SeekPosition',
|
|
149
|
+
value: {value: 0x40, byteLength: 1},
|
|
150
|
+
minVintWidth: 1,
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
minVintWidth: 1,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const custom = makeMatroskaBytes(parsed);
|
|
157
|
+
expect(custom).toEqual(file);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('Should parse seekHead', async () => {
|
|
161
|
+
const file = new Uint8Array(
|
|
162
|
+
await Bun.file('vp8-segments/2165155-0x114d9b74').arrayBuffer(),
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const seekPosition = makeMatroskaBytes({
|
|
166
|
+
type: 'SeekPosition',
|
|
167
|
+
value: {value: 3911, byteLength: 2},
|
|
168
|
+
minVintWidth: 1,
|
|
169
|
+
});
|
|
42
170
|
|
|
43
|
-
const custom =
|
|
44
|
-
|
|
45
|
-
|
|
171
|
+
const custom = makeMatroskaBytes({
|
|
172
|
+
type: 'SeekHead',
|
|
173
|
+
value: [
|
|
174
|
+
{
|
|
175
|
+
type: 'Seek',
|
|
176
|
+
value: [
|
|
177
|
+
{
|
|
178
|
+
type: 'SeekID',
|
|
179
|
+
value: '0x1f43b675',
|
|
180
|
+
minVintWidth: 1,
|
|
181
|
+
},
|
|
182
|
+
seekPosition,
|
|
183
|
+
],
|
|
184
|
+
minVintWidth: 1,
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
minVintWidth: 1,
|
|
46
188
|
});
|
|
47
189
|
expect(custom).toEqual(file);
|
|
190
|
+
|
|
191
|
+
const iterator = getArrayBufferIterator(file, file.length);
|
|
192
|
+
const parsed = await parseEbml(iterator, options);
|
|
193
|
+
|
|
194
|
+
expect(parsed).toEqual({
|
|
195
|
+
minVintWidth: 1,
|
|
196
|
+
type: 'SeekHead',
|
|
197
|
+
value: [
|
|
198
|
+
{
|
|
199
|
+
minVintWidth: 1,
|
|
200
|
+
type: 'Seek',
|
|
201
|
+
value: [
|
|
202
|
+
{minVintWidth: 1, type: 'SeekID', value: '0x1f43b675'},
|
|
203
|
+
{
|
|
204
|
+
minVintWidth: 1,
|
|
205
|
+
type: 'SeekPosition',
|
|
206
|
+
value: {value: 3911, byteLength: 2},
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const parseWebm = async (str: string) => {
|
|
215
|
+
const {boxes} = await parseMedia({
|
|
216
|
+
src: str,
|
|
217
|
+
fields: {
|
|
218
|
+
boxes: true,
|
|
219
|
+
},
|
|
220
|
+
reader: nodeReader,
|
|
221
|
+
});
|
|
222
|
+
return boxes;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const stringifyWebm = (boxes: AnySegment[]) => {
|
|
226
|
+
const buffers: Uint8Array[] = [];
|
|
227
|
+
for (const box of boxes) {
|
|
228
|
+
const bytes = makeMatroskaBytes(box as MatroskaSegment);
|
|
229
|
+
buffers.push(bytes);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const combined = combineUint8Arrays(buffers);
|
|
233
|
+
return combined;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
test('Can we disassemble a Matroska file and assembled it again', async () => {
|
|
237
|
+
process.env.KEEP_SAMPLES = 'true';
|
|
238
|
+
|
|
239
|
+
const parsed = await parseWebm('input.webm');
|
|
240
|
+
|
|
241
|
+
const segment = parsed.find((s) => s.type === 'Segment') as MainSegment;
|
|
242
|
+
const tracks = segment.value.flatMap((s) =>
|
|
243
|
+
s.type === 'Tracks' ? s.value.filter((a) => a.type === 'TrackEntry') : [],
|
|
244
|
+
);
|
|
245
|
+
for (const track of tracks as TrackEntry[]) {
|
|
246
|
+
for (const child of track.value) {
|
|
247
|
+
if (child.type === 'Video') {
|
|
248
|
+
for (const attribute of child.value) {
|
|
249
|
+
if (attribute.type === 'DisplayHeight') {
|
|
250
|
+
attribute.value.value *= 2;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const bytes = await Bun.file('input.webm').arrayBuffer();
|
|
258
|
+
expect(stringifyWebm(parsed).byteLength).toEqual(
|
|
259
|
+
new Uint8Array(bytes).byteLength,
|
|
260
|
+
);
|
|
261
|
+
process.env.KEEP_SAMPLES = 'false';
|
|
48
262
|
});
|