@remotion/media-parser 4.0.265 → 4.0.267
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buffer-iterator.d.ts +1 -0
- package/dist/buffer-iterator.js +17 -0
- package/dist/containers/aac/parse-aac.js +1 -1
- package/dist/containers/avc/create-sps-pps-data.js +15 -1
- package/dist/containers/avc/interpret-sps.js +8 -2
- package/dist/containers/avc/parse-avc.js +23 -24
- package/dist/containers/flac/parse-streaminfo.js +1 -1
- package/dist/containers/iso-base-media/get-moov-atom.js +3 -2
- package/dist/containers/iso-base-media/process-box.js +9 -2
- package/dist/containers/iso-base-media/trun.js +1 -1
- package/dist/containers/m3u/after-manifest-fetch.d.ts +14 -0
- package/dist/containers/m3u/after-manifest-fetch.js +67 -0
- package/dist/containers/m3u/fetch-m3u8-stream.d.ts +3 -0
- package/dist/containers/m3u/fetch-m3u8-stream.js +18 -0
- package/dist/containers/m3u/get-chunks.d.ts +6 -0
- package/dist/containers/m3u/get-chunks.js +20 -0
- package/dist/containers/m3u/get-duration-from-m3u.d.ts +2 -0
- package/dist/containers/m3u/get-duration-from-m3u.js +9 -0
- package/dist/containers/m3u/get-playlist.d.ts +3 -0
- package/dist/containers/m3u/get-playlist.js +27 -0
- package/dist/containers/m3u/get-streams.d.ts +24 -0
- package/dist/containers/m3u/get-streams.js +80 -0
- package/dist/containers/m3u/parse-directive.d.ts +2 -0
- package/dist/containers/m3u/parse-directive.js +72 -0
- package/dist/containers/m3u/parse-m3u-manifest.d.ts +8 -0
- package/dist/containers/m3u/parse-m3u-manifest.js +18 -0
- package/dist/containers/m3u/parse-m3u-media-directive.d.ts +2 -0
- package/dist/containers/m3u/parse-m3u-media-directive.js +31 -0
- package/dist/containers/m3u/parse-m3u.d.ts +4 -0
- package/dist/containers/m3u/parse-m3u.js +35 -0
- package/dist/containers/m3u/parse-m3u8-text.d.ts +2 -0
- package/dist/containers/m3u/parse-m3u8-text.js +23 -0
- package/dist/containers/m3u/parse-stream-inf.d.ts +3 -0
- package/dist/containers/m3u/parse-stream-inf.js +62 -0
- package/dist/containers/m3u/return-packets.d.ts +16 -0
- package/dist/containers/m3u/return-packets.js +71 -0
- package/dist/containers/m3u/select-stream.d.ts +10 -0
- package/dist/containers/m3u/select-stream.js +19 -0
- package/dist/containers/m3u/types.d.ts +62 -0
- package/dist/containers/m3u/types.js +2 -0
- package/dist/containers/mp3/parse-mpeg-header.js +1 -1
- package/dist/containers/riff/expect-riff-box.js +1 -1
- package/dist/containers/transport-stream/boxes.d.ts +4 -1
- package/dist/containers/transport-stream/find-separator.d.ts +1 -2
- package/dist/containers/transport-stream/find-separator.js +7 -13
- package/dist/containers/transport-stream/handle-aac-packet.js +1 -1
- package/dist/containers/transport-stream/handle-avc-packet.js +1 -1
- package/dist/containers/transport-stream/parse-packet.js +7 -1
- package/dist/containers/transport-stream/parse-pat.d.ts +2 -1
- package/dist/containers/transport-stream/parse-pat.js +16 -1
- package/dist/containers/transport-stream/parse-stream-packet.js +86 -74
- package/dist/containers/wav/parse-fmt.js +1 -1
- package/dist/containers/webm/parse-ebml.js +9 -2
- package/dist/download-and-parse-media.js +32 -29
- package/dist/emit-available-info.js +13 -1
- package/dist/emitter.d.ts +4 -0
- package/dist/emitter.js +4 -0
- package/dist/esm/fetch.mjs +148 -0
- package/dist/esm/index.mjs +1321 -528
- package/dist/esm/node-writer.mjs +113 -0
- package/dist/esm/node.mjs +37 -106
- package/dist/esm/{from-web-file.mjs → web-file.mjs} +2 -7
- package/dist/fetch.d.ts +1 -0
- package/dist/fetch.js +17 -0
- package/dist/file-types/detect-file-type.d.ts +5 -1
- package/dist/file-types/detect-file-type.js +5 -1
- package/dist/file-types/index.js +3 -0
- package/dist/forward-controller.d.ts +7 -0
- package/dist/forward-controller.js +25 -0
- package/dist/get-container.js +3 -0
- package/dist/get-duration.js +35 -2
- package/dist/get-fields-from-callbacks.js +1 -0
- package/dist/get-fps.js +7 -0
- package/dist/get-tracks.d.ts +2 -0
- package/dist/get-tracks.js +29 -4
- package/dist/has-all-info.js +4 -0
- package/dist/index.d.ts +46 -9
- package/dist/index.js +3 -1
- package/dist/init-video.js +8 -0
- package/dist/internal-parse-media.js +11 -4
- package/dist/is-audio-structure.js +3 -0
- package/dist/make-hvc1-codec-strings.js +3 -3
- package/dist/media-parser-controller.js +3 -1
- package/dist/metadata/get-metadata.js +26 -3
- package/dist/node-writer.d.ts +1 -0
- package/dist/node-writer.js +17 -0
- package/dist/node.d.ts +1 -0
- package/dist/node.js +17 -0
- package/dist/options.d.ts +9 -1
- package/dist/parse-media.js +11 -8
- package/dist/parse-result.d.ts +2 -1
- package/dist/readers/fetch/get-body-and-reader.d.ts +8 -0
- package/dist/readers/fetch/get-body-and-reader.js +42 -0
- package/dist/readers/fetch/resolve-url.d.ts +1 -0
- package/dist/readers/fetch/resolve-url.js +15 -0
- package/dist/readers/from-fetch.js +19 -40
- package/dist/readers/from-node.js +1 -7
- package/dist/readers/from-web-file.js +1 -6
- package/dist/readers/reader.d.ts +1 -2
- package/dist/register-track.d.ts +8 -3
- package/dist/register-track.js +30 -17
- package/dist/run-parse-iteration.js +6 -1
- package/dist/state/can-skip-tracks.js +2 -1
- package/dist/state/emitted-fields.js +1 -0
- package/dist/state/m3u-state.d.ts +29 -0
- package/dist/state/m3u-state.js +48 -0
- package/dist/state/need-samples-for-fields.js +1 -0
- package/dist/state/parser-state.d.ts +36 -1
- package/dist/state/parser-state.js +4 -1
- package/dist/state/structure.d.ts +1 -0
- package/dist/state/structure.js +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-file.d.ts +1 -0
- package/dist/web-file.js +17 -0
- package/package.json +32 -32
- package/dist/containers/mp3/get-tracks-from-mp3.d.ts +0 -4
- package/dist/containers/mp3/get-tracks-from-mp3.js +0 -25
- package/dist/esm/from-fetch.mjs +0 -237
- package/dist/esm/from-node.mjs +0 -50
|
@@ -6,34 +6,32 @@ const adts_header_1 = require("./adts-header");
|
|
|
6
6
|
const discard_rest_of_packet_1 = require("./discard-rest-of-packet");
|
|
7
7
|
const find_separator_1 = require("./find-separator");
|
|
8
8
|
const process_stream_buffers_1 = require("./process-stream-buffers");
|
|
9
|
-
const parseAdtsStream = async ({
|
|
9
|
+
const parseAdtsStream = async ({ transportStreamEntry, state, structure, offset, }) => {
|
|
10
10
|
var _a, _b;
|
|
11
11
|
const { streamBuffers, nextPesHeaderStore: nextPesHeader } = state.transportStream;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
buffer
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
: restOfPacket.length;
|
|
25
|
-
streamBuffer.buffer = (0, combine_uint8_arrays_1.combineUint8Arrays)([
|
|
26
|
-
streamBuffer.buffer,
|
|
27
|
-
restOfPacket.slice(0, bytesToTake),
|
|
28
|
-
]);
|
|
29
|
-
if (expectedLength === streamBuffer.buffer.byteLength) {
|
|
12
|
+
while (true) {
|
|
13
|
+
const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
|
|
14
|
+
if (!streamBuffer) {
|
|
15
|
+
throw new Error('Stream buffer not found');
|
|
16
|
+
}
|
|
17
|
+
const expectedLength = (_b = (_a = (0, adts_header_1.readAdtsHeader)(streamBuffer.buffer)) === null || _a === void 0 ? void 0 : _a.frameLength) !== null && _b !== void 0 ? _b : null;
|
|
18
|
+
if (expectedLength === null) {
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
if (expectedLength > streamBuffer.buffer.length) {
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
30
24
|
await (0, process_stream_buffers_1.processStreamBuffer)({
|
|
31
|
-
streamBuffer
|
|
25
|
+
streamBuffer: {
|
|
26
|
+
buffer: streamBuffer.buffer.slice(0, expectedLength),
|
|
27
|
+
offset,
|
|
28
|
+
pesHeader: streamBuffer.pesHeader,
|
|
29
|
+
},
|
|
32
30
|
programId: transportStreamEntry.pid,
|
|
33
31
|
state,
|
|
34
32
|
structure,
|
|
35
33
|
});
|
|
36
|
-
const rest =
|
|
34
|
+
const rest = streamBuffer.buffer.slice(expectedLength);
|
|
37
35
|
streamBuffers.set(transportStreamEntry.pid, {
|
|
38
36
|
buffer: rest,
|
|
39
37
|
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
@@ -41,71 +39,85 @@ const parseAdtsStream = async ({ restOfPacket, transportStreamEntry, state, stru
|
|
|
41
39
|
});
|
|
42
40
|
}
|
|
43
41
|
};
|
|
44
|
-
const parseAvcStream = async ({
|
|
45
|
-
const indexOfSeparator = (0, find_separator_1.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
const parseAvcStream = async ({ programId, state, structure, streamBuffer, }) => {
|
|
43
|
+
const indexOfSeparator = (0, find_separator_1.findNthSubarrayIndex)(streamBuffer.buffer, new Uint8Array([0, 0, 1, 9]), 2);
|
|
44
|
+
if (indexOfSeparator === -1 || indexOfSeparator === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const packet = streamBuffer.buffer.slice(0, indexOfSeparator);
|
|
48
|
+
const rest = streamBuffer.buffer.slice(indexOfSeparator);
|
|
49
|
+
await (0, process_stream_buffers_1.processStreamBuffer)({
|
|
50
|
+
state,
|
|
51
|
+
streamBuffer: {
|
|
52
|
+
offset: streamBuffer.offset,
|
|
53
|
+
pesHeader: streamBuffer.pesHeader,
|
|
54
|
+
// Replace the regular 0x00000001 with 0x00000002 to avoid confusion with other 0x00000001 (?)
|
|
55
|
+
buffer: packet,
|
|
56
|
+
},
|
|
57
|
+
programId,
|
|
58
|
+
structure,
|
|
59
|
+
});
|
|
60
|
+
return rest;
|
|
61
|
+
};
|
|
62
|
+
const parseStream = async ({ transportStreamEntry, state, programId, structure, }) => {
|
|
63
|
+
const { iterator } = state;
|
|
64
|
+
let restOfPacket = (0, discard_rest_of_packet_1.getRestOfPacket)(iterator);
|
|
65
|
+
const offset = iterator.counter.getOffset();
|
|
66
|
+
if (transportStreamEntry.streamType === 27) {
|
|
67
|
+
const { streamBuffers, nextPesHeaderStore: nextPesHeader } = state.transportStream;
|
|
68
|
+
while (true) {
|
|
69
|
+
if (!streamBuffers.has(transportStreamEntry.pid)) {
|
|
70
|
+
streamBuffers.set(programId, {
|
|
71
|
+
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
72
|
+
buffer: new Uint8Array([]),
|
|
73
|
+
offset,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
|
|
50
77
|
streamBuffer.buffer = (0, combine_uint8_arrays_1.combineUint8Arrays)([
|
|
51
78
|
streamBuffer.buffer,
|
|
52
79
|
restOfPacket,
|
|
53
80
|
]);
|
|
54
|
-
|
|
81
|
+
const rest = await parseAvcStream({
|
|
82
|
+
state,
|
|
83
|
+
programId,
|
|
84
|
+
structure,
|
|
85
|
+
streamBuffer: streamBuffers.get(transportStreamEntry.pid),
|
|
86
|
+
});
|
|
87
|
+
if (rest !== null) {
|
|
88
|
+
streamBuffers.delete(transportStreamEntry.pid);
|
|
89
|
+
if (rest.length === 0) {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
restOfPacket = rest;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
55
97
|
}
|
|
56
|
-
streamBuffers.set(programId, {
|
|
57
|
-
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
58
|
-
buffer: restOfPacket,
|
|
59
|
-
offset,
|
|
60
|
-
});
|
|
61
98
|
return;
|
|
62
99
|
}
|
|
63
|
-
if (streamBuffer) {
|
|
64
|
-
const packet = restOfPacket.slice(0, indexOfSeparator);
|
|
65
|
-
streamBuffer.buffer = (0, combine_uint8_arrays_1.combineUint8Arrays)([streamBuffer.buffer, packet]);
|
|
66
|
-
await (0, process_stream_buffers_1.processStreamBuffer)({
|
|
67
|
-
state,
|
|
68
|
-
streamBuffer,
|
|
69
|
-
programId,
|
|
70
|
-
structure,
|
|
71
|
-
});
|
|
72
|
-
const rest = restOfPacket.slice(indexOfSeparator);
|
|
73
|
-
streamBuffers.set(programId, {
|
|
74
|
-
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
75
|
-
buffer: rest,
|
|
76
|
-
offset,
|
|
77
|
-
});
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (indexOfSeparator !== 0) {
|
|
81
|
-
throw new Error('No stream buffer found but new separator is not at the beginning');
|
|
82
|
-
}
|
|
83
|
-
streamBuffers.set(programId, {
|
|
84
|
-
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
85
|
-
buffer: restOfPacket.slice(indexOfSeparator),
|
|
86
|
-
offset,
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
const parseStream = ({ transportStreamEntry, state, programId, structure, }) => {
|
|
90
|
-
const { iterator } = state;
|
|
91
|
-
const restOfPacket = (0, discard_rest_of_packet_1.getRestOfPacket)(iterator);
|
|
92
|
-
if (transportStreamEntry.streamType === 27) {
|
|
93
|
-
return parseAvcStream({
|
|
94
|
-
restOfPacket,
|
|
95
|
-
transportStreamEntry,
|
|
96
|
-
state,
|
|
97
|
-
programId,
|
|
98
|
-
structure,
|
|
99
|
-
offset: iterator.counter.getOffset(),
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
100
|
if (transportStreamEntry.streamType === 15) {
|
|
101
|
+
const { streamBuffers, nextPesHeaderStore: nextPesHeader } = state.transportStream;
|
|
102
|
+
const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
|
|
103
|
+
if (!streamBuffer) {
|
|
104
|
+
streamBuffers.set(transportStreamEntry.pid, {
|
|
105
|
+
buffer: restOfPacket,
|
|
106
|
+
pesHeader: nextPesHeader.getNextPesHeader(),
|
|
107
|
+
offset,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
streamBuffer.buffer = (0, combine_uint8_arrays_1.combineUint8Arrays)([
|
|
112
|
+
streamBuffer.buffer,
|
|
113
|
+
restOfPacket,
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
103
116
|
return parseAdtsStream({
|
|
104
|
-
restOfPacket,
|
|
105
117
|
transportStreamEntry,
|
|
106
118
|
state,
|
|
107
119
|
structure,
|
|
108
|
-
offset
|
|
120
|
+
offset,
|
|
109
121
|
});
|
|
110
122
|
}
|
|
111
123
|
throw new Error(`Unsupported stream type ${transportStreamEntry.streamType}`);
|
|
@@ -119,8 +119,15 @@ const postprocessEbml = async ({ offset, ebml, state, }) => {
|
|
|
119
119
|
track: ebml,
|
|
120
120
|
timescale: state.webm.getTimescale(),
|
|
121
121
|
});
|
|
122
|
-
if (track) {
|
|
123
|
-
await (0, register_track_1.
|
|
122
|
+
if (track && track.type === 'audio') {
|
|
123
|
+
await (0, register_track_1.registerAudioTrack)({
|
|
124
|
+
state,
|
|
125
|
+
track,
|
|
126
|
+
container: 'webm',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (track && track.type === 'video') {
|
|
130
|
+
await (0, register_track_1.registerVideoTrack)({
|
|
124
131
|
state,
|
|
125
132
|
track,
|
|
126
133
|
container: 'webm',
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.downloadAndParseMedia = void 0;
|
|
4
|
+
const select_stream_1 = require("./containers/m3u/select-stream");
|
|
4
5
|
const internal_parse_media_1 = require("./internal-parse-media");
|
|
5
6
|
const log_1 = require("./log");
|
|
6
7
|
const from_fetch_1 = require("./readers/from-fetch");
|
|
7
8
|
const downloadAndParseMedia = async (options) => {
|
|
8
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
|
|
9
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10;
|
|
9
10
|
const logLevel = (_a = options.logLevel) !== null && _a !== void 0 ? _a : 'info';
|
|
10
11
|
const content = await options.writer.createContent({
|
|
11
12
|
filename: 'hmm',
|
|
@@ -20,38 +21,40 @@ const downloadAndParseMedia = async (options) => {
|
|
|
20
21
|
onAudioTrack: null,
|
|
21
22
|
onContainer: (_d = options.onContainer) !== null && _d !== void 0 ? _d : null,
|
|
22
23
|
onDimensions: (_e = options.onDimensions) !== null && _e !== void 0 ? _e : null,
|
|
24
|
+
selectM3uStream: (_f = options.selectM3uStream) !== null && _f !== void 0 ? _f : select_stream_1.defaultSelectM3uStreamFn,
|
|
23
25
|
onDiscardedData: async (data) => {
|
|
24
26
|
await content.write(data);
|
|
25
27
|
},
|
|
26
|
-
onDurationInSeconds: (
|
|
27
|
-
onFps: (
|
|
28
|
-
onImages: (
|
|
29
|
-
onInternalStats: (
|
|
30
|
-
onIsHdr: (
|
|
31
|
-
onKeyframes: (
|
|
32
|
-
onLocation: (
|
|
33
|
-
onMetadata: (
|
|
34
|
-
onMimeType: (
|
|
35
|
-
onName: (
|
|
36
|
-
onNumberOfAudioChannels: (
|
|
37
|
-
onParseProgress: (
|
|
38
|
-
onRotation: (
|
|
39
|
-
onSampleRate: (
|
|
40
|
-
onSize: (
|
|
41
|
-
onSlowAudioBitrate: (
|
|
42
|
-
onSlowDurationInSeconds: (
|
|
43
|
-
onSlowFps: (
|
|
44
|
-
onSlowKeyframes: (
|
|
45
|
-
onSlowNumberOfFrames: (
|
|
46
|
-
onSlowVideoBitrate: (
|
|
47
|
-
onStructure: (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
28
|
+
onDurationInSeconds: (_g = options.onDurationInSeconds) !== null && _g !== void 0 ? _g : null,
|
|
29
|
+
onFps: (_h = options.onFps) !== null && _h !== void 0 ? _h : null,
|
|
30
|
+
onImages: (_j = options.onImages) !== null && _j !== void 0 ? _j : null,
|
|
31
|
+
onInternalStats: (_k = options.onInternalStats) !== null && _k !== void 0 ? _k : null,
|
|
32
|
+
onIsHdr: (_l = options.onIsHdr) !== null && _l !== void 0 ? _l : null,
|
|
33
|
+
onKeyframes: (_m = options.onKeyframes) !== null && _m !== void 0 ? _m : null,
|
|
34
|
+
onLocation: (_o = options.onLocation) !== null && _o !== void 0 ? _o : null,
|
|
35
|
+
onMetadata: (_p = options.onMetadata) !== null && _p !== void 0 ? _p : null,
|
|
36
|
+
onMimeType: (_q = options.onMimeType) !== null && _q !== void 0 ? _q : null,
|
|
37
|
+
onName: (_r = options.onName) !== null && _r !== void 0 ? _r : null,
|
|
38
|
+
onNumberOfAudioChannels: (_s = options.onNumberOfAudioChannels) !== null && _s !== void 0 ? _s : null,
|
|
39
|
+
onParseProgress: (_t = options.onParseProgress) !== null && _t !== void 0 ? _t : null,
|
|
40
|
+
onRotation: (_u = options.onRotation) !== null && _u !== void 0 ? _u : null,
|
|
41
|
+
onSampleRate: (_v = options.onSampleRate) !== null && _v !== void 0 ? _v : null,
|
|
42
|
+
onSize: (_w = options.onSize) !== null && _w !== void 0 ? _w : null,
|
|
43
|
+
onSlowAudioBitrate: (_x = options.onSlowAudioBitrate) !== null && _x !== void 0 ? _x : null,
|
|
44
|
+
onSlowDurationInSeconds: (_y = options.onSlowDurationInSeconds) !== null && _y !== void 0 ? _y : null,
|
|
45
|
+
onSlowFps: (_z = options.onSlowFps) !== null && _z !== void 0 ? _z : null,
|
|
46
|
+
onSlowKeyframes: (_0 = options.onSlowKeyframes) !== null && _0 !== void 0 ? _0 : null,
|
|
47
|
+
onSlowNumberOfFrames: (_1 = options.onSlowNumberOfFrames) !== null && _1 !== void 0 ? _1 : null,
|
|
48
|
+
onSlowVideoBitrate: (_2 = options.onSlowVideoBitrate) !== null && _2 !== void 0 ? _2 : null,
|
|
49
|
+
onStructure: (_3 = options.onStructure) !== null && _3 !== void 0 ? _3 : null,
|
|
50
|
+
onM3uStreams: (_4 = options.onM3uStreams) !== null && _4 !== void 0 ? _4 : null,
|
|
51
|
+
onTracks: (_5 = options.onTracks) !== null && _5 !== void 0 ? _5 : null,
|
|
52
|
+
onUnrotatedDimensions: (_6 = options.onUnrotatedDimensions) !== null && _6 !== void 0 ? _6 : null,
|
|
53
|
+
onVideoCodec: (_7 = options.onVideoCodec) !== null && _7 !== void 0 ? _7 : null,
|
|
51
54
|
onVideoTrack: null,
|
|
52
|
-
progressIntervalInMs: (
|
|
53
|
-
reader: (
|
|
54
|
-
controller: (
|
|
55
|
+
progressIntervalInMs: (_8 = options.progressIntervalInMs) !== null && _8 !== void 0 ? _8 : null,
|
|
56
|
+
reader: (_9 = options.reader) !== null && _9 !== void 0 ? _9 : from_fetch_1.fetchReader,
|
|
57
|
+
controller: (_10 = options.controller) !== null && _10 !== void 0 ? _10 : undefined,
|
|
55
58
|
src: options.src,
|
|
56
59
|
onError: async (err) => {
|
|
57
60
|
var _a, _b;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.emitAvailableInfo = void 0;
|
|
4
|
+
const get_streams_1 = require("./containers/m3u/get-streams");
|
|
4
5
|
const get_audio_codec_1 = require("./get-audio-codec");
|
|
5
6
|
const get_container_1 = require("./get-container");
|
|
6
7
|
const get_dimensions_1 = require("./get-dimensions");
|
|
@@ -15,7 +16,7 @@ const get_tracks_1 = require("./get-tracks");
|
|
|
15
16
|
const get_video_codec_1 = require("./get-video-codec");
|
|
16
17
|
const get_metadata_1 = require("./metadata/get-metadata");
|
|
17
18
|
const emitAvailableInfo = async ({ hasInfo, callbacks, state, returnValue, name, mimeType, fieldsInReturnValue, }) => {
|
|
18
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
|
|
19
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
|
|
19
20
|
const keys = Object.keys(hasInfo);
|
|
20
21
|
const { emittedFields } = state;
|
|
21
22
|
for (const key of keys) {
|
|
@@ -339,6 +340,17 @@ const emitAvailableInfo = async ({ hasInfo, callbacks, state, returnValue, name,
|
|
|
339
340
|
}
|
|
340
341
|
continue;
|
|
341
342
|
}
|
|
343
|
+
if (key === 'm3uStreams') {
|
|
344
|
+
if (!emittedFields.m3uStreams && hasInfo.m3uStreams) {
|
|
345
|
+
const streams = (0, get_streams_1.getM3uStreams)(state.getStructureOrNull(), typeof state.src === 'string' ? state.src : null);
|
|
346
|
+
await ((_5 = callbacks.onM3uStreams) === null || _5 === void 0 ? void 0 : _5.call(callbacks, streams));
|
|
347
|
+
if (fieldsInReturnValue.m3uStreams) {
|
|
348
|
+
returnValue.m3uStreams = streams;
|
|
349
|
+
}
|
|
350
|
+
emittedFields.m3uStreams = true;
|
|
351
|
+
}
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
342
354
|
throw new Error(`Unhandled key: ${key}`);
|
|
343
355
|
}
|
|
344
356
|
};
|
package/dist/emitter.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
type MediaParserEventMap = {
|
|
2
2
|
pause: undefined;
|
|
3
3
|
resume: undefined;
|
|
4
|
+
abort: {
|
|
5
|
+
reason?: unknown;
|
|
6
|
+
};
|
|
4
7
|
};
|
|
5
8
|
export type MediaParserEventTypes = keyof MediaParserEventMap;
|
|
6
9
|
export type CallbackListener<T extends MediaParserEventTypes> = (data: {
|
|
@@ -16,5 +19,6 @@ export declare class MediaParserEmitter {
|
|
|
16
19
|
private dispatchEvent;
|
|
17
20
|
dispatchPause: () => void;
|
|
18
21
|
dispatchResume: () => void;
|
|
22
|
+
dispatchAbort: (reason?: unknown) => void;
|
|
19
23
|
}
|
|
20
24
|
export {};
|
package/dist/emitter.js
CHANGED
|
@@ -6,6 +6,7 @@ class MediaParserEmitter {
|
|
|
6
6
|
this.listeners = {
|
|
7
7
|
pause: [],
|
|
8
8
|
resume: [],
|
|
9
|
+
abort: [],
|
|
9
10
|
};
|
|
10
11
|
this.addEventListener = (name, callback) => {
|
|
11
12
|
this.listeners[name].push(callback);
|
|
@@ -19,6 +20,9 @@ class MediaParserEmitter {
|
|
|
19
20
|
this.dispatchResume = () => {
|
|
20
21
|
this.dispatchEvent('resume', undefined);
|
|
21
22
|
};
|
|
23
|
+
this.dispatchAbort = (reason) => {
|
|
24
|
+
this.dispatchEvent('abort', { reason });
|
|
25
|
+
};
|
|
22
26
|
}
|
|
23
27
|
dispatchEvent(dispatchName, context) {
|
|
24
28
|
this.listeners[dispatchName].forEach((callback) => {
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
class MediaParserAbortError extends Error {
|
|
3
|
+
constructor(message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "MediaParserAbortError";
|
|
6
|
+
this.cause = undefined;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/readers/fetch/get-body-and-reader.ts
|
|
11
|
+
var getLengthAndReader = async (endsWithM3u8, res, ownController) => {
|
|
12
|
+
if (endsWithM3u8) {
|
|
13
|
+
const text = await res.text();
|
|
14
|
+
const encoded = new TextEncoder().encode(text);
|
|
15
|
+
const stream = new ReadableStream({
|
|
16
|
+
start(controller) {
|
|
17
|
+
controller.enqueue(encoded);
|
|
18
|
+
controller.close();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
contentLength: encoded.byteLength,
|
|
23
|
+
reader: {
|
|
24
|
+
reader: stream.getReader(),
|
|
25
|
+
abort() {
|
|
26
|
+
ownController.abort();
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
needsContentRange: false
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const length = res.headers.get("content-length");
|
|
33
|
+
const contentLength = length === null ? null : parseInt(length, 10);
|
|
34
|
+
if (!res.body) {
|
|
35
|
+
throw new Error("No body");
|
|
36
|
+
}
|
|
37
|
+
const reader = res.body.getReader();
|
|
38
|
+
return {
|
|
39
|
+
reader: {
|
|
40
|
+
reader,
|
|
41
|
+
abort: () => {
|
|
42
|
+
ownController.abort();
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
contentLength,
|
|
46
|
+
needsContentRange: true
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/readers/fetch/resolve-url.ts
|
|
51
|
+
var resolveUrl = (src) => {
|
|
52
|
+
try {
|
|
53
|
+
const resolvedUrl = typeof window !== "undefined" && typeof window.location !== "undefined" ? new URL(src, window.location.origin) : new URL(src);
|
|
54
|
+
return resolvedUrl;
|
|
55
|
+
} catch {
|
|
56
|
+
return src;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/readers/from-fetch.ts
|
|
61
|
+
function parseContentRange(input) {
|
|
62
|
+
const matches = input.match(/^(\w+) ((\d+)-(\d+)|\*)\/(\d+|\*)$/);
|
|
63
|
+
if (!matches)
|
|
64
|
+
return null;
|
|
65
|
+
const [, unit, , start, end, size] = matches;
|
|
66
|
+
const range = {
|
|
67
|
+
unit,
|
|
68
|
+
start: start != null ? Number(start) : null,
|
|
69
|
+
end: end != null ? Number(end) : null,
|
|
70
|
+
size: size === "*" ? null : Number(size)
|
|
71
|
+
};
|
|
72
|
+
if (range.start === null && range.end === null && range.size === null) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return range;
|
|
76
|
+
}
|
|
77
|
+
var validateContentRangeAndDetectIfSupported = (actualRange, parsedContentRange, statusCode) => {
|
|
78
|
+
if (statusCode === 206) {
|
|
79
|
+
return { supportsContentRange: true };
|
|
80
|
+
}
|
|
81
|
+
if (typeof actualRange === "number" && parsedContentRange?.start !== actualRange) {
|
|
82
|
+
if (actualRange === 0) {
|
|
83
|
+
return { supportsContentRange: false };
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`Range header (${actualRange}) does not match content-range header (${parsedContentRange?.start})`);
|
|
86
|
+
}
|
|
87
|
+
if (actualRange !== null && typeof actualRange !== "number" && (parsedContentRange?.start !== actualRange[0] || parsedContentRange?.end !== actualRange[1])) {
|
|
88
|
+
throw new Error(`Range header (${actualRange}) does not match content-range header (${parsedContentRange?.start})`);
|
|
89
|
+
}
|
|
90
|
+
return { supportsContentRange: true };
|
|
91
|
+
};
|
|
92
|
+
var fetchReader = {
|
|
93
|
+
read: async ({ src, range, controller }) => {
|
|
94
|
+
if (typeof src !== "string") {
|
|
95
|
+
throw new Error("src must be a string when using `fetchReader`");
|
|
96
|
+
}
|
|
97
|
+
const resolvedUrl = resolveUrl(src);
|
|
98
|
+
const resolvedUrlString = resolvedUrl.toString();
|
|
99
|
+
if (!resolvedUrlString.startsWith("https://") && !resolvedUrlString.startsWith("blob:") && !resolvedUrlString.startsWith("http://")) {
|
|
100
|
+
return Promise.reject(new Error(`${resolvedUrlString} is not a URL - needs to start with http:// or https:// or blob:. If you want to read a local file, pass \`reader: nodeReader\` to parseMedia().`));
|
|
101
|
+
}
|
|
102
|
+
const ownController = new AbortController;
|
|
103
|
+
const cache = typeof navigator !== "undefined" && navigator.userAgent.includes("Cloudflare-Workers") ? undefined : "no-store";
|
|
104
|
+
const actualRange = range === null ? 0 : range;
|
|
105
|
+
const endsWithM3u8 = (typeof resolvedUrl === "string" ? resolvedUrl : resolvedUrl.pathname).endsWith(".m3u8");
|
|
106
|
+
const headers = actualRange === 0 && endsWithM3u8 ? {} : typeof actualRange === "number" ? {
|
|
107
|
+
Range: `bytes=${actualRange}-`
|
|
108
|
+
} : {
|
|
109
|
+
Range: `bytes=${`${actualRange[0]}-${actualRange[1]}`}`
|
|
110
|
+
};
|
|
111
|
+
const res = await fetch(resolvedUrl, {
|
|
112
|
+
headers,
|
|
113
|
+
signal: ownController.signal,
|
|
114
|
+
cache
|
|
115
|
+
});
|
|
116
|
+
const contentRange = res.headers.get("content-range");
|
|
117
|
+
const parsedContentRange = contentRange ? parseContentRange(contentRange) : null;
|
|
118
|
+
const { supportsContentRange } = validateContentRangeAndDetectIfSupported(actualRange, parsedContentRange, res.status);
|
|
119
|
+
controller._internals.signal.addEventListener("abort", () => {
|
|
120
|
+
ownController.abort(new MediaParserAbortError("Aborted by user"));
|
|
121
|
+
}, { once: true });
|
|
122
|
+
if (res.status.toString().startsWith("4") || res.status.toString().startsWith("5")) {
|
|
123
|
+
throw new Error(`Server returned status code ${res.status} for ${src} and range ${actualRange}`);
|
|
124
|
+
}
|
|
125
|
+
const contentDisposition = res.headers.get("content-disposition");
|
|
126
|
+
const name = contentDisposition?.match(/filename="([^"]+)"/)?.[1];
|
|
127
|
+
const fallbackName = src.split("/").pop();
|
|
128
|
+
const { contentLength, needsContentRange, reader } = await getLengthAndReader(endsWithM3u8, res, ownController);
|
|
129
|
+
if (controller) {
|
|
130
|
+
controller._internals.signal.addEventListener("abort", () => {
|
|
131
|
+
reader.reader.cancel().catch(() => {
|
|
132
|
+
});
|
|
133
|
+
}, { once: true });
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
reader,
|
|
137
|
+
contentLength,
|
|
138
|
+
contentType: res.headers.get("content-type"),
|
|
139
|
+
name: name ?? fallbackName,
|
|
140
|
+
supportsContentRange,
|
|
141
|
+
needsContentRange
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
export {
|
|
146
|
+
parseContentRange,
|
|
147
|
+
fetchReader
|
|
148
|
+
};
|