@remotion/media-parser 4.0.265 → 4.0.266

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 (137) hide show
  1. package/dist/buffer-iterator.d.ts +1 -0
  2. package/dist/buffer-iterator.js +17 -0
  3. package/dist/containers/aac/parse-aac.js +1 -1
  4. package/dist/containers/avc/create-sps-pps-data.js +15 -1
  5. package/dist/containers/avc/interpret-sps.js +8 -2
  6. package/dist/containers/avc/parse-avc.js +23 -24
  7. package/dist/containers/flac/get-channel-count.d.ts +1 -1
  8. package/dist/containers/flac/m3u/after-manifest-fetch.d.ts +14 -0
  9. package/dist/containers/flac/m3u/after-manifest-fetch.js +53 -0
  10. package/dist/containers/flac/m3u/fetch-m3u8-stream.d.ts +3 -0
  11. package/dist/containers/flac/m3u/fetch-m3u8-stream.js +15 -0
  12. package/dist/containers/flac/m3u/get-chunks.d.ts +6 -0
  13. package/dist/containers/flac/m3u/get-chunks.js +20 -0
  14. package/dist/containers/flac/m3u/get-duration-from-m3u.d.ts +2 -0
  15. package/dist/containers/flac/m3u/get-duration-from-m3u.js +9 -0
  16. package/dist/containers/flac/m3u/get-playlist.d.ts +3 -0
  17. package/dist/containers/flac/m3u/get-playlist.js +19 -0
  18. package/dist/containers/flac/m3u/get-streams.d.ts +13 -0
  19. package/dist/containers/flac/m3u/get-streams.js +41 -0
  20. package/dist/containers/flac/m3u/parse-directive.d.ts +2 -0
  21. package/dist/containers/flac/m3u/parse-directive.js +64 -0
  22. package/dist/containers/flac/m3u/parse-m3u-manifest.d.ts +8 -0
  23. package/dist/containers/flac/m3u/parse-m3u-manifest.js +18 -0
  24. package/dist/containers/flac/m3u/parse-m3u.d.ts +4 -0
  25. package/dist/containers/flac/m3u/parse-m3u.js +35 -0
  26. package/dist/containers/flac/m3u/parse-m3u8-text.d.ts +2 -0
  27. package/dist/containers/flac/m3u/parse-m3u8-text.js +23 -0
  28. package/dist/containers/flac/m3u/parse-stream-inf.d.ts +3 -0
  29. package/dist/containers/flac/m3u/parse-stream-inf.js +61 -0
  30. package/dist/containers/flac/m3u/return-packets.d.ts +14 -0
  31. package/dist/containers/flac/m3u/return-packets.js +63 -0
  32. package/dist/containers/flac/m3u/select-stream.d.ts +10 -0
  33. package/dist/containers/flac/m3u/select-stream.js +15 -0
  34. package/dist/containers/flac/m3u/types.d.ts +48 -0
  35. package/dist/containers/flac/m3u/types.js +2 -0
  36. package/dist/containers/flac/parse-streaminfo.js +1 -1
  37. package/dist/containers/iso-base-media/get-moov-atom.js +3 -2
  38. package/dist/containers/iso-base-media/process-box.js +9 -2
  39. package/dist/containers/iso-base-media/trun.js +1 -1
  40. package/dist/containers/m3u/after-manifest-fetch.d.ts +14 -0
  41. package/dist/containers/m3u/after-manifest-fetch.js +67 -0
  42. package/dist/containers/m3u/fetch-m3u8-stream.d.ts +3 -0
  43. package/dist/containers/m3u/fetch-m3u8-stream.js +18 -0
  44. package/dist/containers/m3u/get-chunks.d.ts +6 -0
  45. package/dist/containers/m3u/get-chunks.js +20 -0
  46. package/dist/containers/m3u/get-duration-from-m3u.d.ts +2 -0
  47. package/dist/containers/m3u/get-duration-from-m3u.js +9 -0
  48. package/dist/containers/m3u/get-playlist.d.ts +3 -0
  49. package/dist/containers/m3u/get-playlist.js +27 -0
  50. package/dist/containers/m3u/get-streams.d.ts +14 -0
  51. package/dist/containers/m3u/get-streams.js +60 -0
  52. package/dist/containers/m3u/parse-directive.d.ts +2 -0
  53. package/dist/containers/m3u/parse-directive.js +64 -0
  54. package/dist/containers/m3u/parse-m3u-manifest.d.ts +8 -0
  55. package/dist/containers/m3u/parse-m3u-manifest.js +18 -0
  56. package/dist/containers/m3u/parse-m3u.d.ts +4 -0
  57. package/dist/containers/m3u/parse-m3u.js +35 -0
  58. package/dist/containers/m3u/parse-m3u8-text.d.ts +2 -0
  59. package/dist/containers/m3u/parse-m3u8-text.js +23 -0
  60. package/dist/containers/m3u/parse-stream-inf.d.ts +3 -0
  61. package/dist/containers/m3u/parse-stream-inf.js +61 -0
  62. package/dist/containers/m3u/return-packets.d.ts +16 -0
  63. package/dist/containers/m3u/return-packets.js +71 -0
  64. package/dist/containers/m3u/select-stream.d.ts +10 -0
  65. package/dist/containers/m3u/select-stream.js +19 -0
  66. package/dist/containers/m3u/types.d.ts +48 -0
  67. package/dist/containers/m3u/types.js +2 -0
  68. package/dist/containers/mp3/parse-mpeg-header.js +1 -1
  69. package/dist/containers/riff/expect-riff-box.js +1 -1
  70. package/dist/containers/transport-stream/boxes.d.ts +4 -1
  71. package/dist/containers/transport-stream/find-separator.d.ts +1 -2
  72. package/dist/containers/transport-stream/find-separator.js +7 -13
  73. package/dist/containers/transport-stream/handle-aac-packet.js +1 -1
  74. package/dist/containers/transport-stream/handle-avc-packet.js +1 -1
  75. package/dist/containers/transport-stream/parse-packet.js +7 -1
  76. package/dist/containers/transport-stream/parse-pat.d.ts +2 -1
  77. package/dist/containers/transport-stream/parse-pat.js +16 -1
  78. package/dist/containers/transport-stream/parse-stream-packet.js +86 -74
  79. package/dist/containers/wav/parse-fmt.js +1 -1
  80. package/dist/containers/webm/parse-ebml.js +9 -2
  81. package/dist/does-need-contentlength-contentrange.d.ts +2 -0
  82. package/dist/does-need-contentlength-contentrange.js +10 -0
  83. package/dist/download-and-parse-media.js +32 -29
  84. package/dist/emit-available-info.js +13 -1
  85. package/dist/emitter.d.ts +4 -0
  86. package/dist/emitter.js +4 -0
  87. package/dist/esm/from-fetch.mjs +65 -38
  88. package/dist/esm/from-node.mjs +2 -8
  89. package/dist/esm/from-web-file.mjs +2 -7
  90. package/dist/esm/index.mjs +1029 -289
  91. package/dist/file-types/detect-file-type.d.ts +5 -1
  92. package/dist/file-types/detect-file-type.js +5 -1
  93. package/dist/file-types/index.js +3 -0
  94. package/dist/forward-controller.d.ts +7 -0
  95. package/dist/forward-controller.js +25 -0
  96. package/dist/get-container.js +3 -0
  97. package/dist/get-duration.js +35 -2
  98. package/dist/get-fields-from-callbacks.js +1 -0
  99. package/dist/get-fps.js +7 -0
  100. package/dist/get-tracks.d.ts +2 -0
  101. package/dist/get-tracks.js +29 -4
  102. package/dist/has-all-info.js +4 -0
  103. package/dist/index.d.ts +46 -9
  104. package/dist/index.js +3 -1
  105. package/dist/init-video.js +8 -0
  106. package/dist/internal-parse-media.js +11 -4
  107. package/dist/is-audio-structure.js +3 -0
  108. package/dist/media-parser-controller.js +3 -1
  109. package/dist/metadata/get-metadata.js +26 -3
  110. package/dist/options.d.ts +9 -1
  111. package/dist/parse-media.js +11 -8
  112. package/dist/parse-result.d.ts +2 -1
  113. package/dist/readers/fetch/get-body-and-reader.d.ts +8 -0
  114. package/dist/readers/fetch/get-body-and-reader.js +41 -0
  115. package/dist/readers/fetch/resolve-url.d.ts +1 -0
  116. package/dist/readers/fetch/resolve-url.js +15 -0
  117. package/dist/readers/from-fetch.js +19 -40
  118. package/dist/readers/from-node.js +1 -7
  119. package/dist/readers/from-uintarray.d.ts +2 -0
  120. package/dist/readers/from-uintarray.js +27 -0
  121. package/dist/readers/from-web-file.js +1 -6
  122. package/dist/readers/reader.d.ts +1 -2
  123. package/dist/register-track.d.ts +8 -3
  124. package/dist/register-track.js +30 -17
  125. package/dist/run-parse-iteration.js +6 -1
  126. package/dist/state/can-skip-tracks.js +2 -1
  127. package/dist/state/emitted-fields.js +1 -0
  128. package/dist/state/m3u-state.d.ts +29 -0
  129. package/dist/state/m3u-state.js +48 -0
  130. package/dist/state/need-samples-for-fields.js +1 -0
  131. package/dist/state/parser-state.d.ts +36 -1
  132. package/dist/state/parser-state.js +4 -1
  133. package/dist/state/structure.d.ts +1 -0
  134. package/dist/state/structure.js +7 -0
  135. package/dist/version.d.ts +1 -1
  136. package/dist/version.js +1 -1
  137. package/package.json +3 -3
