@remotion/media-parser 4.0.202 → 4.0.205
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/av1-codec-string.d.ts +0 -5
- package/dist/av1-codec-string.js +1 -18
- package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +6 -1
- package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
- package/dist/boxes/iso-base-media/ftype.js +31 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.d.ts +4 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +48 -0
- package/dist/boxes/iso-base-media/make-track.js +3 -30
- package/dist/boxes/iso-base-media/mdat/mdat.js +25 -22
- package/dist/boxes/iso-base-media/mdhd.d.ts +2 -0
- package/dist/boxes/iso-base-media/mdhd.js +6 -7
- package/dist/boxes/iso-base-media/mvhd.js +11 -13
- package/dist/boxes/iso-base-media/process-box.js +36 -0
- package/dist/boxes/iso-base-media/tfdt.d.ts +12 -0
- package/dist/boxes/iso-base-media/tfdt.js +20 -0
- package/dist/boxes/iso-base-media/tfhd.d.ts +16 -0
- package/dist/boxes/iso-base-media/tfhd.js +41 -0
- package/dist/boxes/iso-base-media/tkhd.js +9 -12
- package/dist/boxes/iso-base-media/trun.d.ts +21 -0
- package/dist/boxes/iso-base-media/trun.js +44 -0
- package/dist/boxes/webm/bitstream/av1.js +1 -10
- package/dist/boxes/webm/ebml.d.ts +1 -1
- package/dist/boxes/webm/get-track.js +2 -2
- 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 +8 -2
- package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
- package/dist/boxes/webm/tracks.d.ts +8 -0
- package/dist/boxes/webm/tracks.js +21 -0
- package/dist/buffer-iterator.d.ts +1 -0
- package/dist/buffer-iterator.js +3 -2
- package/dist/create/cluster-segment.d.ts +10 -0
- package/dist/create/cluster-segment.js +41 -0
- package/dist/create/create-media.d.ts +6 -1
- package/dist/create/create-media.js +58 -4
- package/dist/create/matroska-header.d.ts +1 -1
- package/dist/create/matroska-info.d.ts +1 -1
- package/dist/create/matroska-info.js +2 -2
- package/dist/create/matroska-segment.d.ts +2 -1
- package/dist/create/matroska-trackentry.d.ts +5 -4
- package/dist/from-web.js +6 -15
- package/dist/get-duration.d.ts +3 -2
- package/dist/get-duration.js +24 -4
- package/dist/get-tracks.d.ts +4 -4
- package/dist/get-video-metadata.d.ts +2 -0
- package/dist/get-video-metadata.js +44 -0
- package/dist/has-all-info.js +1 -1
- package/dist/parse-media.js +1 -1
- package/dist/parse-result.d.ts +4 -1
- package/dist/read-and-increment-offset.d.ts +28 -0
- package/dist/read-and-increment-offset.js +177 -0
- package/dist/samples-from-moof.d.ts +6 -0
- package/dist/samples-from-moof.js +75 -0
- package/dist/traversal.d.ts +8 -1
- package/dist/traversal.js +39 -1
- package/dist/understand-vorbis.d.ts +1 -0
- package/dist/understand-vorbis.js +12 -0
- package/dist/writers/web-fs.js +21 -5
- package/dist/writers/writer.d.ts +3 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/esds/decoder-specific-config.ts +8 -1
- package/src/boxes/iso-base-media/get-sample-positions-from-track.ts +69 -0
- package/src/boxes/iso-base-media/make-track.ts +4 -45
- package/src/boxes/iso-base-media/mdat/mdat.ts +33 -24
- package/src/boxes/iso-base-media/mdhd.ts +10 -7
- package/src/boxes/iso-base-media/mvhd.ts +15 -14
- package/src/boxes/iso-base-media/process-box.ts +42 -0
- package/src/boxes/iso-base-media/tfdt.ts +37 -0
- package/src/boxes/iso-base-media/tfhd.ts +66 -0
- package/src/boxes/iso-base-media/tkhd.ts +11 -13
- package/src/boxes/iso-base-media/trun.ts +74 -0
- package/src/boxes/webm/get-track.ts +2 -2
- package/src/buffer-iterator.ts +3 -2
- package/src/get-duration.ts +40 -5
- package/src/get-tracks.ts +4 -4
- package/src/has-all-info.ts +1 -1
- package/src/parse-media.ts +1 -1
- package/src/parse-result.ts +7 -1
- package/src/samples-from-moof.ts +102 -0
- package/src/test/samples-from-moof.test.ts +2496 -0
- package/src/test/stream-local.test.ts +28 -30
- package/src/test/stream-samples.test.ts +153 -231
- package/src/traversal.ts +56 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/bitstream/av1.d.ts +0 -2
- package/dist/bitstream/av1.js +0 -12
- package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +0 -20
- package/dist/boxes/iso-base-media/avcc-hvcc.js +0 -73
- package/dist/boxes/iso-base-media/avcc.d.ts +0 -18
- package/dist/boxes/iso-base-media/avcc.js +0 -27
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
- package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
- package/dist/boxes/iso-base-media/esds.d.ts +0 -15
- package/dist/boxes/iso-base-media/esds.js +0 -27
- package/dist/create-media.d.ts +0 -1
- package/dist/create-media.js +0 -78
- package/dist/from-input-type-file.d.ts +0 -2
- package/dist/from-input-type-file.js +0 -37
- package/dist/get-codec.d.ts +0 -4
- package/dist/get-codec.js +0 -22
- package/dist/web-file.d.ts +0 -2
- package/dist/web-file.js +0 -37
- /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
- /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
- /package/dist/{sample-aspect-ratio.d.ts → boxes/webm/bitstream/h264/get-h264-descriptor.d.ts} +0 -0
- /package/dist/{sample-aspect-ratio.js → boxes/webm/bitstream/h264/get-h264-descriptor.js} +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTrun = void 0;
|
|
4
|
+
const parseTrun = ({ iterator, offset, size, }) => {
|
|
5
|
+
const version = iterator.getUint8();
|
|
6
|
+
if (version !== 0) {
|
|
7
|
+
throw new Error(`Unsupported TRUN version ${version}`);
|
|
8
|
+
}
|
|
9
|
+
const flags = iterator.getUint24();
|
|
10
|
+
const sampleCount = iterator.getUint32();
|
|
11
|
+
const dataOffset = flags & 0x01 ? iterator.getInt32() : null;
|
|
12
|
+
const firstSampleFlags = flags & 0x04 ? iterator.getUint32() : null;
|
|
13
|
+
const samples = [];
|
|
14
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
15
|
+
const sampleDuration = flags & 0x100 ? iterator.getUint32() : null;
|
|
16
|
+
const sampleSize = flags & 0x200 ? iterator.getUint32() : null;
|
|
17
|
+
const sampleFlags = flags & 0x400 ? iterator.getUint32() : null;
|
|
18
|
+
const sampleCompositionTimeOffset = flags & 0x800
|
|
19
|
+
? version === 0
|
|
20
|
+
? iterator.getUint32()
|
|
21
|
+
: iterator.getInt32Le()
|
|
22
|
+
: null;
|
|
23
|
+
samples.push({
|
|
24
|
+
sampleDuration,
|
|
25
|
+
sampleSize,
|
|
26
|
+
sampleFlags,
|
|
27
|
+
sampleCompositionTimeOffset,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const currentOffset = iterator.counter.getOffset();
|
|
31
|
+
const left = size - (currentOffset - offset);
|
|
32
|
+
if (left !== 0) {
|
|
33
|
+
throw new Error(`Unexpected data left in TRUN box: ${left}`);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
type: 'trun-box',
|
|
37
|
+
version,
|
|
38
|
+
sampleCount,
|
|
39
|
+
dataOffset,
|
|
40
|
+
firstSampleFlags,
|
|
41
|
+
samples,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
exports.parseTrun = parseTrun;
|
|
@@ -50,15 +50,6 @@ const av1Bitstream = ({ stream, length, onVideoSample, trackNumber, context, tim
|
|
|
50
50
|
: {
|
|
51
51
|
type: 'av1-bitstream-unimplemented',
|
|
52
52
|
};
|
|
53
|
-
if (segment.type === 'av1-bitstream-header') {
|
|
54
|
-
if (!size) {
|
|
55
|
-
throw new Error('Expected size');
|
|
56
|
-
}
|
|
57
|
-
const toSample = bytesReadSoFar + size;
|
|
58
|
-
stream.counter.decrement(stream.counter.getOffset() - address);
|
|
59
|
-
const header = stream.getSlice(toSample);
|
|
60
|
-
context.parserState.setAv1BitstreamHeaderSegment(segment, header);
|
|
61
|
-
}
|
|
62
53
|
if (obuType === 6) {
|
|
63
54
|
const head = context.parserState.getAv1BitstreamHeaderSegment();
|
|
64
55
|
if (!head) {
|
|
@@ -89,7 +80,7 @@ const av1Bitstream = ({ stream, length, onVideoSample, trackNumber, context, tim
|
|
|
89
80
|
}
|
|
90
81
|
}
|
|
91
82
|
onVideoSample(trackNumber, {
|
|
92
|
-
|
|
83
|
+
data: (0, combine_uint8array_1.combineUint8Arrays)(extraBytes, frame),
|
|
93
84
|
timestamp: timecode + clusterTimestamp,
|
|
94
85
|
duration: undefined,
|
|
95
86
|
trackId: trackNumber,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const measureEBMLVarInt: (value: number) =>
|
|
1
|
+
export declare const measureEBMLVarInt: (value: number) => 1 | 2 | 3 | 4 | 5 | 6;
|
|
2
2
|
export declare const getVariableInt: (value: number, minWidth: number | null) => Uint8Array;
|
|
@@ -150,7 +150,6 @@ const getTrack = ({ timescale, track, }) => {
|
|
|
150
150
|
denominator: 1,
|
|
151
151
|
},
|
|
152
152
|
timescale,
|
|
153
|
-
samplePositions: [],
|
|
154
153
|
codedHeight: height.value.value,
|
|
155
154
|
codedWidth: width.value.value,
|
|
156
155
|
displayAspectHeight: displayHeight
|
|
@@ -160,6 +159,7 @@ const getTrack = ({ timescale, track, }) => {
|
|
|
160
159
|
? displayWidth.value.value
|
|
161
160
|
: width.value.value,
|
|
162
161
|
rotation: 0,
|
|
162
|
+
trakBox: null,
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
165
|
if ((0, track_entry_1.trackTypeToString)(trackType.value.value) === 'audio') {
|
|
@@ -172,11 +172,11 @@ const getTrack = ({ timescale, track, }) => {
|
|
|
172
172
|
type: 'audio',
|
|
173
173
|
trackId,
|
|
174
174
|
codec: getMatroskaAudioCodecString(track),
|
|
175
|
-
samplePositions: null,
|
|
176
175
|
timescale,
|
|
177
176
|
numberOfChannels,
|
|
178
177
|
sampleRate,
|
|
179
178
|
description: (0, description_1.getAudioDescription)(track),
|
|
179
|
+
trakBox: null,
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
return null;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSeekPositionSegment = void 0;
|
|
4
4
|
const parseSeekPositionSegment = (iterator, length) => {
|
|
5
|
-
const seekPosition = iterator.
|
|
5
|
+
const seekPosition = iterator.getUint(length);
|
|
6
6
|
return {
|
|
7
7
|
type: 'seek-position-segment',
|
|
8
8
|
seekPosition,
|
|
@@ -10,4 +10,4 @@ export type SeekIdSegment = {
|
|
|
10
10
|
type: 'seek-id-segment';
|
|
11
11
|
seekId: string;
|
|
12
12
|
};
|
|
13
|
-
export declare const parseSeekIdSegment: (iterator: BufferIterator) => SeekIdSegment;
|
|
13
|
+
export declare const parseSeekIdSegment: (iterator: BufferIterator, length: number) => SeekIdSegment;
|
|
@@ -19,8 +19,14 @@ const parseSeekSegment = async (iterator, length, parserContext) => {
|
|
|
19
19
|
};
|
|
20
20
|
};
|
|
21
21
|
exports.parseSeekSegment = parseSeekSegment;
|
|
22
|
-
const parseSeekIdSegment = (iterator) => {
|
|
23
|
-
const seekId =
|
|
22
|
+
const parseSeekIdSegment = (iterator, length) => {
|
|
23
|
+
const seekId = '0x' +
|
|
24
|
+
[...iterator.getSlice(length)]
|
|
25
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
26
|
+
.join('');
|
|
27
|
+
if (seekId === null) {
|
|
28
|
+
throw new Error('Not enough bytes to parse seek id');
|
|
29
|
+
}
|
|
24
30
|
return {
|
|
25
31
|
type: 'seek-id-segment',
|
|
26
32
|
seekId,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseTimestampScaleSegment = void 0;
|
|
4
4
|
const parseTimestampScaleSegment = (iterator) => {
|
|
5
|
-
const timestampScale = iterator.
|
|
5
|
+
const timestampScale = iterator.getUint(3);
|
|
6
6
|
return {
|
|
7
7
|
type: 'timestamp-scale-segment',
|
|
8
8
|
timestampScale,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BufferIterator } from '../../buffer-iterator';
|
|
2
|
+
import type { ParserContext } from '../../parser-context';
|
|
3
|
+
import type { MatroskaSegment } from './segments';
|
|
4
|
+
export type TracksSegment = {
|
|
5
|
+
type: 'tracks-segment';
|
|
6
|
+
children: MatroskaSegment[];
|
|
7
|
+
};
|
|
8
|
+
export declare const parseTracksSegment: (iterator: BufferIterator, length: number, parserContext: ParserContext) => Promise<TracksSegment>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTracksSegment = void 0;
|
|
4
|
+
const parse_children_1 = require("./segments/parse-children");
|
|
5
|
+
const parseTracksSegment = async (iterator, length, parserContext) => {
|
|
6
|
+
const children = await (0, parse_children_1.expectChildren)({
|
|
7
|
+
iterator,
|
|
8
|
+
length,
|
|
9
|
+
initialChildren: [],
|
|
10
|
+
wrap: null,
|
|
11
|
+
parserContext,
|
|
12
|
+
});
|
|
13
|
+
if (children.status === 'incomplete') {
|
|
14
|
+
throw new Error('Incomplete children');
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
type: 'tracks-segment',
|
|
18
|
+
children: children.segments,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
exports.parseTracksSegment = parseTracksSegment;
|
package/dist/buffer-iterator.js
CHANGED
|
@@ -392,8 +392,8 @@ const getArrayBufferIterator = (initialData, maxBytes) => {
|
|
|
392
392
|
},
|
|
393
393
|
getUint24: () => {
|
|
394
394
|
const val1 = view.getUint8(counter.getDiscardedOffset());
|
|
395
|
-
const val2 = view.getUint8(counter.getDiscardedOffset());
|
|
396
|
-
const val3 = view.getUint8(counter.getDiscardedOffset());
|
|
395
|
+
const val2 = view.getUint8(counter.getDiscardedOffset() + 1);
|
|
396
|
+
const val3 = view.getUint8(counter.getDiscardedOffset() + 2);
|
|
397
397
|
counter.increment(3);
|
|
398
398
|
return (val1 << 16) | (val2 << 8) | val3;
|
|
399
399
|
},
|
|
@@ -443,6 +443,7 @@ const getArrayBufferIterator = (initialData, maxBytes) => {
|
|
|
443
443
|
},
|
|
444
444
|
getUint32Le,
|
|
445
445
|
getInt32Le,
|
|
446
|
+
getInt32,
|
|
446
447
|
destroy,
|
|
447
448
|
isMp3,
|
|
448
449
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const CLUSTER_MIN_VINT_WIDTH = 8;
|
|
2
|
+
export declare const createClusterSegment: () => import("../boxes/webm/segments/all-segments").BytesAndOffset;
|
|
3
|
+
export declare const makeSimpleBlock: ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }: {
|
|
4
|
+
bytes: Uint8Array;
|
|
5
|
+
trackNumber: number;
|
|
6
|
+
timecodeRelativeToCluster: number;
|
|
7
|
+
keyframe: boolean;
|
|
8
|
+
invisible: boolean;
|
|
9
|
+
lacing: number;
|
|
10
|
+
}) => Uint8Array;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeSimpleBlock = exports.createClusterSegment = exports.CLUSTER_MIN_VINT_WIDTH = void 0;
|
|
4
|
+
const ebml_1 = require("../boxes/webm/ebml");
|
|
5
|
+
const make_header_1 = require("../boxes/webm/make-header");
|
|
6
|
+
exports.CLUSTER_MIN_VINT_WIDTH = 8;
|
|
7
|
+
const createClusterSegment = () => {
|
|
8
|
+
return (0, make_header_1.makeMatroskaBytes)({
|
|
9
|
+
type: 'Cluster',
|
|
10
|
+
value: [
|
|
11
|
+
{
|
|
12
|
+
type: 'Timestamp',
|
|
13
|
+
minVintWidth: 4,
|
|
14
|
+
value: {
|
|
15
|
+
value: 0,
|
|
16
|
+
byteLength: null,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
minVintWidth: exports.CLUSTER_MIN_VINT_WIDTH,
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
exports.createClusterSegment = createClusterSegment;
|
|
24
|
+
const makeSimpleBlock = ({ bytes, trackNumber, timecodeRelativeToCluster, keyframe, invisible, lacing, }) => {
|
|
25
|
+
const simpleBlockHeader = (0, make_header_1.matroskaToHex)('0xa3');
|
|
26
|
+
const headerByte = (Number(keyframe) << 7) | (Number(invisible) << 3) | (lacing << 1);
|
|
27
|
+
const body = (0, make_header_1.combineUint8Arrays)([
|
|
28
|
+
(0, ebml_1.getVariableInt)(trackNumber, null),
|
|
29
|
+
// TODO: Cannot encode long videos because of uint16 overflow
|
|
30
|
+
// need to make new cluster
|
|
31
|
+
(0, make_header_1.serializeUint16)(timecodeRelativeToCluster),
|
|
32
|
+
new Uint8Array([headerByte]),
|
|
33
|
+
bytes,
|
|
34
|
+
]);
|
|
35
|
+
return (0, make_header_1.combineUint8Arrays)([
|
|
36
|
+
simpleBlockHeader,
|
|
37
|
+
(0, ebml_1.getVariableInt)(body.length, null),
|
|
38
|
+
body,
|
|
39
|
+
]);
|
|
40
|
+
};
|
|
41
|
+
exports.makeSimpleBlock = makeSimpleBlock;
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
import type { WriterInterface } from '../writers/writer';
|
|
2
|
-
export
|
|
2
|
+
export type MediaFn = {
|
|
3
|
+
save: () => Promise<void>;
|
|
4
|
+
addSample: (chunk: EncodedVideoChunk, trackNumber: number) => Promise<void>;
|
|
5
|
+
updateDuration: (duration: number) => Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
export declare const createMedia: (writer: WriterInterface) => Promise<MediaFn>;
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createMedia = void 0;
|
|
4
|
+
const ebml_1 = require("../boxes/webm/ebml");
|
|
5
|
+
const make_header_1 = require("../boxes/webm/make-header");
|
|
6
|
+
const all_segments_1 = require("../boxes/webm/segments/all-segments");
|
|
7
|
+
const cluster_segment_1 = require("./cluster-segment");
|
|
4
8
|
const matroska_header_1 = require("./matroska-header");
|
|
5
9
|
const matroska_info_1 = require("./matroska-info");
|
|
6
10
|
const matroska_segment_1 = require("./matroska-segment");
|
|
7
11
|
const matroska_trackentry_1 = require("./matroska-trackentry");
|
|
8
12
|
const createMedia = async (writer) => {
|
|
13
|
+
var _a, _b;
|
|
9
14
|
const header = (0, matroska_header_1.makeMatroskaHeader)();
|
|
10
15
|
const w = await writer.createContent();
|
|
11
|
-
await w.write(header);
|
|
16
|
+
await w.write(header.bytes);
|
|
12
17
|
const matroskaInfo = (0, matroska_info_1.makeMatroskaInfo)({
|
|
13
18
|
timescale: 1000000,
|
|
14
19
|
duration: 2658,
|
|
@@ -28,9 +33,58 @@ const createMedia = async (writer) => {
|
|
|
28
33
|
});
|
|
29
34
|
const matroskaTracks = (0, matroska_trackentry_1.makeMatroskaTracks)([matroskaTrackEntry]);
|
|
30
35
|
const matroskaSegment = (0, matroska_segment_1.createMatroskaSegment)([matroskaInfo, matroskaTracks]);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
const durationOffset = ((_b = (_a = matroskaSegment.offsets.children[0].children.find((c) => c.field === 'Duration')) === null || _a === void 0 ? void 0 : _a.offset) !== null && _b !== void 0 ? _b : 0) + w.getWrittenByteCount();
|
|
37
|
+
if (!durationOffset) {
|
|
38
|
+
throw new Error('could not get duration offset');
|
|
39
|
+
}
|
|
40
|
+
await w.write(matroskaSegment.bytes);
|
|
41
|
+
const cluster = (0, cluster_segment_1.createClusterSegment)();
|
|
42
|
+
const clusterVIntPosition = w.getWrittenByteCount() +
|
|
43
|
+
cluster.offsets.offset +
|
|
44
|
+
(0, make_header_1.matroskaToHex)(all_segments_1.matroskaElements.Cluster).byteLength;
|
|
45
|
+
let clusterSize = cluster.bytes.byteLength;
|
|
46
|
+
await w.write(cluster.bytes);
|
|
47
|
+
const addSample = async (chunk, trackNumber) => {
|
|
48
|
+
const arr = new Uint8Array(chunk.byteLength);
|
|
49
|
+
chunk.copyTo(arr);
|
|
50
|
+
const simpleBlock = (0, cluster_segment_1.makeSimpleBlock)({
|
|
51
|
+
bytes: arr,
|
|
52
|
+
invisible: false,
|
|
53
|
+
keyframe: chunk.type === 'key',
|
|
54
|
+
lacing: 0,
|
|
55
|
+
trackNumber,
|
|
56
|
+
// TODO: Maybe this is bad, because it's in microseconds, but should be in timescale
|
|
57
|
+
// Maybe it only works by coincidence
|
|
58
|
+
timecodeRelativeToCluster: Math.round(chunk.timestamp / 1000),
|
|
59
|
+
});
|
|
60
|
+
clusterSize += simpleBlock.byteLength;
|
|
61
|
+
await w.updateDataAt(clusterVIntPosition, (0, ebml_1.getVariableInt)(clusterSize, cluster_segment_1.CLUSTER_MIN_VINT_WIDTH));
|
|
62
|
+
await w.write(simpleBlock);
|
|
63
|
+
};
|
|
64
|
+
const updateDuration = async (newDuration) => {
|
|
65
|
+
const blocks = (0, make_header_1.padMatroskaBytes)({
|
|
66
|
+
type: 'Duration',
|
|
67
|
+
value: {
|
|
68
|
+
value: newDuration,
|
|
69
|
+
size: '64',
|
|
70
|
+
},
|
|
71
|
+
minVintWidth: null,
|
|
72
|
+
}, 1000);
|
|
73
|
+
await w.updateDataAt(durationOffset, (0, make_header_1.combineUint8Arrays)(blocks.map((b) => b.bytes)));
|
|
74
|
+
};
|
|
75
|
+
let operationProm = Promise.resolve();
|
|
76
|
+
return {
|
|
77
|
+
save: async () => {
|
|
78
|
+
await w.save();
|
|
79
|
+
},
|
|
80
|
+
addSample: (chunk, trackNumber) => {
|
|
81
|
+
operationProm = operationProm.then(() => addSample(chunk, trackNumber));
|
|
82
|
+
return operationProm;
|
|
83
|
+
},
|
|
84
|
+
updateDuration: (duration) => {
|
|
85
|
+
operationProm = operationProm.then(() => updateDuration(duration));
|
|
86
|
+
return operationProm;
|
|
87
|
+
},
|
|
34
88
|
};
|
|
35
89
|
};
|
|
36
90
|
exports.createMedia = createMedia;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const makeMatroskaHeader: () =>
|
|
1
|
+
export declare const makeMatroskaHeader: () => import("../boxes/webm/segments/all-segments").BytesAndOffset;
|
|
@@ -24,14 +24,14 @@ const makeMatroskaInfo = ({ timescale, duration, }) => {
|
|
|
24
24
|
value: '@remotion/media-parser',
|
|
25
25
|
minVintWidth: null,
|
|
26
26
|
},
|
|
27
|
-
{
|
|
27
|
+
...(0, make_header_1.padMatroskaBytes)({
|
|
28
28
|
type: 'Duration',
|
|
29
29
|
value: {
|
|
30
30
|
value: duration,
|
|
31
31
|
size: '64',
|
|
32
32
|
},
|
|
33
33
|
minVintWidth: null,
|
|
34
|
-
},
|
|
34
|
+
}, 1000),
|
|
35
35
|
],
|
|
36
36
|
minVintWidth: null,
|
|
37
37
|
});
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { BytesAndOffset } from '../boxes/webm/segments/all-segments';
|
|
2
|
+
export declare const createMatroskaSegment: (children: BytesAndOffset[]) => BytesAndOffset;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import type { BytesAndOffset } from '../boxes/webm/segments/all-segments';
|
|
1
2
|
export type MatroskaColorParams = {
|
|
2
3
|
transferChracteristics: 'bt709' | 'smpte170m' | 'iec61966-2-1' | null;
|
|
3
4
|
matrixCoefficients: 'bt709' | 'bt470bg' | 'rgb' | 'smpte170m' | null;
|
|
4
5
|
primaries: 'bt709' | 'smpte170m' | 'bt470bg' | null;
|
|
5
6
|
fullRange: boolean | null;
|
|
6
7
|
};
|
|
7
|
-
export declare const makeMatroskaColorBytes: ({ transferChracteristics, matrixCoefficients, primaries, fullRange, }: MatroskaColorParams) =>
|
|
8
|
+
export declare const makeMatroskaColorBytes: ({ transferChracteristics, matrixCoefficients, primaries, fullRange, }: MatroskaColorParams) => BytesAndOffset;
|
|
8
9
|
export declare const makeMatroskaVideoBytes: ({ color, width, height, }: {
|
|
9
10
|
color: MatroskaColorParams;
|
|
10
11
|
width: number;
|
|
11
12
|
height: number;
|
|
12
|
-
}) =>
|
|
13
|
+
}) => BytesAndOffset;
|
|
13
14
|
export declare const makeMatroskaVideoTrackEntryBytes: ({ color, width, height, defaultDuration, trackNumber, codecId, }: {
|
|
14
15
|
color: MatroskaColorParams;
|
|
15
16
|
width: number;
|
|
@@ -17,5 +18,5 @@ export declare const makeMatroskaVideoTrackEntryBytes: ({ color, width, height,
|
|
|
17
18
|
defaultDuration: number;
|
|
18
19
|
trackNumber: number;
|
|
19
20
|
codecId: string;
|
|
20
|
-
}) =>
|
|
21
|
-
export declare const makeMatroskaTracks: (tracks:
|
|
21
|
+
}) => BytesAndOffset;
|
|
22
|
+
export declare const makeMatroskaTracks: (tracks: BytesAndOffset[]) => BytesAndOffset;
|
package/dist/from-web.js
CHANGED
|
@@ -3,9 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.webReader = void 0;
|
|
4
4
|
exports.webReader = {
|
|
5
5
|
read: async (src, range) => {
|
|
6
|
-
if (typeof src !== 'string') {
|
|
7
|
-
throw new Error('src must be a string when using `webReader`');
|
|
8
|
-
}
|
|
9
6
|
const resolvedUrl = typeof window !== 'undefined' && typeof window.location !== 'undefined'
|
|
10
7
|
? new URL(src, window.location.origin).toString()
|
|
11
8
|
: src;
|
|
@@ -17,28 +14,22 @@ exports.webReader = {
|
|
|
17
14
|
const res = await fetch(resolvedUrl, {
|
|
18
15
|
headers: range === null
|
|
19
16
|
? {}
|
|
20
|
-
:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
: {
|
|
25
|
-
Range: `bytes=${`${range[0]}-${range[1]}`}`,
|
|
26
|
-
},
|
|
27
|
-
// Disable Next.js caching
|
|
28
|
-
cache: 'no-store',
|
|
17
|
+
: {
|
|
18
|
+
Range: `bytes=${`${range[0]}-${range[1]}`}`,
|
|
19
|
+
},
|
|
29
20
|
});
|
|
30
21
|
if (!res.body) {
|
|
31
22
|
throw new Error('No body');
|
|
32
23
|
}
|
|
33
24
|
const length = res.headers.get('content-length');
|
|
25
|
+
if (!length) {
|
|
26
|
+
throw new Error('No content-length');
|
|
27
|
+
}
|
|
34
28
|
const contentLength = length === null ? null : parseInt(length, 10);
|
|
35
29
|
const reader = res.body.getReader();
|
|
36
30
|
return { reader, contentLength };
|
|
37
31
|
},
|
|
38
32
|
getLength: async (src) => {
|
|
39
|
-
if (typeof src !== 'string') {
|
|
40
|
-
throw new Error('src must be a string when using `webReader`');
|
|
41
|
-
}
|
|
42
33
|
const res = await fetch(src, {
|
|
43
34
|
method: 'HEAD',
|
|
44
35
|
});
|
package/dist/get-duration.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { AnySegment } from './parse-result';
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
2
|
+
import type { ParserState } from './parser-state';
|
|
3
|
+
export declare const getDuration: (boxes: AnySegment[], parserState: ParserState) => number | null;
|
|
4
|
+
export declare const hasDuration: (boxes: AnySegment[], parserState: ParserState) => boolean;
|
package/dist/get-duration.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.hasDuration = exports.getDuration = void 0;
|
|
4
|
+
const get_sample_positions_from_track_1 = require("./boxes/iso-base-media/get-sample-positions-from-track");
|
|
5
|
+
const get_tracks_1 = require("./get-tracks");
|
|
4
6
|
const traversal_1 = require("./traversal");
|
|
5
7
|
const getDurationFromMatroska = (segments) => {
|
|
6
8
|
const mainSegment = segments.find((s) => s.type === 'Segment');
|
|
@@ -26,7 +28,7 @@ const getDurationFromMatroska = (segments) => {
|
|
|
26
28
|
}
|
|
27
29
|
return (duration.value.value / timestampScale.value.value) * 1000;
|
|
28
30
|
};
|
|
29
|
-
const getDuration = (boxes) => {
|
|
31
|
+
const getDuration = (boxes, parserState) => {
|
|
30
32
|
const matroskaBox = boxes.find((b) => b.type === 'Segment');
|
|
31
33
|
if (matroskaBox) {
|
|
32
34
|
return getDurationFromMatroska(boxes);
|
|
@@ -35,6 +37,7 @@ const getDuration = (boxes) => {
|
|
|
35
37
|
if (!moovBox) {
|
|
36
38
|
return null;
|
|
37
39
|
}
|
|
40
|
+
const moofBox = (0, traversal_1.getMoofBox)(boxes);
|
|
38
41
|
const mvhdBox = (0, traversal_1.getMvhdBox)(moovBox);
|
|
39
42
|
if (!mvhdBox) {
|
|
40
43
|
return null;
|
|
@@ -42,12 +45,29 @@ const getDuration = (boxes) => {
|
|
|
42
45
|
if (mvhdBox.type !== 'mvhd-box') {
|
|
43
46
|
throw new Error('Expected mvhd-box');
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
if (mvhdBox.durationInSeconds > 0) {
|
|
49
|
+
return mvhdBox.durationInSeconds;
|
|
50
|
+
}
|
|
51
|
+
const tracks = (0, get_tracks_1.getTracks)(boxes, parserState);
|
|
52
|
+
const allTracks = [
|
|
53
|
+
...tracks.videoTracks,
|
|
54
|
+
...tracks.audioTracks,
|
|
55
|
+
...tracks.otherTracks,
|
|
56
|
+
];
|
|
57
|
+
const allSamples = allTracks.map((t) => {
|
|
58
|
+
const { timescale: ts } = t;
|
|
59
|
+
const samplePositions = (0, get_sample_positions_from_track_1.getSamplePositionsFromTrack)(t.trakBox, moofBox);
|
|
60
|
+
const highest = samplePositions === null || samplePositions === void 0 ? void 0 : samplePositions.map((sp) => (sp.cts + sp.duration) / ts).reduce((a, b) => Math.max(a, b), 0);
|
|
61
|
+
return highest !== null && highest !== void 0 ? highest : 0;
|
|
62
|
+
});
|
|
63
|
+
const highestTimestamp = Math.max(...allSamples);
|
|
64
|
+
return highestTimestamp;
|
|
46
65
|
};
|
|
47
66
|
exports.getDuration = getDuration;
|
|
48
|
-
const hasDuration = (boxes) => {
|
|
67
|
+
const hasDuration = (boxes, parserState) => {
|
|
49
68
|
try {
|
|
50
|
-
|
|
69
|
+
const duration = (0, exports.getDuration)(boxes, parserState);
|
|
70
|
+
return (0, exports.getDuration)(boxes, parserState) !== null && duration !== 0;
|
|
51
71
|
}
|
|
52
72
|
catch (err) {
|
|
53
73
|
return false;
|
package/dist/get-tracks.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MoovBox } from './boxes/iso-base-media/moov/moov';
|
|
2
|
-
import type {
|
|
2
|
+
import type { TrakBox } from './boxes/iso-base-media/trak/trak';
|
|
3
3
|
import type { AnySegment } from './parse-result';
|
|
4
4
|
import type { ParserState } from './parser-state';
|
|
5
5
|
type SampleAspectRatio = {
|
|
@@ -8,7 +8,6 @@ type SampleAspectRatio = {
|
|
|
8
8
|
};
|
|
9
9
|
export type VideoTrack = {
|
|
10
10
|
type: 'video';
|
|
11
|
-
samplePositions: SamplePosition[] | null;
|
|
12
11
|
trackId: number;
|
|
13
12
|
description: Uint8Array | undefined;
|
|
14
13
|
timescale: number;
|
|
@@ -21,22 +20,23 @@ export type VideoTrack = {
|
|
|
21
20
|
codedWidth: number;
|
|
22
21
|
codedHeight: number;
|
|
23
22
|
rotation: number;
|
|
23
|
+
trakBox: TrakBox | null;
|
|
24
24
|
};
|
|
25
25
|
export type AudioTrack = {
|
|
26
26
|
type: 'audio';
|
|
27
|
-
samplePositions: SamplePosition[] | null;
|
|
28
27
|
trackId: number;
|
|
29
28
|
timescale: number;
|
|
30
29
|
codec: string;
|
|
31
30
|
numberOfChannels: number;
|
|
32
31
|
sampleRate: number;
|
|
33
32
|
description: Uint8Array | undefined;
|
|
33
|
+
trakBox: TrakBox | null;
|
|
34
34
|
};
|
|
35
35
|
export type OtherTrack = {
|
|
36
36
|
type: 'other';
|
|
37
|
-
samplePositions: SamplePosition[] | null;
|
|
38
37
|
trackId: number;
|
|
39
38
|
timescale: number;
|
|
39
|
+
trakBox: TrakBox | null;
|
|
40
40
|
};
|
|
41
41
|
export type Track = VideoTrack | AudioTrack | OtherTrack;
|
|
42
42
|
export declare const getNumberOfTracks: (moovBox: MoovBox) => number;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMedia = void 0;
|
|
4
|
+
const buffer_iterator_1 = require("./buffer-iterator");
|
|
5
|
+
const from_web_1 = require("./from-web");
|
|
6
|
+
const get_dimensions_1 = require("./get-dimensions");
|
|
7
|
+
const get_duration_1 = require("./get-duration");
|
|
8
|
+
const get_fps_1 = require("./get-fps");
|
|
9
|
+
const has_all_info_1 = require("./has-all-info");
|
|
10
|
+
const parse_video_1 = require("./parse-video");
|
|
11
|
+
const parseMedia = async (src, options, readerInterface = from_web_1.webReader) => {
|
|
12
|
+
const reader = await readerInterface.read(src, null);
|
|
13
|
+
const returnValue = {};
|
|
14
|
+
const iterator = (0, buffer_iterator_1.getArrayBufferIterator)(new Uint8Array([]));
|
|
15
|
+
let parseResult = (0, parse_video_1.parseVideo)(iterator);
|
|
16
|
+
while (parseResult.status === 'incomplete') {
|
|
17
|
+
const result = await reader.read();
|
|
18
|
+
if (result.done) {
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
iterator.addData(result.value);
|
|
22
|
+
parseResult = parseResult.continueParsing();
|
|
23
|
+
if ((0, has_all_info_1.hasAllInfo)(options, parseResult)) {
|
|
24
|
+
if (!reader.closed) {
|
|
25
|
+
reader.cancel(new Error('has all information'));
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (options.dimensions) {
|
|
31
|
+
returnValue.dimensions = (0, get_dimensions_1.getDimensions)(parseResult.segments);
|
|
32
|
+
}
|
|
33
|
+
if (options.durationInSeconds) {
|
|
34
|
+
returnValue.durationInSeconds = (0, get_duration_1.getDuration)(parseResult.segments);
|
|
35
|
+
}
|
|
36
|
+
if (options.fps) {
|
|
37
|
+
returnValue.fps = (0, get_fps_1.getFps)(parseResult.segments);
|
|
38
|
+
}
|
|
39
|
+
if (options.boxes) {
|
|
40
|
+
returnValue.boxes = parseResult.segments;
|
|
41
|
+
}
|
|
42
|
+
return returnValue;
|
|
43
|
+
};
|
|
44
|
+
exports.parseMedia = parseMedia;
|
package/dist/has-all-info.js
CHANGED
|
@@ -16,7 +16,7 @@ const hasAllInfo = (options, parseResult, state) => {
|
|
|
16
16
|
return parseResult.status === 'done';
|
|
17
17
|
}
|
|
18
18
|
if (key === 'durationInSeconds') {
|
|
19
|
-
return (0, get_duration_1.hasDuration)(parseResult.segments);
|
|
19
|
+
return (0, get_duration_1.hasDuration)(parseResult.segments, state);
|
|
20
20
|
}
|
|
21
21
|
if (key === 'dimensions' ||
|
|
22
22
|
key === 'rotation' ||
|
package/dist/parse-media.js
CHANGED
|
@@ -100,7 +100,7 @@ const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.
|
|
|
100
100
|
returnValue.rotation = dimensions.rotation;
|
|
101
101
|
}
|
|
102
102
|
if (fields === null || fields === void 0 ? void 0 : fields.durationInSeconds) {
|
|
103
|
-
returnValue.durationInSeconds = (0, get_duration_1.getDuration)(parseResult.segments);
|
|
103
|
+
returnValue.durationInSeconds = (0, get_duration_1.getDuration)(parseResult.segments, state);
|
|
104
104
|
}
|
|
105
105
|
if (fields === null || fields === void 0 ? void 0 : fields.fps) {
|
|
106
106
|
returnValue.fps = (0, get_fps_1.getFps)(parseResult.segments);
|