@remotion/media-parser 4.0.231 → 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.
Files changed (95) hide show
  1. package/dist/add-avc-profile-to-track.d.ts +3 -0
  2. package/dist/add-avc-profile-to-track.js +35 -0
  3. package/dist/add-new-matroska-tracks.d.ts +6 -1
  4. package/dist/add-new-matroska-tracks.js +16 -1
  5. package/dist/boxes/avc/parse-avc.d.ts +18 -0
  6. package/dist/boxes/avc/parse-avc.js +96 -0
  7. package/dist/boxes/iso-base-media/make-track.js +3 -3
  8. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +2 -2
  9. package/dist/boxes/iso-base-media/mdat/mdat.js +5 -2
  10. package/dist/boxes/iso-base-media/moov/moov.js +2 -2
  11. package/dist/boxes/iso-base-media/process-box.d.ts +5 -5
  12. package/dist/boxes/iso-base-media/process-box.js +38 -37
  13. package/dist/boxes/iso-base-media/stsd/mebx.js +2 -2
  14. package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -2
  15. package/dist/boxes/iso-base-media/stsd/samples.js +9 -9
  16. package/dist/boxes/iso-base-media/trak/trak.js +2 -2
  17. package/dist/boxes/iso-base-media/traversal.d.ts +1 -1
  18. package/dist/boxes/riff/expect-riff-box.d.ts +16 -0
  19. package/dist/boxes/riff/expect-riff-box.js +49 -0
  20. package/dist/boxes/riff/get-tracks-from-avi.d.ts +21 -0
  21. package/dist/boxes/riff/get-tracks-from-avi.js +108 -0
  22. package/dist/boxes/riff/is-movi.d.ts +2 -0
  23. package/dist/boxes/riff/is-movi.js +12 -0
  24. package/dist/boxes/riff/parse-avih.d.ts +6 -0
  25. package/dist/boxes/riff/parse-avih.js +32 -0
  26. package/dist/boxes/riff/parse-box.d.ts +13 -0
  27. package/dist/boxes/riff/parse-box.js +113 -0
  28. package/dist/boxes/riff/parse-fmt-box.d.ts +7 -0
  29. package/dist/boxes/riff/parse-fmt-box.js +33 -0
  30. package/dist/boxes/riff/parse-list-box.d.ts +8 -0
  31. package/dist/boxes/riff/parse-list-box.js +30 -0
  32. package/dist/boxes/riff/parse-movi.d.ts +17 -0
  33. package/dist/boxes/riff/parse-movi.js +122 -0
  34. package/dist/boxes/riff/parse-riff-box.d.ts +10 -0
  35. package/dist/boxes/riff/parse-riff-box.js +33 -0
  36. package/dist/boxes/riff/parse-strf.d.ts +7 -0
  37. package/dist/boxes/riff/parse-strf.js +67 -0
  38. package/dist/boxes/riff/parse-strh.d.ts +6 -0
  39. package/dist/boxes/riff/parse-strh.js +46 -0
  40. package/dist/boxes/riff/riff-box.d.ts +81 -0
  41. package/dist/boxes/riff/riff-box.js +2 -0
  42. package/dist/boxes/riff/strf.d.ts +7 -0
  43. package/dist/boxes/riff/strf.js +67 -0
  44. package/dist/boxes/riff/timescale.d.ts +1 -0
  45. package/dist/boxes/riff/timescale.js +4 -0
  46. package/dist/boxes/riff/traversal.d.ts +8 -0
  47. package/dist/boxes/riff/traversal.js +36 -0
  48. package/dist/boxes/webm/parse-ebml.js +2 -2
  49. package/dist/boxes/webm/parse-webm-header.d.ts +2 -2
  50. package/dist/boxes/webm/parse-webm-header.js +7 -7
  51. package/dist/boxes/webm/traversal.d.ts +2 -2
  52. package/dist/buffer-iterator.d.ts +6 -1
  53. package/dist/buffer-iterator.js +24 -5
  54. package/dist/create/iso-base-media/create-iso-base-media.js +0 -4
  55. package/dist/create/matroska/create-matroska-media.js +0 -4
  56. package/dist/create/media-fn.d.ts +0 -1
  57. package/dist/create/mp3/create-mp3.d.ts +2 -0
  58. package/dist/create/mp3/create-mp3.js +49 -0
  59. package/dist/create/wav/create-wav.d.ts +2 -0
  60. package/dist/create/wav/create-wav.js +108 -0
  61. package/dist/emit-available-info.d.ts +2 -2
  62. package/dist/emit-available-info.js +6 -4
  63. package/dist/esm/from-node.mjs +2 -1
  64. package/dist/esm/index.mjs +1487 -431
  65. package/dist/get-audio-codec.d.ts +3 -3
  66. package/dist/get-audio-codec.js +2 -2
  67. package/dist/get-container.d.ts +3 -3
  68. package/dist/get-container.js +9 -7
  69. package/dist/get-dimensions.d.ts +3 -3
  70. package/dist/get-duration.d.ts +3 -3
  71. package/dist/get-duration.js +32 -14
  72. package/dist/get-fps.d.ts +3 -3
  73. package/dist/get-fps.js +31 -4
  74. package/dist/get-tracks.d.ts +4 -7
  75. package/dist/get-tracks.js +55 -27
  76. package/dist/get-video-codec.d.ts +5 -4
  77. package/dist/get-video-codec.js +38 -10
  78. package/dist/has-all-info.d.ts +2 -2
  79. package/dist/has-all-info.js +4 -4
  80. package/dist/index.d.ts +1 -0
  81. package/dist/index.js +2 -0
  82. package/dist/options.d.ts +9 -9
  83. package/dist/parse-media.js +2 -0
  84. package/dist/parse-result.d.ts +20 -6
  85. package/dist/parse-video.d.ts +2 -2
  86. package/dist/parse-video.js +5 -16
  87. package/dist/parser-context.d.ts +1 -0
  88. package/dist/parser-state.d.ts +11 -0
  89. package/dist/parser-state.js +30 -0
  90. package/dist/readers/from-node.js +2 -1
  91. package/dist/register-track.d.ts +13 -0
  92. package/dist/register-track.js +25 -0
  93. package/dist/version.d.ts +1 -1
  94. package/dist/version.js +1 -1
  95. package/package.json +3 -3