@@ -70,6 +70,7 @@ export declare const getArrayBufferIterator: (initialData: Uint8Array, maxBytes:
70
70
  returnToCheckpoint: () => void;
71
71
  };
72
72
  getFlacCodecNumber: () => number;
73
+ readUntilLineEnd: () => string | null;
73
74
  getSyncSafeInt32: () => number;
74
75
  };
75
76
  export type BufferIterator = ReturnType<typeof getArrayBufferIterator>;
@@ -94,6 +94,22 @@ const getArrayBufferIterator = (initialData, maxBytes) => {
94
94
  counter.decrement(1);
95
95
  return new TextDecoder().decode(new Uint8Array(bytes));
96
96
  };
97
+ const readUntilLineEnd = () => {
98
+ const bytes = [];
99
+ // 10 is "\n"
100
+ while (true) {
101
+ if (bytesRemaining() === 0) {
102
+ return null;
103
+ }
104
+ const byte = getUint8();
105
+ bytes.push(byte);
106
+ if (byte === 10) {
107
+ break;
108
+ }
109
+ }
110
+ const str = new TextDecoder().decode(new Uint8Array(bytes)).trim();
111
+ return str;
112
+ };
97
113
  const getUint8 = () => {
98
114
  const val = view.getUint8(counter.getDiscardedOffset());
99
115
  counter.increment(1);
@@ -565,6 +581,7 @@ const getArrayBufferIterator = (initialData, maxBytes) => {
565
581
  readExpGolomb,
566
582
  startCheckpoint,
567
583
  getFlacCodecNumber,
584
+ readUntilLineEnd,
568
585
  getSyncSafeInt32,
569
586
  };
570
587
  };
