@remotion/media-parser 4.0.192 → 4.0.193

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.
Files changed (62) hide show
  1. package/boxes.json +1 -0
  2. package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +21 -0
  3. package/dist/boxes/iso-base-media/esds/esds-descriptors.js +62 -0
  4. package/dist/boxes/iso-base-media/esds/esds.d.ts +15 -0
  5. package/dist/boxes/iso-base-media/esds/esds.js +27 -0
  6. package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
  7. package/dist/boxes/iso-base-media/ftype.js +31 -0
  8. package/dist/boxes/iso-base-media/process-box.js +17 -0
  9. package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -0
  10. package/dist/boxes/iso-base-media/stsd/samples.js +27 -8
  11. package/dist/boxes/webm/parse-webm-header.js +3 -3
  12. package/dist/boxes/webm/segments/track-entry.d.ts +20 -0
  13. package/dist/boxes/webm/segments/track-entry.js +37 -2
  14. package/dist/boxes/webm/segments.d.ts +2 -2
  15. package/dist/boxes/webm/segments.js +12 -0
  16. package/dist/buffer-iterator.d.ts +2 -1
  17. package/dist/buffer-iterator.js +27 -8
  18. package/dist/from-node.js +6 -2
  19. package/dist/from-web.js +6 -1
  20. package/dist/get-audio-codec.d.ts +4 -0
  21. package/dist/get-audio-codec.js +106 -0
  22. package/dist/get-dimensions.js +6 -2
  23. package/dist/get-fps.d.ts +1 -0
  24. package/dist/get-fps.js +34 -1
  25. package/dist/get-video-codec.js +3 -0
  26. package/dist/get-video-metadata.d.ts +2 -0
  27. package/dist/get-video-metadata.js +44 -0
  28. package/dist/has-all-info.d.ts +1 -1
  29. package/dist/has-all-info.js +4 -0
  30. package/dist/options.d.ts +7 -3
  31. package/dist/parse-media.js +23 -6
  32. package/dist/parse-result.d.ts +2 -1
  33. package/dist/read-and-increment-offset.d.ts +28 -0
  34. package/dist/read-and-increment-offset.js +177 -0
  35. package/dist/reader.d.ts +5 -1
  36. package/package.json +2 -2
  37. package/src/boxes/iso-base-media/esds/esds-descriptors.ts +104 -0
  38. package/src/boxes/iso-base-media/esds/esds.ts +49 -0
  39. package/src/boxes/iso-base-media/process-box.ts +20 -0
  40. package/src/boxes/iso-base-media/stsd/samples.ts +35 -8
  41. package/src/boxes/webm/parse-webm-header.ts +3 -3
  42. package/src/boxes/webm/segments/track-entry.ts +66 -1
  43. package/src/boxes/webm/segments.ts +29 -1
  44. package/src/buffer-iterator.ts +34 -10
  45. package/src/from-node.ts +6 -4
  46. package/src/from-web.ts +8 -1
  47. package/src/get-audio-codec.ts +143 -0
  48. package/src/get-dimensions.ts +11 -4
  49. package/src/get-fps.ts +48 -0
  50. package/src/get-video-codec.ts +4 -0
  51. package/src/has-all-info.ts +14 -2
  52. package/src/options.ts +18 -3
  53. package/src/parse-media.ts +30 -7
  54. package/src/parse-result.ts +3 -1
  55. package/src/reader.ts +5 -1
  56. package/src/test/matroska.test.ts +6 -7
  57. package/src/test/parse-esds.test.ts +75 -0
  58. package/src/test/stream-local.test.ts +79 -2
  59. package/src/test/stsd.test.ts +52 -5
  60. package/tsconfig.tsbuildinfo +1 -1
  61. package/dist/get-codec.d.ts +0 -4
  62. package/dist/get-codec.js +0 -22