@@ -17,7 +17,7 @@ import type { TkhdBox } from './tkhd';
17
17
  import type { TrakBox } from './trak/trak';
18
18
  import type { TrunBox } from './trun';
19
19
  export declare const getFtypBox: (segments: AnySegment[]) => FtypBox | null;
20
- export declare const getMoovBox: (segments: AnySegment[]) => MoovBox | null;
20
+ export declare const getMoovBox: (segments: IsoBaseMediaBox[]) => MoovBox | null;
21
21
  export declare const getMoofBox: (main: AnySegment[]) => IsoBaseMediaBox | null;
22
22
  export declare const getMvhdBox: (moovBox: MoovBox) => MvhdBox | null;
23
23
  export declare const getTraks: (moovBox: MoovBox) => TrakBox[];
@@ -0,0 +1,16 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { RiffStructure } from '../../parse-result';
3
+ import type { ParserContext } from '../../parser-context';
4
+ import type { RiffBox } from './riff-box';
5
+ export type RiffResult = {
6
+ type: 'incomplete';
7
+ continueParsing: () => Promise<RiffResult>;
8
+ } | {
9
+ type: 'complete';
10
+ box: RiffBox | null;
11
+ };
12
+ export declare const expectRiffBox: ({ iterator, options, structure, }: {
13
+ iterator: BufferIterator;
14
+ options: ParserContext;
15
+ structure: RiffStructure;
16
+ }) => Promise<RiffResult>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expectRiffBox = void 0;
4
+ const is_movi_1 = require("./is-movi");
5
+ const parse_movi_1 = require("./parse-movi");
6
+ const parse_riff_box_1 = require("./parse-riff-box");
7
+ const expectRiffBox = async ({ iterator, options, structure, }) => {
8
+ // Need at least 16 bytes to read LIST,size,movi,size
9
+ if (iterator.bytesRemaining() < 16) {
10
+ return {
11
+ type: 'incomplete',
12
+ continueParsing() {
13
+ return (0, exports.expectRiffBox)({ structure, iterator, options });
14
+ },
15
+ };
16
+ }
17
+ const ckId = iterator.getByteString(4);
18
+ const ckSize = iterator.getUint32Le();
19
+ if ((0, is_movi_1.isMoviAtom)(iterator, ckId)) {
20
+ iterator.discard(4);
21
+ return (0, parse_movi_1.parseMovi)({
22
+ iterator,
23
+ maxOffset: ckSize + iterator.counter.getOffset() - 4,
24
+ options,
25
+ structure,
26
+ });
27
+ }
28
+ // TODO: Add capability to read partially
29
+ if (iterator.bytesRemaining() < ckSize) {
30
+ iterator.counter.decrement(8);
31
+ return {
32
+ type: 'incomplete',
33
+ continueParsing: () => {
34
+ return (0, exports.expectRiffBox)({ structure, iterator, options });
35
+ },
36
+ };
37
+ }
38
+ return {
39
+ type: 'complete',
40
+ box: await (0, parse_riff_box_1.parseRiffBox)({
41
+ id: ckId,
42
+ iterator,
43
+ size: ckSize,
44
+ boxes: structure.boxes,
45
+ options,
46
+ }),
47
+ };
48
+ };
49
+ exports.expectRiffBox = expectRiffBox;
@@ -0,0 +1,21 @@
1
+ import type { AudioTrack, OtherTrack, VideoTrack } from '../../get-tracks';
2
+ import type { RiffStructure } from '../../parse-result';
3
+ import type { ParserState } from '../../parser-state';
4
+ import type { StrfBoxAudio, StrfBoxVideo, StrhBox } from './riff-box';
5
+ export type AllTracks = {
6
+ videoTracks: VideoTrack[];
7
+ audioTracks: AudioTrack[];
8
+ otherTracks: OtherTrack[];
9
+ };
10
+ export declare const getNumberOfTracks: (structure: RiffStructure) => number;
11
+ export declare const makeAviAudioTrack: ({ strf, index, }: {
12
+ strf: StrfBoxAudio;
13
+ index: number;
14
+ }) => AudioTrack;
15
+ export declare const makeAviVideoTrack: ({ strh, strf, index, }: {
16
+ strh: StrhBox;
17
+ strf: StrfBoxVideo;
18
+ index: number;
19
+ }) => VideoTrack;
20
+ export declare const getTracksFromAvi: (structure: RiffStructure, state: ParserState) => AllTracks;
21
+ export declare const hasAllTracksFromAvi: (structure: RiffStructure, state: ParserState) => boolean;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasAllTracksFromAvi = exports.getTracksFromAvi = exports.makeAviVideoTrack = exports.makeAviAudioTrack = exports.getNumberOfTracks = void 0;
4
+ const add_avc_profile_to_track_1 = require("../../add-avc-profile-to-track");
5
+ const timescale_1 = require("./timescale");
6
+ const traversal_1 = require("./traversal");
7
+ const getNumberOfTracks = (structure) => {
8
+ const avihBox = (0, traversal_1.getAvihBox)(structure);
9
+ if (avihBox) {
10
+ return avihBox.streams;
11
+ }
12
+ throw new Error('No avih box found');
13
+ };
14
+ exports.getNumberOfTracks = getNumberOfTracks;
15
+ const makeAviAudioTrack = ({ strf, index, }) => {
16
+ // 255 = AAC
17
+ if (strf.formatTag !== 255) {
18
+ throw new Error(`Unsupported audio format ${strf.formatTag}`);
19
+ }
20
+ return {
21
+ type: 'audio',
22
+ codec: 'mp4a.40.2', // According to Claude 3.5 Sonnet
23
+ codecPrivate: new Uint8Array([18, 16]),
24
+ codecWithoutConfig: 'aac',
25
+ description: new Uint8Array([18, 16]),
26
+ numberOfChannels: strf.numberOfChannels,
27
+ sampleRate: strf.sampleRate,
28
+ timescale: timescale_1.MEDIA_PARSER_RIFF_TIMESCALE,
29
+ trackId: index,
30
+ trakBox: null,
31
+ };
32
+ };
33
+ exports.makeAviAudioTrack = makeAviAudioTrack;
34
+ const makeAviVideoTrack = ({ strh, strf, index, }) => {
35
+ if (strh.handler !== 'H264') {
36
+ throw new Error(`Unsupported video codec ${strh.handler}`);
37
+ }
38
+ return {
39
+ codecPrivate: null,
40
+ codec: 'to-be-overriden-later',
41
+ codecWithoutConfig: 'h264',
42
+ codedHeight: strf.height,
43
+ codedWidth: strf.width,
44
+ width: strf.width,
45
+ height: strf.height,
46
+ type: 'video',
47
+ displayAspectHeight: strf.height,
48
+ timescale: timescale_1.MEDIA_PARSER_RIFF_TIMESCALE,
49
+ description: undefined,
50
+ trackId: index,
51
+ color: {
52
+ fullRange: null,
53
+ matrixCoefficients: null,
54
+ primaries: null,
55
+ transferCharacteristics: null,
56
+ },
57
+ displayAspectWidth: strf.width,
58
+ trakBox: null,
59
+ rotation: 0,
60
+ sampleAspectRatio: {
61
+ numerator: 1,
62
+ denominator: 1,
63
+ },
64
+ fps: strh.rate / strh.scale,
65
+ };
66
+ };
67
+ exports.makeAviVideoTrack = makeAviVideoTrack;
68
+ const getTracksFromAvi = (structure, state) => {
69
+ if (!(0, traversal_1.isRiffAvi)(structure)) {
70
+ throw new Error('Not an AVI file');
71
+ }
72
+ const videoTracks = [];
73
+ const audioTracks = [];
74
+ const otherTracks = [];
75
+ const boxes = (0, traversal_1.getStrlBoxes)(structure);
76
+ let i = 0;
77
+ for (const box of boxes) {
78
+ const strh = (0, traversal_1.getStrhBox)(box.children);
79
+ const strf = (0, traversal_1.getStrfBox)(box.children);
80
+ if (!strh || !strf) {
81
+ continue;
82
+ }
83
+ if (strf.type === 'strf-box-video') {
84
+ videoTracks.push((0, add_avc_profile_to_track_1.addAvcProfileToTrack)((0, exports.makeAviVideoTrack)({ strh, strf, index: i }), state.getAvcProfile()));
85
+ }
86
+ else if (strh.fccType === 'auds') {
87
+ audioTracks.push((0, exports.makeAviAudioTrack)({ strf, index: i }));
88
+ }
89
+ else {
90
+ throw new Error(`Unsupported track type ${strh.fccType}`);
91
+ }
92
+ i++;
93
+ }
94
+ return { audioTracks, otherTracks, videoTracks };
95
+ };
96
+ exports.getTracksFromAvi = getTracksFromAvi;
97
+ const hasAllTracksFromAvi = (structure, state) => {
98
+ if (!(0, traversal_1.isRiffAvi)(structure)) {
99
+ throw new Error('Not an AVI file');
100
+ }
101
+ const numberOfTracks = (0, exports.getNumberOfTracks)(structure);
102
+ const tracks = (0, exports.getTracksFromAvi)(structure, state);
103
+ return (tracks.videoTracks.length +
104
+ tracks.audioTracks.length +
105
+ tracks.otherTracks.length ===
106
+ numberOfTracks);
107
+ };
108
+ exports.hasAllTracksFromAvi = hasAllTracksFromAvi;
@@ -0,0 +1,2 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ export declare const isMoviAtom: (iterator: BufferIterator, ckId: string) => boolean;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isMoviAtom = void 0;
4
+ const isMoviAtom = (iterator, ckId) => {
5
+ if (ckId !== 'LIST') {
6
+ return false;
7
+ }
8
+ const listType = iterator.getByteString(4);
9
+ iterator.counter.decrement(4);
10
+ return listType === 'movi';
11
+ };
12
+ exports.isMoviAtom = isMoviAtom;
@@ -0,0 +1,6 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { RiffBox } from './riff-box';
3
+ export declare const parseAvih: ({ iterator, size, }: {
4
+ iterator: BufferIterator;
5
+ size: number;
6
+ }) => RiffBox;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseAvih = void 0;
4
+ const parseAvih = ({ iterator, size, }) => {
5
+ const { expectNoMoreBytes } = iterator.startBox(size);
6
+ const dwMicroSecPerFrame = iterator.getUint32Le();
7
+ const dwMaxBytesPerSec = iterator.getUint32Le();
8
+ const paddingGranularity = iterator.getUint32Le();
9
+ const flags = iterator.getUint32Le();
10
+ const totalFrames = iterator.getUint32Le();
11
+ const initialFrames = iterator.getUint32Le();
12
+ const streams = iterator.getUint32Le();
13
+ const suggestedBufferSize = iterator.getUint32Le();
14
+ const width = iterator.getUint32Le();
15
+ const height = iterator.getUint32Le();
16
+ iterator.discard(16);
17
+ expectNoMoreBytes();
18
+ return {
19
+ type: 'avih-box',
20
+ microSecPerFrame: dwMicroSecPerFrame,
21
+ maxBytesPerSecond: dwMaxBytesPerSec,
22
+ paddingGranularity,
23
+ flags,
24
+ totalFrames,
25
+ initialFrames,
26
+ streams,
27
+ suggestedBufferSize,
28
+ height,
29
+ width,
30
+ };
31
+ };
32
+ exports.parseAvih = parseAvih;
@@ -0,0 +1,13 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { ParseResult, RiffStructure } from '../../parse-result';
3
+ import type { ParserContext } from '../../parser-context';
4
+ export declare const parseRiffBody: ({ iterator, structure, maxOffset, options, }: {
5
+ iterator: BufferIterator;
6
+ structure: RiffStructure;
7
+ maxOffset: number;
8
+ options: ParserContext;
9
+ }) => Promise<ParseResult<RiffStructure>>;
10
+ export declare const parseRiff: ({ iterator, options, }: {
11
+ iterator: BufferIterator;
12
+ options: ParserContext;
13
+ }) => Promise<ParseResult<RiffStructure>>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRiff = exports.parseRiffBody = void 0;
4
+ const register_track_1 = require("../../register-track");
5
+ const expect_riff_box_1 = require("./expect-riff-box");
6
+ const get_tracks_from_avi_1 = require("./get-tracks-from-avi");
7
+ const traversal_1 = require("./traversal");
8
+ const continueAfterRiffBoxResult = ({ result, structure, iterator, maxOffset, options, }) => {
9
+ if (result.type === 'incomplete') {
10
+ return Promise.resolve({
11
+ status: 'incomplete',
12
+ async continueParsing() {
13
+ return Promise.resolve(continueAfterRiffBoxResult({
14
+ result: await result.continueParsing(),
15
+ structure,
16
+ iterator,
17
+ maxOffset,
18
+ options,
19
+ }));
20
+ },
21
+ segments: structure,
22
+ skipTo: null,
23
+ });
24
+ }
25
+ if (result.type === 'complete') {
26
+ if (result.box) {
27
+ structure.boxes.push(result.box);
28
+ }
29
+ }
30
+ return (0, exports.parseRiffBody)({ iterator, maxOffset, options, structure });
31
+ };
32
+ const parseRiffBody = async ({ iterator, structure, maxOffset, options, }) => {
33
+ while (iterator.bytesRemaining() > 0 &&
34
+ iterator.counter.getOffset() < maxOffset) {
35
+ const result = await (0, expect_riff_box_1.expectRiffBox)({
36
+ iterator,
37
+ options,
38
+ structure,
39
+ });
40
+ if (result.type === 'incomplete') {
41
+ return {
42
+ status: 'incomplete',
43
+ async continueParsing() {
44
+ return Promise.resolve(continueAfterRiffBoxResult({
45
+ iterator,
46
+ maxOffset,
47
+ options,
48
+ result: await result.continueParsing(),
49
+ structure,
50
+ }));
51
+ },
52
+ segments: structure,
53
+ skipTo: null,
54
+ };
55
+ }
56
+ if (result.box === null) {
57
+ continue;
58
+ }
59
+ structure.boxes.push(result.box);
60
+ if (result.box.type === 'strf-box-video' ||
61
+ result.box.type === 'strf-box-audio') {
62
+ const strh = (0, traversal_1.getStrhBox)(structure.boxes);
63
+ const strf = (0, traversal_1.getStrfBox)(structure.boxes);
64
+ if (!strh || !strf) {
65
+ throw new Error('strh or strf box missing');
66
+ }
67
+ if (strf.type === 'strf-box-audio' && options.onAudioTrack) {
68
+ const audioTrack = (0, get_tracks_from_avi_1.makeAviAudioTrack)({
69
+ index: options.nextTrackIndex,
70
+ strf,
71
+ });
72
+ await (0, register_track_1.registerTrack)({
73
+ options,
74
+ state: options.parserState,
75
+ track: audioTrack,
76
+ });
77
+ }
78
+ if (options.onVideoTrack && strf.type === 'strf-box-video') {
79
+ const videoTrack = (0, get_tracks_from_avi_1.makeAviVideoTrack)({
80
+ strh,
81
+ index: options.nextTrackIndex,
82
+ strf,
83
+ });
84
+ (0, register_track_1.registerVideoTrackWhenProfileIsAvailable)({
85
+ options,
86
+ state: options.parserState,
87
+ track: videoTrack,
88
+ });
89
+ }
90
+ options.nextTrackIndex++;
91
+ }
92
+ }
93
+ return {
94
+ status: 'done',
95
+ segments: structure,
96
+ };
97
+ };
98
+ exports.parseRiffBody = parseRiffBody;
99
+ const parseRiff = ({ iterator, options, }) => {
100
+ const structure = { type: 'riff', boxes: [] };
101
+ const riff = iterator.getByteString(4);
102
+ if (riff !== 'RIFF') {
103
+ throw new Error('Not a RIFF file');
104
+ }
105
+ const size = iterator.getUint32Le();
106
+ const fileType = iterator.getByteString(4);
107
+ if (fileType !== 'WAVE' && fileType !== 'AVI') {
108
+ throw new Error(`File type ${fileType} not supported`);
109
+ }
110
+ structure.boxes.push({ type: 'riff-header', fileSize: size, fileType });
111
+ return (0, exports.parseRiffBody)({ iterator, structure, maxOffset: Infinity, options });
112
+ };
113
+ exports.parseRiff = parseRiff;
@@ -0,0 +1,7 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { RiffBox } from './riff-box';
3
+ export declare const parseFmtBox: ({ iterator, boxes, size, }: {
4
+ iterator: BufferIterator;
5
+ boxes: RiffBox[];
6
+ size: number;
7
+ }) => RiffBox;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFmtBox = void 0;
4
+ const parseFmtBox = ({ iterator, boxes, size, }) => {
5
+ const box = iterator.startBox(size);
6
+ const header = boxes.find((b) => b.type === 'riff-header');
7
+ if (!header) {
8
+ throw new Error('Expected RIFF header');
9
+ }
10
+ if (header.fileType !== 'WAVE') {
11
+ throw new Error('Only supporting WAVE type');
12
+ }
13
+ const wFormatTag = iterator.getUint16Le();
14
+ if (wFormatTag !== 1) {
15
+ throw new Error('Expected wFormatTag to be 1, only supporting this');
16
+ }
17
+ const numberOfChannels = iterator.getUint16Le();
18
+ const sampleRate = iterator.getUint32Le();
19
+ const byteRate = iterator.getUint32Le();
20
+ const blockAlign = iterator.getUint16Le();
21
+ const bitsPerSample = iterator.getUint16Le();
22
+ box.expectNoMoreBytes();
23
+ return {
24
+ type: 'wave-format-box',
25
+ formatTag: wFormatTag,
26
+ numberOfChannels,
27
+ sampleRate,
28
+ blockAlign,
29
+ byteRate,
30
+ bitsPerSample,
31
+ };
32
+ };
33
+ exports.parseFmtBox = parseFmtBox;
@@ -0,0 +1,8 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { ParserContext } from '../../parser-context';
3
+ import type { RiffBox } from './riff-box';
4
+ export declare const parseListBox: ({ iterator, size, options, }: {
5
+ iterator: BufferIterator;
6
+ size: number;
7
+ options: ParserContext;
8
+ }) => Promise<RiffBox>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseListBox = void 0;
4
+ const parse_box_1 = require("./parse-box");
5
+ const parseListBox = async ({ iterator, size, options, }) => {
6
+ const counter = iterator.counter.getOffset();
7
+ const listType = iterator.getByteString(4);
8
+ if (listType === 'movi') {
9
+ throw new Error('should not be handled here');
10
+ }
11
+ const structure = {
12
+ type: 'riff',
13
+ boxes: [],
14
+ };
15
+ const result = await (0, parse_box_1.parseRiffBody)({
16
+ structure,
17
+ iterator,
18
+ maxOffset: counter + size,
19
+ options,
20
+ });
21
+ if (result.status === 'incomplete') {
22
+ throw new Error(`Should only parse complete boxes (${listType})`);
23
+ }
24
+ return {
25
+ type: 'list-box',
26
+ listType,
27
+ children: structure.boxes,
28
+ };
29
+ };
30
+ exports.parseListBox = parseListBox;
@@ -0,0 +1,17 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { RiffStructure } from '../../parse-result';
3
+ import type { ParserContext } from '../../parser-context';
4
+ import type { RiffResult } from './expect-riff-box';
5
+ export declare const handleChunk: ({ iterator, options, structure, ckId, ckSize, }: {
6
+ iterator: BufferIterator;
7
+ options: ParserContext;
8
+ structure: RiffStructure;
9
+ ckId: string;
10
+ ckSize: number;
11
+ }) => Promise<void>;
12
+ export declare const parseMovi: ({ iterator, maxOffset, options, structure, }: {
13
+ iterator: BufferIterator;
14
+ maxOffset: number;
15
+ options: ParserContext;
16
+ structure: RiffStructure;
17
+ }) => Promise<RiffResult>;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseMovi = exports.handleChunk = void 0;
4
+ const parse_avc_1 = require("../avc/parse-avc");
5
+ const timescale_1 = require("./timescale");
6
+ const traversal_1 = require("./traversal");
7
+ const getStrhForIndex = (structure, trackId) => {
8
+ const boxes = (0, traversal_1.getStrlBoxes)(structure);
9
+ const box = boxes[trackId];
10
+ if (!box) {
11
+ throw new Error('Expected box');
12
+ }
13
+ const strh = (0, traversal_1.getStrhBox)(box.children);
14
+ if (!strh) {
15
+ throw new Error('strh');
16
+ }
17
+ return strh;
18
+ };
19
+ const handleChunk = async ({ iterator, options, structure, ckId, ckSize, }) => {
20
+ const videoChunk = ckId.match(/^([0-9]{2})dc$/);
21
+ if (videoChunk) {
22
+ const trackId = parseInt(videoChunk[1], 10);
23
+ const strh = getStrhForIndex(structure, trackId);
24
+ const samplesPerSecond = strh.rate / strh.scale;
25
+ const nthSample = options.parserState.getSamplesForTrack(trackId);
26
+ const timeInSec = nthSample / samplesPerSecond;
27
+ const timestamp = Math.floor(timeInSec * timescale_1.MEDIA_PARSER_RIFF_TIMESCALE);
28
+ const duration = Math.floor((1 / samplesPerSecond) * timescale_1.MEDIA_PARSER_RIFF_TIMESCALE);
29
+ const data = iterator.getSlice(ckSize);
30
+ const infos = (0, parse_avc_1.parseAvc)(data);
31
+ const keyOrDelta = infos.find((i) => i.type === 'keyframe' || i.type === 'delta-frame');
32
+ if (!keyOrDelta) {
33
+ throw new Error('expected avc to contain info about key or delta');
34
+ }
35
+ const avcProfile = infos.find((i) => i.type === 'avc-profile');
36
+ const ppsProfile = infos.find((i) => i.type === 'avc-pps');
37
+ if (avcProfile && ppsProfile) {
38
+ await options.parserState.onProfile({ pps: ppsProfile, sps: avcProfile });
39
+ }
40
+ await options.parserState.onVideoSample(trackId, {
41
+ cts: timestamp,
42
+ dts: timestamp,
43
+ data,
44
+ duration,
45
+ timestamp,
46
+ trackId,
47
+ type: keyOrDelta.type === 'keyframe' ? 'key' : 'delta',
48
+ });
49
+ }
50
+ else {
51
+ const audioChunk = ckId.match(/^([0-9]{2})wb$/);
52
+ if (audioChunk) {
53
+ const trackId = parseInt(audioChunk[1], 10);
54
+ const strh = getStrhForIndex(structure, trackId);
55
+ const samplesPerSecond = strh.rate / strh.scale;
56
+ const nthSample = options.parserState.getSamplesForTrack(trackId);
57
+ const timeInSec = nthSample / samplesPerSecond;
58
+ const timestamp = timeInSec * timescale_1.MEDIA_PARSER_RIFF_TIMESCALE;
59
+ const duration = (1 / samplesPerSecond) * timescale_1.MEDIA_PARSER_RIFF_TIMESCALE;
60
+ await options.parserState.onAudioSample(trackId, {
61
+ cts: timestamp,
62
+ dts: timestamp,
63
+ data: iterator.getSlice(ckSize),
64
+ duration,
65
+ timestamp,
66
+ trackId,
67
+ type: 'key',
68
+ });
69
+ }
70
+ }
71
+ };
72
+ exports.handleChunk = handleChunk;
73
+ const parseMovi = async ({ iterator, maxOffset, options, structure, }) => {
74
+ while (iterator.counter.getOffset() < maxOffset) {
75
+ if (iterator.bytesRemaining() < 8) {
76
+ return {
77
+ type: 'incomplete',
78
+ continueParsing: () => {
79
+ return Promise.resolve((0, exports.parseMovi)({ iterator, maxOffset, options, structure }));
80
+ },
81
+ };
82
+ }
83
+ const ckId = iterator.getByteString(4);
84
+ const ckSize = iterator.getUint32Le();
85
+ if (iterator.bytesRemaining() < ckSize) {
86
+ iterator.counter.decrement(8);
87
+ return {
88
+ type: 'incomplete',
89
+ continueParsing: () => {
90
+ return Promise.resolve((0, exports.parseMovi)({ iterator, maxOffset, options, structure }));
91
+ },
92
+ };
93
+ }
94
+ await (0, exports.handleChunk)({ iterator, options, structure, ckId, ckSize });
95
+ // Discard added zeroes
96
+ while (iterator.counter.getOffset() < maxOffset &&
97
+ iterator.bytesRemaining() > 0) {
98
+ if (iterator.getUint8() !== 0) {
99
+ iterator.counter.decrement(1);
100
+ break;
101
+ }
102
+ }
103
+ }
104
+ if (iterator.counter.getOffset() === maxOffset) {
105
+ return {
106
+ type: 'complete',
107
+ box: {
108
+ type: 'movi-box',
109
+ },
110
+ };
111
+ }
112
+ if (iterator.counter.getOffset() > maxOffset) {
113
+ throw new Error('Oops, this should not happen!');
114
+ }
115
+ return {
116
+ type: 'incomplete',
117
+ continueParsing: () => {
118
+ return Promise.resolve((0, exports.parseMovi)({ iterator, maxOffset, options, structure }));
119
+ },
120
+ };
121
+ };
122
+ exports.parseMovi = parseMovi;
@@ -0,0 +1,10 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { ParserContext } from '../../parser-context';
3
+ import type { RiffBox } from './riff-box';
4
+ export declare const parseRiffBox: ({ iterator, size, id, boxes, options, }: {
5
+ iterator: BufferIterator;
6
+ size: number;
7
+ id: string;
8
+ boxes: RiffBox[];
9
+ options: ParserContext;
10
+ }) => Promise<RiffBox>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRiffBox = void 0;
4
+ const parse_avih_1 = require("./parse-avih");
5
+ const parse_fmt_box_1 = require("./parse-fmt-box");
6
+ const parse_list_box_1 = require("./parse-list-box");
7
+ const parse_strf_1 = require("./parse-strf");
8
+ const parse_strh_1 = require("./parse-strh");
9
+ const parseRiffBox = ({ iterator, size, id, boxes, options, }) => {
10
+ if (id === 'fmt') {
11
+ return Promise.resolve((0, parse_fmt_box_1.parseFmtBox)({ iterator, boxes, size }));
12
+ }
13
+ if (id === 'LIST') {
14
+ return (0, parse_list_box_1.parseListBox)({ iterator, size, options });
15
+ }
16
+ if (id === 'avih') {
17
+ return Promise.resolve((0, parse_avih_1.parseAvih)({ iterator, size }));
18
+ }
19
+ if (id === 'strh') {
20
+ return Promise.resolve((0, parse_strh_1.parseStrh)({ iterator, size }));
21
+ }
22
+ if (id === 'strf') {
23
+ return Promise.resolve((0, parse_strf_1.parseStrf)({ iterator, size, boxes }));
24
+ }
25
+ iterator.discard(size);
26
+ const box = {
27
+ type: 'riff-box',
28
+ size,
29
+ id,
30
+ };
31
+ return Promise.resolve(box);
32
+ };
33
+ exports.parseRiffBox = parseRiffBox;
@@ -0,0 +1,7 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { RiffBox } from './riff-box';
3
+ export declare const parseStrf: ({ iterator, size, boxes, }: {
4
+ iterator: BufferIterator;
5
+ size: number;
6
+ boxes: RiffBox[];
7
+ }) => RiffBox;