@@ -46,7 +46,7 @@ const parseAac = async (state) => {
46
46
  iterator.counter.decrement(iterator.counter.getOffset() - startOffset);
47
47
  const data = iterator.getSlice(frameLength);
48
48
  if (state.callbacks.tracks.getTracks().length === 0) {
49
- await (0, register_track_1.registerTrack)({
49
+ await (0, register_track_1.registerAudioTrack)({
50
50
  state,
51
51
  container: 'aac',
52
52
  track: {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSpsPpsData = void 0;
4
4
  const combine_uint8_arrays_1 = require("../../combine-uint8-arrays");
5
+ const truthy_1 = require("../../truthy");
5
6
  function serializeUint16(value) {
6
7
  const buffer = new ArrayBuffer(2);
7
8
  const view = new DataView(buffer);
@@ -29,6 +30,19 @@ const createSpsPpsData = (avc1Profile) => {
29
30
  serializeUint16(avc1Profile.pps.pps.length),
30
31
  // PPS
31
32
  avc1Profile.pps.pps,
32
- ]);
33
+ // if AVCProfileIndication != 66 && AVCProfileIndication != 77 && AVCProfileIndication != 88
34
+ [66, 77, 88].some((b) => avc1Profile.sps.spsData.profile === b)
35
+ ? null
36
+ : /**
37
+ * reserved 63 (0x3F)
38
+ chroma_format 1, '4:2:0'
39
+ reserved 31 (0x1F)
40
+ bit_depth_luma_minus8 0
41
+ reserved 31 (0x1F)
42
+ bit_depth_chroma_minus8 0
43
+ numOfSequenceParameterSetExt 0
44
+ */
45
+ new Uint8Array([0xfd, 0xf8, 0xf8, 0]),
46
+ ].filter(truthy_1.truthy));
33
47
  };
34
48
  exports.createSpsPpsData = createSpsPpsData;
@@ -3,11 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getVideoColorFromSps = exports.getSampleAspectRatioFromSps = exports.getDimensionsFromSps = void 0;
4
4
  const color_1 = require("./color");
5
5
  const getDimensionsFromSps = (sps) => {
6
+ var _a, _b, _c, _d;
6
7
  const height = sps.pic_height_in_map_units_minus1;
7
8
  const width = sps.pic_width_in_mbs_minus1;
9
+ // https://stackoverflow.com/questions/12018535/get-the-width-height-of-the-video-from-h-264-nalu
8
10
  return {
9
- height: (height + 1) * 16,
10
- width: (width + 1) * 16,
11
+ height: (height + 1) * 16 -
12
+ ((_a = sps.frame_crop_bottom_offset) !== null && _a !== void 0 ? _a : 0) * 2 -
13
+ ((_b = sps.frame_crop_top_offset) !== null && _b !== void 0 ? _b : 0) * 2,
14
+ width: (width + 1) * 16 -
15
+ ((_c = sps.frame_crop_right_offset) !== null && _c !== void 0 ? _c : 0) * 2 -
16
+ ((_d = sps.frame_crop_left_offset) !== null && _d !== void 0 ? _d : 0) * 2,
11
17
  };
12
18
  };
13
19
  exports.getDimensionsFromSps = getDimensionsFromSps;
@@ -79,7 +79,7 @@ const readSps = (iterator) => {
79
79
  let frame_crop_bottom_offset = null;
80
80
  let vui_parameters = null;
81
81
  // Page 71
82
- if (!(profile === 100 ||
82
+ if (profile === 100 ||
83
83
  profile === 110 ||
84
84
  profile === 122 ||
85
85
  profile === 244 ||
@@ -91,29 +91,28 @@ const readSps = (iterator) => {
91
91
  profile === 138 ||
92
92
  profile === 139 ||
93
93
  profile === 134 ||
94
- profile === 135)) {
95
- throw new Error('Invalid profile');
96
- }
97
- const chromaFormat = iterator.readExpGolomb();
98
- if (chromaFormat === 3) {
99
- separate_colour_plane_flag = iterator.getBits(1);
100
- }
101
- bit_depth_luma_minus8 = iterator.readExpGolomb();
102
- bit_depth_chroma_minus8 = iterator.readExpGolomb();
103
- qpprime_y_zero_transform_bypass_flag = iterator.getBits(1);
104
- const seq_scaling_matrix_present_flag = iterator.getBits(1);
105
- const seq_scaling_list_present_flag = [];
106
- if (seq_scaling_matrix_present_flag) {
107
- for (let i = 0; i < (chromaFormat !== 3 ? 8 : 12); i++) {
108
- seq_scaling_list_present_flag[i] = iterator.getBits(1);
109
- if (seq_scaling_list_present_flag[i]) {
110
- if (i < 6) {
111
- // scaling_list not implemented
112
- throw new Error('Not implemented');
113
- }
114
- else {
115
- // scaling_list not implemented
116
- throw new Error('Not implemented');
94
+ profile === 135) {
95
+ const chromaFormat = iterator.readExpGolomb();
96
+ if (chromaFormat === 3) {
97
+ separate_colour_plane_flag = iterator.getBits(1);
98
+ }
99
+ bit_depth_luma_minus8 = iterator.readExpGolomb();
100
+ bit_depth_chroma_minus8 = iterator.readExpGolomb();
101
+ qpprime_y_zero_transform_bypass_flag = iterator.getBits(1);
102
+ const seq_scaling_matrix_present_flag = iterator.getBits(1);
103
+ const seq_scaling_list_present_flag = [];
104
+ if (seq_scaling_matrix_present_flag) {
105
+ for (let i = 0; i < (chromaFormat !== 3 ? 8 : 12); i++) {
106
+ seq_scaling_list_present_flag[i] = iterator.getBits(1);
107
+ if (seq_scaling_list_present_flag[i]) {
108
+ if (i < 6) {
109
+ // scaling_list not implemented
110
+ throw new Error('Not implemented');
111
+ }
112
+ else {
113
+ // scaling_list not implemented
114
+ throw new Error('Not implemented');
115
+ }
117
116
  }
118
117
  }
119
118
  }
@@ -1,2 +1,2 @@
1
1
  import type { BufferIterator } from '../../buffer-iterator';
2
- export declare const getChannelCount: (iterator: BufferIterator) => 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
2
+ export declare const getChannelCount: (iterator: BufferIterator) => 2 | 1 | 8 | 7 | 3 | 6 | 5 | 4;
@@ -0,0 +1,14 @@
1
+ import type { M3uState } from '../../state/m3u-state';
2
+ import type { ParserState } from '../../state/parser-state';
3
+ import type { StreamSelectionFn } from './select-stream';
4
+ import type { M3uStructure } from './types';
5
+ export declare const afterManifestFetch: ({ structure, m3uState, src, streamSelectionFn, }: {
6
+ structure: M3uStructure;
7
+ m3uState: M3uState;
8
+ src: string | null;
9
+ streamSelectionFn: StreamSelectionFn;
10
+ }) => Promise<void>;
11
+ export declare const runOverM3u: ({ state, structure, }: {
12
+ state: ParserState;
13
+ structure: M3uStructure;
14
+ }) => Promise<void>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runOverM3u = exports.afterManifestFetch = void 0;
4
+ const register_track_1 = require("../../register-track");
5
+ const fetch_m3u8_stream_1 = require("./fetch-m3u8-stream");
6
+ const get_streams_1 = require("./get-streams");
7
+ const return_packets_1 = require("./return-packets");
8
+ const select_stream_1 = require("./select-stream");
9
+ const afterManifestFetch = async ({ structure, m3uState, src, streamSelectionFn, }) => {
10
+ const streams = (0, get_streams_1.getM3uStreams)(structure, src);
11
+ if (streams === null) {
12
+ throw new Error('No streams found');
13
+ }
14
+ const selectedStream = await (0, select_stream_1.selectStream)({ streams, fn: streamSelectionFn });
15
+ m3uState.setSelectedStream(selectedStream);
16
+ if (!selectedStream.resolution) {
17
+ throw new Error('Stream does not have a resolution');
18
+ }
19
+ const boxes = await (0, fetch_m3u8_stream_1.fetchM3u8Stream)(selectedStream);
20
+ structure.boxes.push({ type: 'm3u-playlist', boxes });
21
+ m3uState.setReadyToIterateOverM3u();
22
+ };
23
+ exports.afterManifestFetch = afterManifestFetch;
24
+ const runOverM3u = async ({ state, structure, }) => {
25
+ const selectedStream = state.m3u.getSelectedStream();
26
+ if (!selectedStream) {
27
+ throw new Error('No stream selected');
28
+ }
29
+ await (0, return_packets_1.iteratorOverTsFiles)({
30
+ playlistUrl: selectedStream.url,
31
+ structure,
32
+ logLevel: state.logLevel,
33
+ onDoneWithTracks() {
34
+ state.callbacks.tracks.setIsDone(state.logLevel);
35
+ },
36
+ onAudioTrack: (track) => {
37
+ return (0, register_track_1.registerAudioTrack)({
38
+ container: 'm3u8',
39
+ state,
40
+ track,
41
+ });
42
+ },
43
+ onVideoTrack: (track) => {
44
+ return (0, register_track_1.registerVideoTrack)({
45
+ container: 'm3u8',
46
+ state,
47
+ track,
48
+ });
49
+ },
50
+ m3uState: state.m3u,
51
+ });
52
+ };
53
+ exports.runOverM3u = runOverM3u;
@@ -0,0 +1,3 @@
1
+ import type { M3uStream } from './get-streams';
2
+ import type { M3uBox } from './types';
3
+ export declare const fetchM3u8Stream: (stream: M3uStream) => Promise<M3uBox[]>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchM3u8Stream = void 0;
4
+ const parse_m3u8_text_1 = require("./parse-m3u8-text");
5
+ const fetchM3u8Stream = async (stream) => {
6
+ const res = await fetch(stream.url);
7
+ const text = await res.text();
8
+ const lines = text.split('\n');
9
+ const boxes = [];
10
+ for (const line of lines) {
11
+ (0, parse_m3u8_text_1.parseM3u8Text)(line, boxes);
12
+ }
13
+ return boxes;
14
+ };
15
+ exports.fetchM3u8Stream = fetchM3u8Stream;
@@ -0,0 +1,6 @@
1
+ import type { M3uPlaylist } from './types';
2
+ export type M3uChunk = {
3
+ duration: number;
4
+ url: string;
5
+ };
6
+ export declare const getChunks: (playlist: M3uPlaylist) => M3uChunk[];
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getChunks = void 0;
4
+ const getChunks = (playlist) => {
5
+ const chunks = [];
6
+ for (let i = 0; i < playlist.boxes.length; i++) {
7
+ const box = playlist.boxes[i];
8
+ if (box.type === 'm3u-extinf') {
9
+ const nextBox = playlist.boxes[i + 1];
10
+ i++;
11
+ if (nextBox.type !== 'm3u-text-value') {
12
+ throw new Error('Expected m3u-text-value');
13
+ }
14
+ chunks.push({ duration: box.value, url: nextBox.value });
15
+ }
16
+ continue;
17
+ }
18
+ return chunks;
19
+ };
20
+ exports.getChunks = getChunks;
@@ -0,0 +1,2 @@
1
+ import type { M3uStructure } from './types';
2
+ export declare const getDurationFromM3u: (structure: M3uStructure) => number | null;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDurationFromM3u = void 0;
4
+ const get_playlist_1 = require("./get-playlist");
5
+ const getDurationFromM3u = (structure) => {
6
+ const playlist = (0, get_playlist_1.getPlaylist)(structure);
7
+ return (0, get_playlist_1.getDurationFromPlaylist)(playlist);
8
+ };
9
+ exports.getDurationFromM3u = getDurationFromM3u;
@@ -0,0 +1,3 @@
1
+ import type { M3uPlaylist, M3uStructure } from './types';
2
+ export declare const getPlaylist: (structure: M3uStructure) => M3uPlaylist;
3
+ export declare const getDurationFromPlaylist: (playlist: M3uPlaylist) => number;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDurationFromPlaylist = exports.getPlaylist = void 0;
4
+ const getPlaylist = (structure) => {
5
+ const playlists = structure.boxes.filter((box) => box.type === 'm3u-playlist');
6
+ if (playlists.length !== 1) {
7
+ throw new Error('Expected one playlist');
8
+ }
9
+ return playlists[0];
10
+ };
11
+ exports.getPlaylist = getPlaylist;
12
+ const getDurationFromPlaylist = (playlist) => {
13
+ const duration = playlist.boxes.filter((box) => box.type === 'm3u-extinf');
14
+ if (duration.length === 0) {
15
+ throw new Error('Expected duration in m3u playlist');
16
+ }
17
+ return duration.reduce((acc, d) => acc + d.value, 0);
18
+ };
19
+ exports.getDurationFromPlaylist = getDurationFromPlaylist;
@@ -0,0 +1,13 @@
1
+ import type { Dimensions } from '../../get-dimensions';
2
+ import type { Structure } from '../../parse-result';
3
+ import type { ParserState } from '../../state/parser-state';
4
+ export type M3uStream = {
5
+ url: string;
6
+ bandwidth: number | null;
7
+ averageBandwidth: number | null;
8
+ resolution: Dimensions | null;
9
+ codecs: string[] | null;
10
+ id: number;
11
+ };
12
+ export declare const getM3uStreams: (structure: Structure | null, originalSrc: string | null) => M3uStream[] | null;
13
+ export declare const m3uHasStreams: (state: ParserState) => boolean;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.m3uHasStreams = exports.getM3uStreams = void 0;
4
+ const getM3uStreams = (structure, originalSrc) => {
5
+ if (structure === null || structure.type !== 'm3u') {
6
+ return null;
7
+ }
8
+ const boxes = [];
9
+ for (let i = 0; i < structure.boxes.length; i++) {
10
+ const str = structure.boxes[i];
11
+ if (str.type === 'm3u-stream-info') {
12
+ const next = structure.boxes[i + 1];
13
+ if (next.type !== 'm3u-text-value') {
14
+ throw new Error('Expected m3u-text-value');
15
+ }
16
+ boxes.push({
17
+ url: originalSrc && originalSrc.startsWith('http')
18
+ ? new URL(next.value, originalSrc).href
19
+ : next.value,
20
+ averageBandwidth: str.averageBandwidth,
21
+ bandwidth: str.bandwidth,
22
+ codecs: str.codecs,
23
+ resolution: str.resolution,
24
+ id: i,
25
+ });
26
+ }
27
+ }
28
+ return boxes;
29
+ };
30
+ exports.getM3uStreams = getM3uStreams;
31
+ const m3uHasStreams = (state) => {
32
+ const structure = state.getStructureOrNull();
33
+ if (!structure) {
34
+ return false;
35
+ }
36
+ if (structure.type !== 'm3u') {
37
+ return true;
38
+ }
39
+ return state.m3u.hasFinishedManifest();
40
+ };
41
+ exports.m3uHasStreams = m3uHasStreams;
@@ -0,0 +1,2 @@
1
+ import type { M3uBox } from './types';
2
+ export declare const parseM3uDirective: (str: string) => M3uBox;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseM3uDirective = void 0;
4
+ const parse_stream_inf_1 = require("./parse-stream-inf");
5
+ const parseM3uDirective = (str) => {
6
+ const firstColon = str.indexOf(':');
7
+ const directive = firstColon === -1 ? str : str.slice(0, firstColon);
8
+ const value = firstColon === -1 ? null : str.slice(firstColon + 1);
9
+ if (directive === '#EXT-X-VERSION') {
10
+ if (!value) {
11
+ throw new Error('EXT-X-VERSION directive must have a value');
12
+ }
13
+ return {
14
+ type: 'm3u-version',
15
+ version: value,
16
+ };
17
+ }
18
+ if (directive === '#EXT-X-INDEPENDENT-SEGMENTS') {
19
+ return {
20
+ type: 'm3u-independent-segments',
21
+ };
22
+ }
23
+ if (directive === '#EXT-X-TARGETDURATION') {
24
+ if (!value) {
25
+ throw new Error('EXT-X-TARGETDURATION directive must have a value');
26
+ }
27
+ return {
28
+ type: 'm3u-target-duration',
29
+ duration: parseFloat(value),
30
+ };
31
+ }
32
+ if (directive === '#EXTINF') {
33
+ if (!value) {
34
+ throw new Error('EXTINF has no value');
35
+ }
36
+ return {
37
+ type: 'm3u-extinf',
38
+ value: parseFloat(value),
39
+ };
40
+ }
41
+ if (directive === '#EXT-X-ENDLIST') {
42
+ return {
43
+ type: 'm3u-endlist',
44
+ };
45
+ }
46
+ if (directive === '#EXT-X-PLAYLIST-TYPE') {
47
+ if (!value) {
48
+ throw new Error('#EXT-X-PLAYLIST-TYPE. directive must have a value');
49
+ }
50
+ return {
51
+ type: 'm3u-playlist-type',
52
+ playlistType: value,
53
+ };
54
+ }
55
+ if (directive === '#EXT-X-STREAM-INF') {
56
+ if (!value) {
57
+ throw new Error('EXT-X-STREAM-INF directive must have a value');
58
+ }
59
+ const res = (0, parse_stream_inf_1.parseStreamInf)(value);
60
+ return res;
61
+ }
62
+ throw new Error(`Unknown directive ${directive}. Value: ${value}`);
63
+ };
64
+ exports.parseM3uDirective = parseM3uDirective;
@@ -0,0 +1,8 @@
1
+ import type { BufferIterator } from '../../buffer-iterator';
2
+ import type { ParseResult } from '../../parse-result';
3
+ import type { M3uStructure } from './types';
4
+ export declare const parseM3uManifest: ({ iterator, structure, contentLength, }: {
5
+ iterator: BufferIterator;
6
+ structure: M3uStructure;
7
+ contentLength: number;
8
+ }) => Promise<ParseResult>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseM3uManifest = void 0;
4
+ const parse_m3u8_text_1 = require("./parse-m3u8-text");
5
+ const parseM3uManifest = ({ iterator, structure, contentLength, }) => {
6
+ const start = iterator.startCheckpoint();
7
+ const line = iterator.readUntilLineEnd();
8
+ if (iterator.counter.getOffset() > contentLength) {
9
+ throw new Error('Unexpected end of file');
10
+ }
11
+ if (line === null) {
12
+ start.returnToCheckpoint();
13
+ return Promise.resolve(null);
14
+ }
15
+ (0, parse_m3u8_text_1.parseM3u8Text)(line, structure.boxes);
16
+ return Promise.resolve(null);
17
+ };
18
+ exports.parseM3uManifest = parseM3uManifest;
@@ -0,0 +1,4 @@
1
+ import type { ParserState } from '../../state/parser-state';
2
+ export declare const parseM3u: ({ state }: {
3
+ state: ParserState;
4
+ }) => Promise<any>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseM3u = void 0;
4
+ const after_manifest_fetch_1 = require("./after-manifest-fetch");
5
+ const parse_m3u_manifest_1 = require("./parse-m3u-manifest");
6
+ const parseM3u = async ({ state }) => {
7
+ const structure = state.getM3uStructure();
8
+ if (state.m3u.isReadyToIterateOverM3u()) {
9
+ await (0, after_manifest_fetch_1.runOverM3u)({
10
+ state,
11
+ structure,
12
+ });
13
+ return null;
14
+ }
15
+ if (state.m3u.hasFinishedManifest()) {
16
+ await (0, after_manifest_fetch_1.afterManifestFetch)({
17
+ structure,
18
+ m3uState: state.m3u,
19
+ src: typeof state.src === 'string' ? state.src : null,
20
+ streamSelectionFn: state.streamSelectionFn,
21
+ });
22
+ return null;
23
+ }
24
+ const box = await (0, parse_m3u_manifest_1.parseM3uManifest)({
25
+ iterator: state.iterator,
26
+ structure,
27
+ contentLength: state.contentLength,
28
+ });
29
+ const isDoneNow = state.iterator.counter.getOffset() === state.contentLength;
30
+ if (isDoneNow) {
31
+ state.m3u.setHasFinishedManifest();
32
+ }
33
+ return box;
34
+ };
35
+ exports.parseM3u = parseM3u;
@@ -0,0 +1,2 @@
1
+ import type { M3uBox } from './types';
2
+ export declare const parseM3u8Text: (line: string, boxes: M3uBox[]) => void;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseM3u8Text = void 0;
4
+ const parse_directive_1 = require("./parse-directive");
5
+ const parseM3u8Text = (line, boxes) => {
6
+ if (line === '#EXTM3U') {
7
+ boxes.push({
8
+ type: 'm3u-header',
9
+ });
10
+ return;
11
+ }
12
+ if (line.startsWith('#')) {
13
+ boxes.push((0, parse_directive_1.parseM3uDirective)(line));
14
+ return;
15
+ }
16
+ if (line.trim()) {
17
+ boxes.push({
18
+ type: 'm3u-text-value',
19
+ value: line,
20
+ });
21
+ }
22
+ };
23
+ exports.parseM3u8Text = parseM3u8Text;
@@ -0,0 +1,3 @@
1
+ import type { M3uStreamInfo } from './types';
2
+ export declare function splitRespectingQuotes(input: string): string[];
3
+ export declare const parseStreamInf: (str: string) => M3uStreamInfo;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseStreamInf = void 0;
4
+ exports.splitRespectingQuotes = splitRespectingQuotes;
5
+ function splitRespectingQuotes(input) {
6
+ const result = [];
7
+ let currentPart = '';
8
+ let insideQuote = false;
9
+ for (let i = 0; i < input.length; i++) {
10
+ const char = input[i];
11
+ // Toggle flag when encountering a quote character.
12
+ if (char === '"') {
13
+ insideQuote = !insideQuote;
14
+ currentPart += char;
15
+ }
16
+ // If we encounter a comma and we are NOT inside a quoted substring
17
+ else if (char === ',' && !insideQuote) {
18
+ result.push(currentPart);
19
+ currentPart = '';
20
+ }
21
+ else {
22
+ currentPart += char;
23
+ }
24
+ }
25
+ // Push the last token, if any.
26
+ if (currentPart) {
27
+ result.push(currentPart);
28
+ }
29
+ return result;
30
+ }
31
+ const parseStreamInf = (str) => {
32
+ const quotes = splitRespectingQuotes(str);
33
+ const map = {};
34
+ for (const quote of quotes) {
35
+ const firstColon = quote.indexOf('=');
36
+ const key = firstColon === -1 ? quote : quote.slice(0, firstColon);
37
+ const value = firstColon === -1 ? null : quote.slice(firstColon + 1);
38
+ if (value === null) {
39
+ throw new Error('Value is null');
40
+ }
41
+ const actualValue = (value === null || value === void 0 ? void 0 : value.startsWith('"')) && (value === null || value === void 0 ? void 0 : value.endsWith('"'))
42
+ ? value.slice(1, -1)
43
+ : value;
44
+ map[key] = actualValue;
45
+ }
46
+ return {
47
+ type: 'm3u-stream-info',
48
+ averageBandwidth: map['AVERAGE-BANDWIDTH']
49
+ ? parseInt(map['AVERAGE-BANDWIDTH'], 10)
50
+ : null,
51
+ bandwidth: map.BANDWIDTH ? parseInt(map.BANDWIDTH, 10) : null,
52
+ codecs: map.CODECS ? map.CODECS.split(',') : null,
53
+ resolution: map.RESOLUTION
54
+ ? {
55
+ width: parseInt(map.RESOLUTION.split('x')[0], 10),
56
+ height: parseInt(map.RESOLUTION.split('x')[1], 10),
57
+ }
58
+ : null,
59
+ };
60
+ };
61
+ exports.parseStreamInf = parseStreamInf;
@@ -0,0 +1,14 @@
1
+ import type { AudioTrack, VideoTrack } from '../../get-tracks';
2
+ import type { LogLevel } from '../../log';
3
+ import type { M3uState } from '../../state/m3u-state';
4
+ import type { OnAudioSample, OnVideoSample } from '../../webcodec-sample-types';
5
+ import type { M3uStructure } from './types';
6
+ export declare const iteratorOverTsFiles: ({ structure, onVideoTrack, m3uState, onAudioTrack, onDoneWithTracks, playlistUrl, logLevel, }: {
7
+ structure: M3uStructure;
8
+ onVideoTrack: (track: VideoTrack) => Promise<OnVideoSample | null>;
9
+ onAudioTrack: (track: AudioTrack) => Promise<OnAudioSample | null>;
10
+ onDoneWithTracks: () => void;
11
+ m3uState: M3uState;
12
+ playlistUrl: string;
13
+ logLevel: LogLevel;
14
+ }) => Promise<void>;