package/boxes.json ADDED
@@ -0,0 +1 @@
1
+ [{"type":"ftyp-box","majorBrand":"qt","minorVersion":0,"compatibleBrands":["qt"],"offset":0,"boxSize":20},{"type":"regular-box","boxType":"wide","boxSize":8,"children":[],"offset":20},{"type":"regular-box","boxType":"mdat","children":[],"boxSize":39048800,"offset":28},{"offset":39048828,"boxSize":14100,"type":"moov-box","children":[{"creationTime":1686832959000,"modificationTime":1686832973000,"timeScale":600,"durationInUnits":7541,"durationInSeconds":12.568333333333333,"rate":1,"volume":1,"matrix":[65536,0,0,0,65536,0,0,0,1073741824],"nextTrackId":6,"type":"mvhd-box","boxSize":108,"offset":39048836},{"offset":39048944,"boxSize":7341,"type":"trak-box","children":[{"offset":39048952,"boxSize":92,"type":"tkhd-box","creationTime":1686832959000,"modificationTime":1686832973000,"trackId":1,"duration":7541,"layer":0,"alternateGroup":0,"volume":0,"matrix":[0,65536,0,4294901760,0,0,141557760,0,1073741824],"width":3840,"height":2160,"version":0},{"type":"regular-box","boxType":"tapt","boxSize":68,"children":[],"offset":39049044},{"type":"regular-box","boxType":"edts","boxSize":36,"children":[],"offset":39049112},{"type":"regular-box","boxType":"mdia","boxSize":7137,"children":[{"type":"mdhd-box","duration":7541,"timescale":600,"version":0,"language":21956,"quality":0},{"type":"regular-box","boxType":"hdlr","boxSize":49,"children":[],"offset":39049188},{"type":"regular-box","boxType":"minf","boxSize":7048,"children":[{"type":"regular-box","boxType":"vmhd","boxSize":20,"children":[],"offset":39049245},{"type":"regular-box","boxType":"hdlr","boxSize":56,"children":[],"offset":39049265},{"type":"regular-box","boxType":"dinf","boxSize":36,"children":[],"offset":39049321},{"type":"regular-box","boxType":"stbl","boxSize":6928,"children":[{"type":"stsd-box","boxSize":309,"offset":39049365,"numberOfEntries":1,"samples":[{"format":"hvc1","offset":39049381,"dataReferenceIndex":1,"version":0,"revisionLevel":0,"vendor":[0,0,0,0],"size":293,"type":"video","width":3840,"height":2160,"horizontalResolutionPpi":72,"verticalResolutionPpi":72,"spacialQuality":512,"temporalQuality":512,"dataSize":0,"frameCountPerSample":1,"compressorName":[4,72,69,86,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"depth":24,"colorTableId":-1}]},{"type":"regular-box","boxType":"sgpd","boxSize":104,"children":[],"offset":39049674},{"type":"regular-box","boxType":"sgpd","boxSize":26,"children":[],"offset":39049778},{"type":"regular-box","boxType":"sgpd","boxSize":28,"children":[],"offset":39049804},{"type":"regular-box","boxType":"sbgp","boxSize":212,"children":[],"offset":39049832},{"type":"regular-box","boxType":"csgm","boxSize":71,"children":[],"offset":39050044},{"type":"regular-box","boxType":"csgm","boxSize":249,"children":[],"offset":39050115},{"type":"stts-box","sampleDistribution":[{"sampleCount":269,"sampleDelta":20},{"sampleCount":1,"sampleDelta":21},{"sampleCount":107,"sampleDelta":20}]},{"type":"regular-box","boxType":"ctts","boxSize":3032,"children":[],"offset":39050404},{"type":"regular-box","boxType":"cslg","boxSize":32,"children":[],"offset":39053436},{"type":"regular-box","boxType":"stss","boxSize":64,"children":[],"offset":39053468},{"type":"regular-box","boxType":"sdtp","boxSize":389,"children":[],"offset":39053532},{"type":"regular-box","boxType":"stsc","boxSize":616,"children":[],"offset":39053921},{"type":"regular-box","boxType":"stsz","boxSize":1528,"children":[],"offset":39054537},{"type":"regular-box","boxType":"stco","boxSize":220,"children":[],"offset":39056065}],"offset":39049357}],"offset":39049237}],"offset":39049148}]},{"offset":39056285,"boxSize":3190,"type":"trak-box","children":[{"offset":39056293,"boxSize":92,"type":"tkhd-box","creationTime":1686832959000,"modificationTime":1686832973000,"trackId":2,"duration":7540,"layer":0,"alternateGroup":0,"volume":256,"matrix":[65536,0,0,0,65536,0,0,0,1073741824],"width":0,"height":0,"version":0},{"type":"regular-box","boxType":"edts","boxSize":36,"children":[],"offset":39056385},{"type":"regular-box","boxType":"mdia","boxSize":3054,"children":[{"type":"mdhd-box","duration":557056,"timescale":44100,"version":0,"language":21956,"quality":0},{"type":"regular-box","boxType":"hdlr","boxSize":49,"children":[],"offset":39056461},{"type":"regular-box","boxType":"minf","boxSize":2965,"children":[{"type":"regular-box","boxType":"smhd","boxSize":16,"children":[],"offset":39056518},{"type":"regular-box","boxType":"hdlr","boxSize":56,"children":[],"offset":39056534},{"type":"regular-box","boxType":"dinf","boxSize":36,"children":[],"offset":39056590},{"type":"regular-box","boxType":"stbl","boxSize":2849,"children":[{"type":"stsd-box","boxSize":159,"offset":39056634,"numberOfEntries":1,"samples":[{"format":"mp4a","offset":39056650,"dataReferenceIndex":1,"version":1,"revisionLevel":0,"vendor":[0,0,0,0],"size":143,"type":"audio","numberOfChannels":2,"sampleSize":16,"compressionId":-2,"packetSize":0,"sampleRate":44100,"samplesPerPacket":1024,"bytesPerPacket":1,"bytesPerFrame":2,"bitsPerSample":2,"children":[{"type":"regular-box","boxType":"wave","boxSize":91,"children":[{"type":"regular-box","boxType":"frma","boxSize":12,"children":[],"offset":39056710},{"type":"regular-box","boxType":"mp4a","boxSize":12,"children":[],"offset":39056722},{"type":"esds-box","version":0,"tag":3,"sizeOfInstance":34,"esId":0,"descriptors":[{"type":"decoder-config-descriptor","objectTypeIndication":"aac"},{"type":"sl-config-descriptor"}]},{"type":"regular-box","boxType":"\u0000\u0000\u0000\u0000","boxSize":8,"children":[],"offset":39056785}],"offset":39056702}]}]},{"type":"regular-box","boxType":"sgpd","boxSize":26,"children":[],"offset":39056793},{"type":"regular-box","boxType":"sbgp","boxSize":28,"children":[],"offset":39056819},{"type":"stts-box","sampleDistribution":[{"sampleCount":544,"sampleDelta":1024}]},{"type":"regular-box","boxType":"stsc","boxSize":292,"children":[],"offset":39056871},{"type":"regular-box","boxType":"stsz","boxSize":2196,"children":[],"offset":39057163},{"type":"regular-box","boxType":"stco","boxSize":116,"children":[],"offset":39059359}],"offset":39056626}],"offset":39056510}],"offset":39056421}]},{"offset":39059475,"boxSize":629,"type":"trak-box","children":[{"offset":39059483,"boxSize":92,"type":"tkhd-box","creationTime":1686832959000,"modificationTime":1686832973000,"trackId":3,"duration":7541,"layer":0,"alternateGroup":0,"volume":0,"matrix":[65536,0,0,0,65536,0,0,0,1073741824],"width":0,"height":0,"version":0},{"type":"regular-box","boxType":"edts","boxSize":36,"children":[],"offset":39059575},{"type":"regular-box","boxType":"tref","boxSize":32,"children":[],"offset":39059611},{"type":"regular-box","boxType":"mdia","boxSize":461,"children":[{"type":"mdhd-box","duration":7541,"timescale":600,"version":0,"language":21956,"quality":0},{"type":"regular-box","boxType":"hdlr","boxSize":52,"children":[],"offset":39059683},{"type":"regular-box","boxType":"minf","boxSize":369,"children":[{"type":"regular-box","boxType":"gmhd","boxSize":32,"children":[],"offset":39059743},{"type":"regular-box","boxType":"hdlr","boxSize":56,"children":[],"offset":39059775},{"type":"regular-box","boxType":"dinf","boxSize":36,"children":[],"offset":39059831},{"type":"regular-box","boxType":"stbl","boxSize":237,"children":[{"type":"stsd-box","boxSize":133,"offset":39059875,"numberOfEntries":1,"samples":[{"type":"unknown","offset":39059891,"dataReferenceIndex":1,"version":0,"revisionLevel":101,"vendor":[107,101,121,115],"size":117,"format":"mebx"}]},{"type":"stts-box","sampleDistribution":[{"sampleCount":1,"sampleDelta":7541}]},{"type":"regular-box","boxType":"stsc","boxSize":28,"children":[],"offset":39060032},{"type":"regular-box","boxType":"stsz","boxSize":24,"children":[],"offset":39060060},{"type":"regular-box","boxType":"stco","boxSize":20,"children":[],"offset":39060084}],"offset":39059867}],"offset":39059735}],"offset":39059643}]},{"offset":39060104,"boxSize":1074,"type":"trak-box","children":[{"offset":39060112,"boxSize":92,"type":"tkhd-box","creationTime":1686832959000,"modificationTime":1686832973000,"trackId":4,"duration":7541,"layer":0,"alternateGroup":0,"volume":0,"matrix":[65536,0,0,0,65536,0,0,0,1073741824],"width":0,"height":0,"version":0},{"type":"regular-box","boxType":"edts","boxSize":36,"children":[],"offset":39060204},{"type":"regular-box","boxType":"tref","boxSize":32,"children":[],"offset":39060240},{"type":"regular-box","boxType":"mdia","boxSize":906,"children":[{"type":"mdhd-box","duration":7541,"timescale":600,"version":0,"language":21956,"quality":0},{"type":"regular-box","boxType":"hdlr","boxSize":52,"children":[],"offset":39060312},{"type":"regular-box","boxType":"minf","boxSize":814,"children":[{"type":"regular-box","boxType":"gmhd","boxSize":32,"children":[],"offset":39060372},{"type":"regular-box","boxType":"hdlr","boxSize":56,"children":[],"offset":39060404},{"type":"regular-box","boxType":"dinf","boxSize":36,"children":[],"offset":39060460},{"type":"regular-box","boxType":"stbl","boxSize":682,"children":[{"type":"stsd-box","boxSize":578,"offset":39060504,"numberOfEntries":1,"samples":[{"type":"unknown","offset":39060520,"dataReferenceIndex":1,"version":0,"revisionLevel":502,"vendor":[107,101,121,115],"size":562,"format":"mebx"}]},{"type":"stts-box","sampleDistribution":[{"sampleCount":1,"sampleDelta":7541}]},{"type":"regular-box","boxType":"stsc","boxSize":28,"children":[],"offset":39061106},{"type":"regular-box","boxType":"stsz","boxSize":24,"children":[],"offset":39061134},{"type":"regular-box","boxType":"stco","boxSize":20,"children":[],"offset":39061158}],"offset":39060496}],"offset":39060364}],"offset":39060272}]},{"offset":39061178,"boxSize":1218,"type":"trak-box","children":[{"offset":39061186,"boxSize":92,"type":"tkhd-box","creationTime":1686832959000,"modificationTime":1686832973000,"trackId":5,"duration":7541,"layer":0,"alternateGroup":0,"volume":0,"matrix":[65536,0,0,0,65536,0,0,0,1073741824],"width":0,"height":0,"version":0},{"type":"regular-box","boxType":"edts","boxSize":36,"children":[],"offset":39061278},{"type":"regular-box","boxType":"tref","boxSize":32,"children":[],"offset":39061314},{"type":"regular-box","boxType":"mdia","boxSize":1050,"children":[{"type":"mdhd-box","duration":7541,"timescale":600,"version":0,"language":21956,"quality":0},{"type":"regular-box","boxType":"hdlr","boxSize":52,"children":[],"offset":39061386},{"type":"regular-box","boxType":"minf","boxSize":958,"children":[{"type":"regular-box","boxType":"gmhd","boxSize":32,"children":[],"offset":39061446},{"type":"regular-box","boxType":"hdlr","boxSize":56,"children":[],"offset":39061478},{"type":"regular-box","boxType":"dinf","boxSize":36,"children":[],"offset":39061534},{"type":"regular-box","boxType":"stbl","boxSize":826,"children":[{"type":"stsd-box","boxSize":598,"offset":39061578,"numberOfEntries":1,"samples":[{"type":"unknown","offset":39061594,"dataReferenceIndex":1,"version":0,"revisionLevel":566,"vendor":[107,101,121,115],"size":582,"format":"mebx"}]},{"type":"stts-box","sampleDistribution":[{"sampleCount":269,"sampleDelta":20},{"sampleCount":1,"sampleDelta":21},{"sampleCount":107,"sampleDelta":20}]},{"type":"regular-box","boxType":"stsc","boxSize":40,"children":[],"offset":39062216},{"type":"regular-box","boxType":"stsz","boxSize":20,"children":[],"offset":39062256},{"type":"regular-box","boxType":"stco","boxSize":120,"children":[],"offset":39062276}],"offset":39061570}],"offset":39061438}],"offset":39061346}]},{"type":"regular-box","boxType":"meta","boxSize":532,"children":[],"offset":39062396}]}]
@@ -0,0 +1,21 @@
1
+ import type { BufferIterator } from '../../../buffer-iterator';
2
+ type AudioObjectType = 'aac' | 'mp3' | 'unknown';
3
+ type DecoderConfigDescriptor = {
4
+ type: 'decoder-config-descriptor';
5
+ objectTypeIndication: AudioObjectType;
6
+ };
7
+ type SlConfigDescriptor = {
8
+ type: 'sl-config-descriptor';
9
+ };
10
+ type UnknownDescriptor = {
11
+ type: 'unknown-descriptor';
12
+ };
13
+ export type Descriptor = DecoderConfigDescriptor | SlConfigDescriptor | UnknownDescriptor;
14
+ type DescriptorAndNext = {
15
+ descriptor: Descriptor | null;
16
+ };
17
+ export declare const processDescriptor: ({ iterator, }: {
18
+ iterator: BufferIterator;
19
+ }) => DescriptorAndNext;
20
+ export declare const parseDescriptors: (iterator: BufferIterator, maxBytes: number) => Descriptor[];
21
+ export {};
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseDescriptors = exports.processDescriptor = void 0;
4
+ const mapToObjectAudioIndicator = (num) => {
5
+ // https://chromium.googlesource.com/chromium/src/media/+/master/formats/mp4/es_descriptor.h
6
+ // http://netmedia.zju.edu.cn/multimedia2013/mpeg-4/ISO%20IEC%2014496-1%20MPEG-4%20System%20Standard.pdf
7
+ // Page 42, table 8
8
+ if (num === 0x40) {
9
+ return 'aac';
10
+ }
11
+ if (num === 0x6b) {
12
+ return 'mp3';
13
+ }
14
+ return 'unknown';
15
+ };
16
+ const processDescriptor = ({ iterator, }) => {
17
+ const tag = iterator.getUint8();
18
+ if (tag === 4) {
19
+ const size = iterator.getPaddedFourByteNumber();
20
+ const initialOffset = iterator.counter.getOffset();
21
+ const objectTypeIndication = iterator.getUint8();
22
+ const remaining = size - (iterator.counter.getOffset() - initialOffset);
23
+ iterator.discard(remaining);
24
+ return {
25
+ descriptor: {
26
+ type: 'decoder-config-descriptor',
27
+ objectTypeIndication: mapToObjectAudioIndicator(objectTypeIndication),
28
+ },
29
+ };
30
+ }
31
+ if (tag === 6) {
32
+ const size = iterator.getPaddedFourByteNumber();
33
+ iterator.discard(size);
34
+ return {
35
+ descriptor: {
36
+ type: 'sl-config-descriptor',
37
+ },
38
+ };
39
+ }
40
+ return {
41
+ descriptor: null,
42
+ };
43
+ };
44
+ exports.processDescriptor = processDescriptor;
45
+ const parseDescriptors = (iterator, maxBytes) => {
46
+ const descriptors = [];
47
+ const initialOffset = iterator.counter.getOffset();
48
+ while (iterator.bytesRemaining() > 0 &&
49
+ iterator.counter.getOffset() - initialOffset < maxBytes) {
50
+ const { descriptor } = (0, exports.processDescriptor)({
51
+ iterator,
52
+ });
53
+ if (descriptor) {
54
+ descriptors.push(descriptor);
55
+ }
56
+ else {
57
+ break;
58
+ }
59
+ }
60
+ return descriptors;
61
+ };
62
+ exports.parseDescriptors = parseDescriptors;
@@ -0,0 +1,15 @@
1
+ import type { BufferIterator } from '../../../buffer-iterator';
2
+ import type { Descriptor } from './esds-descriptors';
3
+ export interface EsdsBox {
4
+ type: 'esds-box';
5
+ version: number;
6
+ tag: number;
7
+ sizeOfInstance: number;
8
+ esId: number;
9
+ descriptors: Descriptor[];
10
+ }
11
+ export declare const parseEsds: ({ data, size, fileOffset, }: {
12
+ data: BufferIterator;
13
+ size: number;
14
+ fileOffset: number;
15
+ }) => EsdsBox;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseEsds = void 0;
4
+ const esds_descriptors_1 = require("./esds-descriptors");
5
+ const parseEsds = ({ data, size, fileOffset, }) => {
6
+ const version = data.getUint8();
7
+ // Flags, we discard them
8
+ data.discard(3);
9
+ const tag = data.getUint8();
10
+ const sizeOfInstance = data.getPaddedFourByteNumber();
11
+ const esId = data.getUint16();
12
+ // disard 1 byte, currently unknown
13
+ data.discard(1);
14
+ const remaining = size - (data.counter.getOffset() - fileOffset);
15
+ const descriptors = (0, esds_descriptors_1.parseDescriptors)(data, remaining);
16
+ const remainingNow = size - (data.counter.getOffset() - fileOffset);
17
+ data.discard(remainingNow);
18
+ return {
19
+ type: 'esds-box',
20
+ version,
21
+ tag,
22
+ sizeOfInstance,
23
+ esId,
24
+ descriptors,
25
+ };
26
+ };
27
+ exports.parseEsds = parseEsds;
@@ -0,0 +1,9 @@
1
+ import type { BaseBox } from './base-type';
2
+ export interface FtypBox extends BaseBox {
3
+ type: 'ftyp-box';
4
+ majorBrand: string;
5
+ minorVersion: number;
6
+ compatibleBrands: string[];
7
+ }
8
+ export declare const fourByteToNumber: (data: ArrayBuffer, from: number) => number;
9
+ export declare const parseFtyp: (data: ArrayBuffer, offset: number) => FtypBox;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFtyp = exports.fourByteToNumber = void 0;
4
+ const fourByteToNumber = (data, from) => {
5
+ const view = new DataView(data);
6
+ return ((view.getUint8(from + 0) << 24) |
7
+ (view.getUint8(from + 1) << 16) |
8
+ (view.getUint8(from + 2) << 8) |
9
+ view.getUint8(from + 3));
10
+ };
11
+ exports.fourByteToNumber = fourByteToNumber;
12
+ const parseFtyp = (data, offset) => {
13
+ const majorBrand = new TextDecoder().decode(data.slice(8, 12)).trim();
14
+ const minorVersion = (0, exports.fourByteToNumber)(data, 12);
15
+ const rest = data.slice(16);
16
+ const types = rest.byteLength / 4;
17
+ const compatibleBrands = [];
18
+ for (let i = 0; i < types; i++) {
19
+ const fourBytes = rest.slice(i * 4, i * 4 + 4);
20
+ compatibleBrands.push(new TextDecoder().decode(fourBytes).trim());
21
+ }
22
+ return {
23
+ type: 'ftyp-box',
24
+ majorBrand,
25
+ minorVersion,
26
+ compatibleBrands,
27
+ offset,
28
+ boxSize: data.byteLength,
29
+ };
30
+ };
31
+ exports.parseFtyp = parseFtyp;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseBoxes = void 0;
4
+ const esds_1 = require("./esds/esds");
4
5
  const ftyp_1 = require("./ftyp");
5
6
  const mdhd_1 = require("./mdhd");
6
7
  const moov_1 = require("./moov/moov");
@@ -15,6 +16,7 @@ const getChildren = ({ boxType, iterator, bytesRemainingInBox, }) => {
15
16
  boxType === 'minf' ||
16
17
  boxType === 'stbl' ||
17
18
  boxType === 'dims' ||
19
+ boxType === 'wave' ||
18
20
  boxType === 'stsb';
19
21
  if (parseChildren) {
20
22
  const parsed = (0, exports.parseBoxes)({
@@ -28,6 +30,9 @@ const getChildren = ({ boxType, iterator, bytesRemainingInBox, }) => {
28
30
  }
29
31
  return parsed.segments;
30
32
  }
33
+ if (bytesRemainingInBox < 0) {
34
+ throw new Error('Box size is too big ' + JSON.stringify({ boxType }));
35
+ }
31
36
  iterator.discard(bytesRemainingInBox);
32
37
  return [];
33
38
  };
@@ -132,6 +137,18 @@ const processBox = ({ iterator, allowIncompleteBoxes, }) => {
132
137
  size: boxSize,
133
138
  };
134
139
  }
140
+ if (boxType === 'esds') {
141
+ const box = (0, esds_1.parseEsds)({
142
+ data: iterator,
143
+ size: boxSize,
144
+ fileOffset,
145
+ });
146
+ return {
147
+ type: 'complete',
148
+ box,
149
+ size: boxSize,
150
+ };
151
+ }
135
152
  const bytesRemainingInBox = boxSize - (iterator.counter.getOffset() - fileOffset);
136
153
  const children = getChildren({
137
154
  boxType,
@@ -1,4 +1,5 @@
1
1
  import type { BufferIterator } from '../../../buffer-iterator';
2
+ import type { AnySegment } from '../../../parse-result';
2
3
  type SampleBase = {
3
4
  format: string;
4
5
  offset: number;
@@ -19,6 +20,7 @@ type AudioSample = SampleBase & {
19
20
  bytesPerPacket: number | null;
20
21
  bytesPerFrame: number | null;
21
22
  bitsPerSample: number | null;
23
+ children: AnySegment[];
22
24
  };
23
25
  type VideoSample = SampleBase & {
24
26
  type: 'video';
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseSamples = exports.processSample = void 0;
4
+ const process_box_1 = require("../process-box");
4
5
  // https://developer.apple.com/documentation/quicktime-file-format/video_sample_description
5
6
  const videoTags = [
6
7
  'cvid',
@@ -99,7 +100,15 @@ const processSample = ({ iterator, }) => {
99
100
  const packetSize = iterator.getUint16();
100
101
  const sampleRate = iterator.getFixedPoint1616Number();
101
102
  const bytesRemainingInBox = boxSize - (iterator.counter.getOffset() - fileOffset);
102
- iterator.discard(bytesRemainingInBox);
103
+ const children = (0, process_box_1.parseBoxes)({
104
+ iterator,
105
+ allowIncompleteBoxes: false,
106
+ maxBytes: bytesRemainingInBox,
107
+ initialBoxes: [],
108
+ });
109
+ if (children.status === 'incomplete') {
110
+ throw new Error('Incomplete boxes are not allowed');
111
+ }
103
112
  return {
104
113
  sample: {
105
114
  format: boxFormat,
@@ -119,21 +128,30 @@ const processSample = ({ iterator, }) => {
119
128
  bytesPerPacket: null,
120
129
  bytesPerFrame: null,
121
130
  bitsPerSample: null,
131
+ children: children.segments,
122
132
  },
123
133
  };
124
134
  }
125
135
  if (version === 1) {
126
136
  const numberOfChannels = iterator.getUint16();
127
137
  const sampleSize = iterator.getUint16();
128
- const compressionId = iterator.getUint16();
138
+ const compressionId = iterator.getInt16();
129
139
  const packetSize = iterator.getUint16();
130
140
  const sampleRate = iterator.getFixedPoint1616Number();
131
- const samplesPerPacket = iterator.getUint16();
132
- const bytesPerPacket = iterator.getUint16();
133
- const bytesPerFrame = iterator.getUint16();
134
- const bitsPerSample = iterator.getUint16();
141
+ const samplesPerPacket = iterator.getUint32();
142
+ const bytesPerPacket = iterator.getUint32();
143
+ const bytesPerFrame = iterator.getUint32();
144
+ const bytesPerSample = iterator.getUint32();
135
145
  const bytesRemainingInBox = boxSize - (iterator.counter.getOffset() - fileOffset);
136
- iterator.discard(bytesRemainingInBox);
146
+ const children = (0, process_box_1.parseBoxes)({
147
+ iterator,
148
+ allowIncompleteBoxes: false,
149
+ maxBytes: bytesRemainingInBox,
150
+ initialBoxes: [],
151
+ });
152
+ if (children.status === 'incomplete') {
153
+ throw new Error('Incomplete boxes are not allowed');
154
+ }
137
155
  return {
138
156
  sample: {
139
157
  format: boxFormat,
@@ -152,7 +170,8 @@ const processSample = ({ iterator, }) => {
152
170
  samplesPerPacket,
153
171
  bytesPerPacket,
154
172
  bytesPerFrame,
155
- bitsPerSample,
173
+ bitsPerSample: bytesPerSample,
174
+ children: children.segments,
156
175
  },
157
176
  };
158
177
  }
@@ -6,11 +6,11 @@ const segments_1 = require("./segments");
6
6
  const parseWebm = (counter) => {
7
7
  counter.discard(4);
8
8
  const length = counter.getVint();
9
- if (length !== 31) {
10
- throw new Error(`Expected header length 31, got ${length}`);
9
+ if (length !== 31 && length !== 35) {
10
+ throw new Error(`Expected header length 31 or 25, got ${length}`);
11
11
  }
12
12
  // Discard header for now
13
- counter.discard(31);
13
+ counter.discard(length);
14
14
  return { status: 'done', segments: [(0, segments_1.expectSegment)(counter)] };
15
15
  };
16
16
  exports.parseWebm = parseWebm;
@@ -79,3 +79,23 @@ export type InterlacedSegment = {
79
79
  interlaced: boolean;
80
80
  };
81
81
  export declare const parseInterlacedSegment: (iterator: BufferIterator) => InterlacedSegment;
82
+ export type CodecPrivateSegment = {
83
+ type: 'codec-private-segment';
84
+ codecPrivateData: number[];
85
+ };
86
+ export declare const parseCodecPrivateSegment: (iterator: BufferIterator) => CodecPrivateSegment;
87
+ export type Crc32Segment = {
88
+ type: 'crc32-segment';
89
+ crc32: number[];
90
+ };
91
+ export declare const parseCrc32Segment: (iterator: BufferIterator) => Crc32Segment;
92
+ export type SegmentUUIDSegment = {
93
+ type: 'segment-uuid-segment';
94
+ segmentUUID: string;
95
+ };
96
+ export declare const parseSegmentUUIDSegment: (iterator: BufferIterator) => SegmentUUIDSegment;
97
+ export type DefaultFlagSegment = {
98
+ type: 'default-flag-segment';
99
+ defaultFlag: boolean;
100
+ };
101
+ export declare const parseDefaultFlagSegment: (iterator: BufferIterator) => DefaultFlagSegment;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseInterlacedSegment = exports.parseTitleSegment = exports.parseColorSegment = exports.parseMaxBlockAdditionId = exports.parseAlphaModeSegment = exports.parseHeightSegment = exports.parseWidthSegment = exports.parseVideoSegment = exports.parseDefaultDurationSegment = exports.parseTrackTypeSegment = exports.parseCodecSegment = exports.parseLanguageSegment = exports.parseFlagLacing = exports.parseTrackUID = exports.parseTrackNumber = exports.parseTrackEntry = void 0;
3
+ exports.parseDefaultFlagSegment = exports.parseSegmentUUIDSegment = exports.parseCrc32Segment = exports.parseCodecPrivateSegment = exports.parseInterlacedSegment = exports.parseTitleSegment = exports.parseColorSegment = exports.parseMaxBlockAdditionId = exports.parseAlphaModeSegment = exports.parseHeightSegment = exports.parseWidthSegment = exports.parseVideoSegment = exports.parseDefaultDurationSegment = exports.parseTrackTypeSegment = exports.parseCodecSegment = exports.parseLanguageSegment = exports.parseFlagLacing = exports.parseTrackUID = exports.parseTrackNumber = exports.parseTrackEntry = void 0;
4
4
  const parse_children_1 = require("./parse-children");
5
5
  const parseTrackEntry = (iterator) => {
6
6
  const offset = iterator.counter.getOffset();
@@ -162,7 +162,7 @@ const parseMaxBlockAdditionId = (iterator) => {
162
162
  exports.parseMaxBlockAdditionId = parseMaxBlockAdditionId;
163
163
  const parseColorSegment = (iterator) => {
164
164
  const length = iterator.getVint();
165
- iterator.discard(length - 1);
165
+ iterator.discard(length);
166
166
  return {
167
167
  type: 'color-segment',
168
168
  };
@@ -189,3 +189,38 @@ const parseInterlacedSegment = (iterator) => {
189
189
  };
190
190
  };
191
191
  exports.parseInterlacedSegment = parseInterlacedSegment;
192
+ const parseCodecPrivateSegment = (iterator) => {
193
+ const length = iterator.getVint();
194
+ return {
195
+ type: 'codec-private-segment',
196
+ codecPrivateData: [...iterator.getSlice(length)],
197
+ };
198
+ };
199
+ exports.parseCodecPrivateSegment = parseCodecPrivateSegment;
200
+ const parseCrc32Segment = (iterator) => {
201
+ const length = iterator.getVint();
202
+ return {
203
+ type: 'crc32-segment',
204
+ crc32: [...iterator.getSlice(length)],
205
+ };
206
+ };
207
+ exports.parseCrc32Segment = parseCrc32Segment;
208
+ const parseSegmentUUIDSegment = (iterator) => {
209
+ const length = iterator.getVint();
210
+ return {
211
+ type: 'segment-uuid-segment',
212
+ segmentUUID: iterator.getSlice(length).toString(),
213
+ };
214
+ };
215
+ exports.parseSegmentUUIDSegment = parseSegmentUUIDSegment;
216
+ const parseDefaultFlagSegment = (iterator) => {
217
+ const length = iterator.getVint();
218
+ if (length !== 1) {
219
+ throw new Error('Expected default flag segment to be 1 byte');
220
+ }
221
+ return {
222
+ type: 'default-flag-segment',
223
+ defaultFlag: Boolean(iterator.getUint8()),
224
+ };
225
+ };
226
+ exports.parseDefaultFlagSegment = parseDefaultFlagSegment;
@@ -7,10 +7,10 @@ import { type SeekSegment } from './segments/seek';
7
7
  import type { SeekHeadSegment } from './segments/seek-head';
8
8
  import { type SeekPositionSegment } from './segments/seek-position';
9
9
  import type { TimestampScaleSegment } from './segments/timestamp-scale';
10
- import type { AlphaModeSegment, CodecSegment, ColorSegment, DefaultDurationSegment, FlagLacingSegment, HeightSegment, InterlacedSegment, LanguageSegment, MaxBlockAdditionId, TitleSegment, TrackEntrySegment, TrackNumberSegment, TrackTypeSegment, TrackUIDSegment, VideoSegment, WidthSegment } from './segments/track-entry';
10
+ import type { AlphaModeSegment, CodecPrivateSegment, CodecSegment, ColorSegment, Crc32Segment, DefaultDurationSegment, DefaultFlagSegment, FlagLacingSegment, HeightSegment, InterlacedSegment, LanguageSegment, MaxBlockAdditionId, SegmentUUIDSegment, TitleSegment, TrackEntrySegment, TrackNumberSegment, TrackTypeSegment, TrackUIDSegment, VideoSegment, WidthSegment } from './segments/track-entry';
11
11
  import type { TracksSegment } from './segments/tracks';
12
12
  import type { UnknownSegment } from './segments/unknown';
13
13
  import type { VoidSegment } from './segments/void';
14
14
  import type { WritingAppSegment } from './segments/writing';
15
- export type MatroskaSegment = MainSegment | UnknownSegment | SeekHeadSegment | SeekSegment | SeekPositionSegment | VoidSegment | InfoSegment | TimestampScaleSegment | MuxingAppSegment | WritingAppSegment | DurationSegment | TracksSegment | TrackEntrySegment | TrackNumberSegment | TrackUIDSegment | FlagLacingSegment | LanguageSegment | CodecSegment | TrackTypeSegment | DefaultDurationSegment | VideoSegment | WidthSegment | HeightSegment | AlphaModeSegment | MaxBlockAdditionId | ColorSegment | TitleSegment | InterlacedSegment;
15
+ export type MatroskaSegment = MainSegment | UnknownSegment | SeekHeadSegment | SeekSegment | SeekPositionSegment | VoidSegment | InfoSegment | TimestampScaleSegment | MuxingAppSegment | WritingAppSegment | DurationSegment | TracksSegment | TrackEntrySegment | TrackNumberSegment | TrackUIDSegment | FlagLacingSegment | LanguageSegment | CodecSegment | TrackTypeSegment | DefaultDurationSegment | VideoSegment | WidthSegment | HeightSegment | AlphaModeSegment | MaxBlockAdditionId | ColorSegment | TitleSegment | InterlacedSegment | CodecPrivateSegment | Crc32Segment | SegmentUUIDSegment | DefaultFlagSegment;
16
16
  export declare const expectSegment: (iterator: BufferIterator) => MatroskaSegment;
@@ -100,9 +100,21 @@ const expectSegment = (iterator) => {
100
100
  if (segmentId === '0x53c0') {
101
101
  return (0, track_entry_1.parseAlphaModeSegment)(iterator);
102
102
  }
103
+ if (segmentId === '0x63a2') {
104
+ return (0, track_entry_1.parseCodecPrivateSegment)(iterator);
105
+ }
103
106
  if (segmentId === '0x7ba9') {
104
107
  return (0, track_entry_1.parseTitleSegment)(iterator);
105
108
  }
109
+ if (segmentId === '0xbf') {
110
+ return (0, track_entry_1.parseCrc32Segment)(iterator);
111
+ }
112
+ if (segmentId === '0x73a4') {
113
+ return (0, track_entry_1.parseSegmentUUIDSegment)(iterator);
114
+ }
115
+ if (segmentId === '0x88') {
116
+ return (0, track_entry_1.parseDefaultFlagSegment)(iterator);
117
+ }
106
118
  const length = iterator.getVint();
107
119
  const bytesRemaining = iterator.byteLength() - iterator.counter.getOffset();
108
120
  const toDiscard = Math.min(bytesRemaining, length > 0 ? length : bytesRemaining);
@@ -7,7 +7,7 @@ export declare class OffsetCounter {
7
7
  discardBytes(amount: number): void;
8
8
  decrement(amount: number): void;
9
9
  }
10
- export declare const getArrayBufferIterator: (initialData: Uint8Array) => {
10
+ export declare const getArrayBufferIterator: (initialData: Uint8Array, maxBytes?: number) => {
11
11
  addData: (newData: Uint8Array) => void;
12
12
  counter: OffsetCounter;
13
13
  byteLength: () => number;
@@ -19,6 +19,7 @@ export declare const getArrayBufferIterator: (initialData: Uint8Array) => {
19
19
  getFourByteNumber: () => number;
20
20
  getSlice: (amount: number) => Uint8Array;
21
21
  getAtom: () => string;
22
+ getPaddedFourByteNumber: () => number;
22
23
  getMatroskaSegmentId: () => string;
23
24
  getVint: () => number;
24
25
  getUint8: () => number;
@@ -54,8 +54,12 @@ const matchesPattern = (pattern) => {
54
54
  const makeOffsetCounter = () => {
55
55
  return new OffsetCounter(0);
56
56
  };
57
- const getArrayBufferIterator = (initialData) => {
58
- let data = initialData;
57
+ const getArrayBufferIterator = (initialData, maxBytes) => {
58
+ const buf = new ArrayBuffer(initialData.byteLength, {
59
+ maxByteLength: maxBytes !== null && maxBytes !== void 0 ? maxBytes : 1000000000,
60
+ });
61
+ let data = new Uint8Array(buf);
62
+ data.set(initialData);
59
63
  let view = new DataView(data.buffer);
60
64
  const counter = makeOffsetCounter();
61
65
  const getSlice = (amount) => {
@@ -71,15 +75,24 @@ const getArrayBufferIterator = (initialData) => {
71
75
  const getFourByteNumber = () => {
72
76
  return ((getUint8() << 24) | (getUint8() << 16) | (getUint8() << 8) | getUint8());
73
77
  };
78
+ const getPaddedFourByteNumber = () => {
79
+ let lastInt = 128;
80
+ while (((lastInt = getUint8()), lastInt === 128)) {
81
+ // Do nothing
82
+ }
83
+ return lastInt;
84
+ };
74
85
  const getUint32 = () => {
75
86
  const val = view.getUint32(counter.getDiscardedOffset());
76
87
  counter.increment(4);
77
88
  return val;
78
89
  };
79
90
  const addData = (newData) => {
80
- const newArray = new Uint8Array(data.buffer.byteLength + newData.byteLength);
81
- newArray.set(data);
82
- newArray.set(new Uint8Array(newData), data.byteLength);
91
+ const oldLength = buf.byteLength;
92
+ const newLength = oldLength + newData.byteLength;
93
+ buf.resize(newLength);
94
+ const newArray = new Uint8Array(buf);
95
+ newArray.set(newData, oldLength);
83
96
  data = newArray;
84
97
  view = new DataView(data.buffer);
85
98
  };
@@ -98,9 +111,9 @@ const getArrayBufferIterator = (initialData) => {
98
111
  const removeBytesRead = () => {
99
112
  const bytesToRemove = counter.getDiscardedOffset();
100
113
  counter.discardBytes(bytesToRemove);
101
- const newArray = new Uint8Array(data.buffer.byteLength - bytesToRemove);
102
- newArray.set(data.slice(bytesToRemove));
103
- data = newArray;
114
+ const newData = data.slice(bytesToRemove);
115
+ data.set(newData);
116
+ buf.resize(newData.byteLength);
104
117
  view = new DataView(data.buffer);
105
118
  };
106
119
  return {
@@ -120,6 +133,7 @@ const getArrayBufferIterator = (initialData) => {
120
133
  const atom = getSlice(4);
121
134
  return new TextDecoder().decode(atom);
122
135
  },
136
+ getPaddedFourByteNumber,
123
137
  getMatroskaSegmentId: () => {
124
138
  const first = getSlice(1);
125
139
  const firstOneString = `0x${Array.from(new Uint8Array(first))
@@ -140,6 +154,9 @@ const getArrayBufferIterator = (initialData) => {
140
154
  '0xb0',
141
155
  '0xba',
142
156
  '0x9a',
157
+ '0xe1',
158
+ '0xbf',
159
+ '0x88',
143
160
  ];
144
161
  if (knownIdsWithOneLength.includes(firstOneString)) {
145
162
  return firstOneString;
@@ -157,6 +174,8 @@ const getArrayBufferIterator = (initialData) => {
157
174
  '0x55ee',
158
175
  '0x55b0',
159
176
  '0x7ba9',
177
+ '0x63a2',
178
+ '0x73a4',
160
179
  ];
161
180
  const firstTwoString = `${firstOneString}${Array.from(new Uint8Array(firstTwo))
162
181
  .map((b) => {
package/dist/from-node.js CHANGED
@@ -5,12 +5,16 @@ const fs_1 = require("fs");
5
5
  const promises_1 = require("node:fs/promises");
6
6
  const stream_1 = require("stream");
7
7
  exports.nodeReader = {
8
- read: (src, range) => {
8
+ read: async (src, range) => {
9
9
  const stream = (0, fs_1.createReadStream)(src, {
10
10
  start: range === null ? 0 : range[0],
11
11
  end: range === null ? Infinity : range[1],
12
12
  });
13
- return Promise.resolve(stream_1.Readable.toWeb(stream).getReader());
13
+ const stats = await (0, promises_1.stat)(src);
14
+ return {
15
+ reader: stream_1.Readable.toWeb(stream).getReader(),
16
+ contentLength: stats.size,
17
+ };
14
18
  },
15
19
  getLength: async (src) => {
16
20
  const stats = await (0, promises_1.stat)(src);
package/dist/from-web.js CHANGED
@@ -21,8 +21,13 @@ exports.webReader = {
21
21
  if (!res.body) {
22
22
  throw new Error('No body');
23
23
  }
24
+ const length = res.headers.get('content-length');
25
+ if (!length) {
26
+ throw new Error('No content-length');
27
+ }
28
+ const contentLength = length === null ? null : parseInt(length, 10);
24
29
  const reader = res.body.getReader();
25
- return reader;
30
+ return { reader, contentLength };
26
31
  },
27
32
  getLength: async (src) => {
28
33
  const res = await fetch(src, {
@@ -0,0 +1,4 @@
1
+ import type { KnownAudioCodecs } from './options';
2
+ import type { AnySegment } from './parse-result';
3
+ export declare const hasAudioCodec: (boxes: AnySegment[]) => boolean;
4
+ export declare const getAudioCodec: (boxes: AnySegment[]) => KnownAudioCodecs | null;