@remotion/media-parser 4.0.272 → 4.0.274
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/containers/flac/get-channel-count.d.ts +1 -1
- package/dist/containers/iso-base-media/get-video-codec-from-iso-track.d.ts +1 -1
- package/dist/containers/iso-base-media/make-track.js +1 -0
- package/dist/containers/m3u/iterate-over-segment-files.js +4 -1
- package/dist/containers/riff/get-tracks-from-avi.js +1 -0
- package/dist/containers/transport-stream/handle-avc-packet.js +1 -0
- package/dist/containers/webm/make-track.js +1 -0
- package/dist/esm/index.mjs +9 -351
- package/dist/esm/worker-server-entry.mjs +8 -1
- package/dist/esm/worker-web-entry.mjs +8 -1
- package/dist/esm/worker.mjs +20 -8
- package/dist/get-tracks.d.ts +1 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker.d.ts +3 -2
- package/dist/worker.js +2 -267
- package/package.json +13 -4
- package/dist/containers/m3u/m3u-child-stream.d.ts +0 -0
- package/dist/containers/m3u/m3u-child-stream.js +0 -1
- package/dist/containers/m3u/return-packets.d.ts +0 -17
- package/dist/containers/m3u/return-packets.js +0 -109
- package/dist/esm/fetch.mjs +0 -194
- package/dist/esm/web-file.mjs +0 -60
- package/dist/esm/worker-server.mjs +0 -12914
- package/dist/parse-media-on-browser-worker.d.ts +0 -2
- package/dist/parse-media-on-browser-worker.js +0 -4
- package/dist/parse-media-on-worker.d.ts +0 -2
- package/dist/parse-media-on-worker.js +0 -4
- package/dist/state/last-eventloop-break.d.ts +0 -4
- package/dist/state/last-eventloop-break.js +0 -14
- package/dist/web-file.d.ts +0 -1
- package/dist/web-file.js +0 -1
- package/dist/worker-bun-entry.d.ts +0 -1
- package/dist/worker-bun-entry.js +0 -5
- package/dist/worker-entry.d.ts +0 -1
- package/dist/worker-entry.js +0 -5
package/dist/worker.js
CHANGED
|
@@ -1,267 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
-
payload) => {
|
|
5
|
-
const { onAudioCodec, onContainer, onDimensions, onUnrotatedDimensions, onVideoCodec, onFps, onAudioTrack, onDurationInSeconds, onImages, onInternalStats, onIsHdr, onKeyframes, onLocation, onM3uStreams, onMetadata, onMimeType, onName, onNumberOfAudioChannels,
|
|
6
|
-
// TODO: Callback functions
|
|
7
|
-
onParseProgress, onRotation, onSampleRate, onSlowAudioBitrate, onSize, onSlowDurationInSeconds, onSlowFps, onSlowKeyframes, onSlowNumberOfFrames, onSlowVideoBitrate, onStructure, onTracks, onVideoTrack, selectM3uStream, selectM3uAssociatedPlaylists, ...others } = payload;
|
|
8
|
-
return {
|
|
9
|
-
type: 'request-worker',
|
|
10
|
-
payload: others,
|
|
11
|
-
postAudioCodec: Boolean(onAudioCodec),
|
|
12
|
-
postContainer: Boolean(onContainer),
|
|
13
|
-
postDimensions: Boolean(onDimensions),
|
|
14
|
-
postDurationInSeconds: Boolean(onDurationInSeconds),
|
|
15
|
-
postFps: Boolean(onFps),
|
|
16
|
-
postImages: Boolean(onImages),
|
|
17
|
-
postInternalStats: Boolean(onInternalStats),
|
|
18
|
-
postIsHdr: Boolean(onIsHdr),
|
|
19
|
-
postKeyframes: Boolean(onKeyframes),
|
|
20
|
-
postLocation: Boolean(onLocation),
|
|
21
|
-
postM3uStreams: Boolean(onM3uStreams),
|
|
22
|
-
postMetadata: Boolean(onMetadata),
|
|
23
|
-
postMimeType: Boolean(onMimeType),
|
|
24
|
-
postName: Boolean(onName),
|
|
25
|
-
postNumberOfAudioChannels: Boolean(onNumberOfAudioChannels),
|
|
26
|
-
postRotation: Boolean(onRotation),
|
|
27
|
-
postSampleRate: Boolean(onSampleRate),
|
|
28
|
-
postSlowAudioBitrate: Boolean(onSlowAudioBitrate),
|
|
29
|
-
postSlowDurationInSeconds: Boolean(onSlowDurationInSeconds),
|
|
30
|
-
postSlowFps: Boolean(onSlowFps),
|
|
31
|
-
postSlowKeyframes: Boolean(onSlowKeyframes),
|
|
32
|
-
postSlowNumberOfFrames: Boolean(onSlowNumberOfFrames),
|
|
33
|
-
postSlowVideoBitrate: Boolean(onSlowVideoBitrate),
|
|
34
|
-
postStructure: Boolean(onStructure),
|
|
35
|
-
postTracks: Boolean(onTracks),
|
|
36
|
-
postUnrotatedDimensions: Boolean(onUnrotatedDimensions),
|
|
37
|
-
postVideoCodec: Boolean(onVideoCodec),
|
|
38
|
-
postSize: Boolean(onSize),
|
|
39
|
-
postParseProgress: Boolean(onParseProgress),
|
|
40
|
-
postM3uStreamSelection: Boolean(selectM3uStream),
|
|
41
|
-
postM3uAssociatedPlaylistsSelection: Boolean(selectM3uAssociatedPlaylists),
|
|
42
|
-
postOnAudioTrack: Boolean(onAudioTrack),
|
|
43
|
-
postOnVideoTrack: Boolean(onVideoTrack),
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
const post = (worker, payload) => {
|
|
47
|
-
worker.postMessage(payload);
|
|
48
|
-
};
|
|
49
|
-
export const parseMediaOnWorker = async ({ controller, ...params }) => {
|
|
50
|
-
if (typeof Worker === 'undefined') {
|
|
51
|
-
throw new Error('"Worker" is not available. Cannot call workerClient()');
|
|
52
|
-
}
|
|
53
|
-
const worker = new Worker(new URL('./worker-server', import.meta.url));
|
|
54
|
-
post(worker, convertToWorkerPayload(params));
|
|
55
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
56
|
-
const onAbort = () => {
|
|
57
|
-
post(worker, { type: 'request-abort' });
|
|
58
|
-
};
|
|
59
|
-
const onResume = () => {
|
|
60
|
-
post(worker, { type: 'request-resume' });
|
|
61
|
-
};
|
|
62
|
-
const onPause = () => {
|
|
63
|
-
post(worker, { type: 'request-pause' });
|
|
64
|
-
};
|
|
65
|
-
const callbacks = {};
|
|
66
|
-
function onMessage(message) {
|
|
67
|
-
const data = message.data;
|
|
68
|
-
if (data.type === 'response-done') {
|
|
69
|
-
resolve(data.payload);
|
|
70
|
-
}
|
|
71
|
-
if (data.type === 'response-error') {
|
|
72
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
73
|
-
cleanup();
|
|
74
|
-
reject(deserializeError(data));
|
|
75
|
-
}
|
|
76
|
-
if (data.type === 'response-on-callback-request') {
|
|
77
|
-
Promise.resolve()
|
|
78
|
-
.then(async () => {
|
|
79
|
-
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;
|
|
80
|
-
if (data.payload.callbackType === 'audio-codec') {
|
|
81
|
-
await ((_a = params.onAudioCodec) === null || _a === void 0 ? void 0 : _a.call(params, data.payload.value));
|
|
82
|
-
return { payloadType: 'void' };
|
|
83
|
-
}
|
|
84
|
-
if (data.payload.callbackType === 'container') {
|
|
85
|
-
await ((_b = params.onContainer) === null || _b === void 0 ? void 0 : _b.call(params, data.payload.value));
|
|
86
|
-
return { payloadType: 'void' };
|
|
87
|
-
}
|
|
88
|
-
if (data.payload.callbackType === 'dimensions') {
|
|
89
|
-
await ((_c = params.onDimensions) === null || _c === void 0 ? void 0 : _c.call(params, data.payload.value));
|
|
90
|
-
return { payloadType: 'void' };
|
|
91
|
-
}
|
|
92
|
-
if (data.payload.callbackType === 'unrotated-dimensions') {
|
|
93
|
-
await ((_d = params.onUnrotatedDimensions) === null || _d === void 0 ? void 0 : _d.call(params, data.payload.value));
|
|
94
|
-
return { payloadType: 'void' };
|
|
95
|
-
}
|
|
96
|
-
if (data.payload.callbackType === 'video-codec') {
|
|
97
|
-
await ((_e = params.onVideoCodec) === null || _e === void 0 ? void 0 : _e.call(params, data.payload.value));
|
|
98
|
-
return { payloadType: 'void' };
|
|
99
|
-
}
|
|
100
|
-
if (data.payload.callbackType === 'tracks') {
|
|
101
|
-
await ((_f = params.onTracks) === null || _f === void 0 ? void 0 : _f.call(params, data.payload.value));
|
|
102
|
-
return { payloadType: 'void' };
|
|
103
|
-
}
|
|
104
|
-
if (data.payload.callbackType === 'rotation') {
|
|
105
|
-
await ((_g = params.onRotation) === null || _g === void 0 ? void 0 : _g.call(params, data.payload.value));
|
|
106
|
-
return { payloadType: 'void' };
|
|
107
|
-
}
|
|
108
|
-
if (data.payload.callbackType === 'sample-rate') {
|
|
109
|
-
await ((_h = params.onSampleRate) === null || _h === void 0 ? void 0 : _h.call(params, data.payload.value));
|
|
110
|
-
return { payloadType: 'void' };
|
|
111
|
-
}
|
|
112
|
-
if (data.payload.callbackType === 'slow-audio-bitrate') {
|
|
113
|
-
await ((_j = params.onSlowAudioBitrate) === null || _j === void 0 ? void 0 : _j.call(params, data.payload.value));
|
|
114
|
-
return { payloadType: 'void' };
|
|
115
|
-
}
|
|
116
|
-
if (data.payload.callbackType === 'slow-duration-in-seconds') {
|
|
117
|
-
await ((_k = params.onSlowDurationInSeconds) === null || _k === void 0 ? void 0 : _k.call(params, data.payload.value));
|
|
118
|
-
return { payloadType: 'void' };
|
|
119
|
-
}
|
|
120
|
-
if (data.payload.callbackType === 'slow-fps') {
|
|
121
|
-
await ((_l = params.onSlowFps) === null || _l === void 0 ? void 0 : _l.call(params, data.payload.value));
|
|
122
|
-
return { payloadType: 'void' };
|
|
123
|
-
}
|
|
124
|
-
if (data.payload.callbackType === 'slow-keyframes') {
|
|
125
|
-
await ((_m = params.onSlowKeyframes) === null || _m === void 0 ? void 0 : _m.call(params, data.payload.value));
|
|
126
|
-
return { payloadType: 'void' };
|
|
127
|
-
}
|
|
128
|
-
if (data.payload.callbackType === 'slow-number-of-frames') {
|
|
129
|
-
await ((_o = params.onSlowNumberOfFrames) === null || _o === void 0 ? void 0 : _o.call(params, data.payload.value));
|
|
130
|
-
return { payloadType: 'void' };
|
|
131
|
-
}
|
|
132
|
-
if (data.payload.callbackType === 'slow-video-bitrate') {
|
|
133
|
-
await ((_p = params.onSlowVideoBitrate) === null || _p === void 0 ? void 0 : _p.call(params, data.payload.value));
|
|
134
|
-
return { payloadType: 'void' };
|
|
135
|
-
}
|
|
136
|
-
if (data.payload.callbackType === 'structure') {
|
|
137
|
-
await ((_q = params.onStructure) === null || _q === void 0 ? void 0 : _q.call(params, data.payload.value));
|
|
138
|
-
return { payloadType: 'void' };
|
|
139
|
-
}
|
|
140
|
-
if (data.payload.callbackType === 'fps') {
|
|
141
|
-
await ((_r = params.onFps) === null || _r === void 0 ? void 0 : _r.call(params, data.payload.value));
|
|
142
|
-
return { payloadType: 'void' };
|
|
143
|
-
}
|
|
144
|
-
if (data.payload.callbackType === 'images') {
|
|
145
|
-
await ((_s = params.onImages) === null || _s === void 0 ? void 0 : _s.call(params, data.payload.value));
|
|
146
|
-
return { payloadType: 'void' };
|
|
147
|
-
}
|
|
148
|
-
if (data.payload.callbackType === 'internal-stats') {
|
|
149
|
-
await ((_t = params.onInternalStats) === null || _t === void 0 ? void 0 : _t.call(params, data.payload.value));
|
|
150
|
-
return { payloadType: 'void' };
|
|
151
|
-
}
|
|
152
|
-
if (data.payload.callbackType === 'is-hdr') {
|
|
153
|
-
await ((_u = params.onIsHdr) === null || _u === void 0 ? void 0 : _u.call(params, data.payload.value));
|
|
154
|
-
return { payloadType: 'void' };
|
|
155
|
-
}
|
|
156
|
-
if (data.payload.callbackType === 'keyframes') {
|
|
157
|
-
await ((_v = params.onKeyframes) === null || _v === void 0 ? void 0 : _v.call(params, data.payload.value));
|
|
158
|
-
return { payloadType: 'void' };
|
|
159
|
-
}
|
|
160
|
-
if (data.payload.callbackType === 'location') {
|
|
161
|
-
await ((_w = params.onLocation) === null || _w === void 0 ? void 0 : _w.call(params, data.payload.value));
|
|
162
|
-
return { payloadType: 'void' };
|
|
163
|
-
}
|
|
164
|
-
if (data.payload.callbackType === 'm3u-streams') {
|
|
165
|
-
await ((_x = params.onM3uStreams) === null || _x === void 0 ? void 0 : _x.call(params, data.payload.value));
|
|
166
|
-
return { payloadType: 'void' };
|
|
167
|
-
}
|
|
168
|
-
if (data.payload.callbackType === 'metadata') {
|
|
169
|
-
await ((_y = params.onMetadata) === null || _y === void 0 ? void 0 : _y.call(params, data.payload.value));
|
|
170
|
-
return { payloadType: 'void' };
|
|
171
|
-
}
|
|
172
|
-
if (data.payload.callbackType === 'mime-type') {
|
|
173
|
-
await ((_z = params.onMimeType) === null || _z === void 0 ? void 0 : _z.call(params, data.payload.value));
|
|
174
|
-
return { payloadType: 'void' };
|
|
175
|
-
}
|
|
176
|
-
if (data.payload.callbackType === 'name') {
|
|
177
|
-
await ((_0 = params.onName) === null || _0 === void 0 ? void 0 : _0.call(params, data.payload.value));
|
|
178
|
-
return { payloadType: 'void' };
|
|
179
|
-
}
|
|
180
|
-
if (data.payload.callbackType === 'number-of-audio-channels') {
|
|
181
|
-
await ((_1 = params.onNumberOfAudioChannels) === null || _1 === void 0 ? void 0 : _1.call(params, data.payload.value));
|
|
182
|
-
return { payloadType: 'void' };
|
|
183
|
-
}
|
|
184
|
-
if (data.payload.callbackType === 'size') {
|
|
185
|
-
await ((_2 = params.onSize) === null || _2 === void 0 ? void 0 : _2.call(params, data.payload.value));
|
|
186
|
-
return { payloadType: 'void' };
|
|
187
|
-
}
|
|
188
|
-
if (data.payload.callbackType === 'duration-in-seconds') {
|
|
189
|
-
await ((_3 = params.onDurationInSeconds) === null || _3 === void 0 ? void 0 : _3.call(params, data.payload.value));
|
|
190
|
-
return { payloadType: 'void' };
|
|
191
|
-
}
|
|
192
|
-
if (data.payload.callbackType === 'parse-progress') {
|
|
193
|
-
await ((_4 = params.onParseProgress) === null || _4 === void 0 ? void 0 : _4.call(params, data.payload.value));
|
|
194
|
-
return { payloadType: 'void' };
|
|
195
|
-
}
|
|
196
|
-
if (data.payload.callbackType === 'm3u-stream-selection') {
|
|
197
|
-
const selection = await params.selectM3uStream(data.payload.value);
|
|
198
|
-
return { payloadType: 'm3u-stream-selection', value: selection };
|
|
199
|
-
}
|
|
200
|
-
if (data.payload.callbackType === 'm3u-associated-playlists-selection') {
|
|
201
|
-
const selection = await params.selectM3uAssociatedPlaylists(data.payload.value);
|
|
202
|
-
return {
|
|
203
|
-
payloadType: 'm3u-associated-playlists-selection',
|
|
204
|
-
value: selection,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
if (data.payload.callbackType === 'on-audio-track') {
|
|
208
|
-
const possibleCallback = await ((_5 = params.onAudioTrack) === null || _5 === void 0 ? void 0 : _5.call(params, data.payload.value));
|
|
209
|
-
if (possibleCallback) {
|
|
210
|
-
callbacks[data.payload.value.track.trackId] = possibleCallback;
|
|
211
|
-
}
|
|
212
|
-
return {
|
|
213
|
-
payloadType: 'on-audio-track-response',
|
|
214
|
-
registeredCallback: Boolean(possibleCallback),
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
if (data.payload.callbackType === 'on-video-track') {
|
|
218
|
-
const possibleCallback = await ((_6 = params.onVideoTrack) === null || _6 === void 0 ? void 0 : _6.call(params, data.payload.value));
|
|
219
|
-
if (possibleCallback) {
|
|
220
|
-
callbacks[data.payload.value.track.trackId] = possibleCallback;
|
|
221
|
-
}
|
|
222
|
-
return {
|
|
223
|
-
payloadType: 'on-video-track-response',
|
|
224
|
-
registeredCallback: Boolean(possibleCallback),
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
if (data.payload.callbackType === 'on-audio-video-sample') {
|
|
228
|
-
const callback = callbacks[data.payload.trackId];
|
|
229
|
-
if (!callback) {
|
|
230
|
-
throw new Error(`No callback registered for track ${data.payload.trackId}`);
|
|
231
|
-
}
|
|
232
|
-
await callback(data.payload.value);
|
|
233
|
-
return { payloadType: 'void' };
|
|
234
|
-
}
|
|
235
|
-
throw new Error(`Unknown callback type: ${data.payload}`);
|
|
236
|
-
})
|
|
237
|
-
.then((payload) => {
|
|
238
|
-
post(worker, {
|
|
239
|
-
type: 'acknowledge-callback',
|
|
240
|
-
nonce: data.nonce,
|
|
241
|
-
...payload,
|
|
242
|
-
});
|
|
243
|
-
})
|
|
244
|
-
.catch((err) => {
|
|
245
|
-
reject(err);
|
|
246
|
-
post(worker, {
|
|
247
|
-
type: 'signal-error-in-callback',
|
|
248
|
-
nonce: data.nonce,
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
worker.addEventListener('message', onMessage);
|
|
254
|
-
controller === null || controller === void 0 ? void 0 : controller.addEventListener('abort', onAbort);
|
|
255
|
-
controller === null || controller === void 0 ? void 0 : controller.addEventListener('resume', onResume);
|
|
256
|
-
controller === null || controller === void 0 ? void 0 : controller.addEventListener('pause', onPause);
|
|
257
|
-
function cleanup() {
|
|
258
|
-
worker.removeEventListener('message', onMessage);
|
|
259
|
-
controller === null || controller === void 0 ? void 0 : controller.removeEventListener('abort', onAbort);
|
|
260
|
-
controller === null || controller === void 0 ? void 0 : controller.removeEventListener('resume', onResume);
|
|
261
|
-
controller === null || controller === void 0 ? void 0 : controller.removeEventListener('pause', onPause);
|
|
262
|
-
worker.terminate();
|
|
263
|
-
}
|
|
264
|
-
const val = await promise;
|
|
265
|
-
cleanup();
|
|
266
|
-
return val;
|
|
267
|
-
};
|
|
1
|
+
export { parseMediaOnServerWorker } from './parse-media-on-server-worker';
|
|
2
|
+
export { parseMediaOnWebWorker } from './parse-media-on-web-worker';
|
package/package.json
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/media-parser",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.274",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@types/wicg-file-system-access": "2023.10.5",
|
|
11
11
|
"eslint": "9.19.0",
|
|
12
|
-
"@types/bun": "1.2.
|
|
13
|
-
"@remotion/example-videos": "4.0.
|
|
14
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
12
|
+
"@types/bun": "1.2.5",
|
|
13
|
+
"@remotion/example-videos": "4.0.274",
|
|
14
|
+
"@remotion/eslint-config-internal": "4.0.274"
|
|
15
15
|
},
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
@@ -62,6 +62,12 @@
|
|
|
62
62
|
"require": "./dist/worker-server-entry.js",
|
|
63
63
|
"module": "./dist/esm/worker-server-entry.mjs",
|
|
64
64
|
"import": "./dist/esm/worker-server-entry.mjs"
|
|
65
|
+
},
|
|
66
|
+
"./worker": {
|
|
67
|
+
"types": "./dist/worker.d.ts",
|
|
68
|
+
"require": "./dist/worker.js",
|
|
69
|
+
"module": "./dist/esm/worker.mjs",
|
|
70
|
+
"import": "./dist/esm/worker.mjs"
|
|
65
71
|
}
|
|
66
72
|
},
|
|
67
73
|
"typesVersions": {
|
|
@@ -83,6 +89,9 @@
|
|
|
83
89
|
],
|
|
84
90
|
"worker-server-entry": [
|
|
85
91
|
"dist/worker-server-entry.d.ts"
|
|
92
|
+
],
|
|
93
|
+
"worker": [
|
|
94
|
+
"dist/worker.d.ts"
|
|
86
95
|
]
|
|
87
96
|
}
|
|
88
97
|
},
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { AudioTrack, VideoTrack } from '../../get-tracks';
|
|
2
|
-
import type { LogLevel } from '../../log';
|
|
3
|
-
import type { MediaParserController } from '../../media-parser-controller';
|
|
4
|
-
import type { ExistingM3uRun, M3uState } from '../../state/m3u-state';
|
|
5
|
-
import type { OnAudioSample, OnVideoSample } from '../../webcodec-sample-types';
|
|
6
|
-
import type { M3uStructure } from './types';
|
|
7
|
-
export declare const iteratorOverSegmentFiles: ({ structure, onVideoTrack, m3uState, onAudioTrack, onDoneWithTracks, playlistUrl, logLevel, parentController, onInitialProgress, }: {
|
|
8
|
-
structure: M3uStructure;
|
|
9
|
-
onVideoTrack: (track: VideoTrack) => Promise<OnVideoSample | null>;
|
|
10
|
-
onAudioTrack: (track: AudioTrack) => Promise<OnAudioSample | null>;
|
|
11
|
-
onDoneWithTracks: () => void;
|
|
12
|
-
m3uState: M3uState;
|
|
13
|
-
playlistUrl: string;
|
|
14
|
-
logLevel: LogLevel;
|
|
15
|
-
parentController: MediaParserController;
|
|
16
|
-
onInitialProgress: (run: ExistingM3uRun | null) => void;
|
|
17
|
-
}) => Promise<void>;
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.iteratorOverSegmentFiles = void 0;
|
|
4
|
-
const forward_controller_1 = require("../../forward-controller");
|
|
5
|
-
const media_parser_controller_1 = require("../../media-parser-controller");
|
|
6
|
-
const parse_media_1 = require("../../parse-media");
|
|
7
|
-
const get_chunks_1 = require("./get-chunks");
|
|
8
|
-
const get_playlist_1 = require("./get-playlist");
|
|
9
|
-
const iteratorOverSegmentFiles = async ({ structure, onVideoTrack, m3uState, onAudioTrack, onDoneWithTracks, playlistUrl, logLevel, parentController, onInitialProgress, }) => {
|
|
10
|
-
const playlist = (0, get_playlist_1.getPlaylist)(structure, playlistUrl);
|
|
11
|
-
const chunks = (0, get_chunks_1.getChunks)(playlist);
|
|
12
|
-
let resolver = onInitialProgress;
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
|
-
let rejector = (_e) => { };
|
|
15
|
-
const childController = (0, media_parser_controller_1.mediaParserController)();
|
|
16
|
-
const forwarded = (0, forward_controller_1.forwardMediaParserController)({
|
|
17
|
-
childController,
|
|
18
|
-
parentController,
|
|
19
|
-
});
|
|
20
|
-
const makeContinuationFn = () => {
|
|
21
|
-
return {
|
|
22
|
-
continue() {
|
|
23
|
-
const { promise, reject, resolve } = Promise.withResolvers();
|
|
24
|
-
resolver = resolve;
|
|
25
|
-
rejector = reject;
|
|
26
|
-
childController.resume();
|
|
27
|
-
return promise;
|
|
28
|
-
},
|
|
29
|
-
abort() {
|
|
30
|
-
childController.abort();
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
for (const chunk of chunks) {
|
|
35
|
-
const isLastChunk = chunk === chunks[chunks.length - 1];
|
|
36
|
-
await childController._internals.checkForAbortAndPause();
|
|
37
|
-
const src = new URL(chunk.url, playlistUrl);
|
|
38
|
-
const isMp4 = src.pathname.endsWith('.mp4');
|
|
39
|
-
try {
|
|
40
|
-
const data = await (0, parse_media_1.parseMedia)({
|
|
41
|
-
src,
|
|
42
|
-
acknowledgeRemotionLicense: true,
|
|
43
|
-
logLevel,
|
|
44
|
-
controller: childController,
|
|
45
|
-
progressIntervalInMs: 0,
|
|
46
|
-
onParseProgress: () => {
|
|
47
|
-
childController.pause();
|
|
48
|
-
resolver(makeContinuationFn());
|
|
49
|
-
},
|
|
50
|
-
fields: isMp4 ? { structure: true } : undefined,
|
|
51
|
-
onTracks: () => {
|
|
52
|
-
if (!m3uState.hasEmittedDoneWithTracks(playlistUrl)) {
|
|
53
|
-
m3uState.setHasEmittedDoneWithTracks(playlistUrl);
|
|
54
|
-
onDoneWithTracks();
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
},
|
|
58
|
-
onAudioTrack: async ({ track }) => {
|
|
59
|
-
const callbackOrFalse = m3uState.hasEmittedAudioTrack(playlistUrl);
|
|
60
|
-
if (callbackOrFalse === false) {
|
|
61
|
-
const callback = await onAudioTrack(track);
|
|
62
|
-
if (!callback) {
|
|
63
|
-
m3uState.setHasEmittedAudioTrack(playlistUrl, null);
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
m3uState.setHasEmittedAudioTrack(playlistUrl, callback);
|
|
67
|
-
return (sample) => {
|
|
68
|
-
return callback(sample);
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return callbackOrFalse;
|
|
72
|
-
},
|
|
73
|
-
onVideoTrack: async ({ track }) => {
|
|
74
|
-
const callbackOrFalse = m3uState.hasEmittedVideoTrack(playlistUrl);
|
|
75
|
-
if (callbackOrFalse === false) {
|
|
76
|
-
const callback = await onVideoTrack(track);
|
|
77
|
-
if (!callback) {
|
|
78
|
-
m3uState.setHasEmittedVideoTrack(playlistUrl, null);
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
m3uState.setHasEmittedVideoTrack(playlistUrl, callback);
|
|
82
|
-
return (sample) => {
|
|
83
|
-
return callback(sample);
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
return callbackOrFalse;
|
|
87
|
-
},
|
|
88
|
-
mp4HeaderSegment: m3uState.getMp4HeaderSegment(),
|
|
89
|
-
});
|
|
90
|
-
if (isMp4) {
|
|
91
|
-
if (data.structure.type !== 'iso-base-media') {
|
|
92
|
-
throw new Error('Expected an mp4 file');
|
|
93
|
-
}
|
|
94
|
-
m3uState.setMp4HeaderSegment(data.structure);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
rejector(e);
|
|
99
|
-
throw e;
|
|
100
|
-
}
|
|
101
|
-
forwarded.cleanup();
|
|
102
|
-
if (!isLastChunk) {
|
|
103
|
-
childController.pause();
|
|
104
|
-
resolver(makeContinuationFn());
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
resolver(null);
|
|
108
|
-
};
|
|
109
|
-
exports.iteratorOverSegmentFiles = iteratorOverSegmentFiles;
|
package/dist/esm/fetch.mjs
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
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 ({
|
|
12
|
-
canLiveWithoutContentLength,
|
|
13
|
-
res,
|
|
14
|
-
ownController,
|
|
15
|
-
requestedWithoutRange
|
|
16
|
-
}) => {
|
|
17
|
-
const length = res.headers.get("content-length");
|
|
18
|
-
const contentLength = length === null ? null : parseInt(length, 10);
|
|
19
|
-
if (requestedWithoutRange || canLiveWithoutContentLength && contentLength === null) {
|
|
20
|
-
const buffer = await res.arrayBuffer();
|
|
21
|
-
const encoded = new Uint8Array(buffer);
|
|
22
|
-
const stream = new ReadableStream({
|
|
23
|
-
start(controller) {
|
|
24
|
-
controller.enqueue(encoded);
|
|
25
|
-
controller.close();
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
return {
|
|
29
|
-
contentLength: encoded.byteLength,
|
|
30
|
-
reader: {
|
|
31
|
-
reader: stream.getReader(),
|
|
32
|
-
abort() {
|
|
33
|
-
ownController.abort();
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
needsContentRange: false
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
if (!res.body) {
|
|
40
|
-
throw new Error("No body");
|
|
41
|
-
}
|
|
42
|
-
const reader = res.body.getReader();
|
|
43
|
-
return {
|
|
44
|
-
reader: {
|
|
45
|
-
reader,
|
|
46
|
-
abort: () => {
|
|
47
|
-
ownController.abort();
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
contentLength,
|
|
51
|
-
needsContentRange: true
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// src/readers/fetch/resolve-url.ts
|
|
56
|
-
var resolveUrl = (src) => {
|
|
57
|
-
try {
|
|
58
|
-
const resolvedUrl = typeof window !== "undefined" && typeof window.location !== "undefined" ? new URL(src, window.location.origin) : new URL(src);
|
|
59
|
-
return resolvedUrl;
|
|
60
|
-
} catch {
|
|
61
|
-
return src;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// src/readers/from-fetch.ts
|
|
66
|
-
function parseContentRange(input) {
|
|
67
|
-
const matches = input.match(/^(\w+) ((\d+)-(\d+)|\*)\/(\d+|\*)$/);
|
|
68
|
-
if (!matches)
|
|
69
|
-
return null;
|
|
70
|
-
const [, unit, , start, end, size] = matches;
|
|
71
|
-
const range = {
|
|
72
|
-
unit,
|
|
73
|
-
start: start != null ? Number(start) : null,
|
|
74
|
-
end: end != null ? Number(end) : null,
|
|
75
|
-
size: size === "*" ? null : Number(size)
|
|
76
|
-
};
|
|
77
|
-
if (range.start === null && range.end === null && range.size === null) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
return range;
|
|
81
|
-
}
|
|
82
|
-
var validateContentRangeAndDetectIfSupported = ({
|
|
83
|
-
requestedRange,
|
|
84
|
-
parsedContentRange,
|
|
85
|
-
statusCode
|
|
86
|
-
}) => {
|
|
87
|
-
if (statusCode === 206) {
|
|
88
|
-
return { supportsContentRange: true };
|
|
89
|
-
}
|
|
90
|
-
if (typeof requestedRange === "number" && parsedContentRange?.start !== requestedRange) {
|
|
91
|
-
if (requestedRange === 0) {
|
|
92
|
-
return { supportsContentRange: false };
|
|
93
|
-
}
|
|
94
|
-
throw new Error(`Range header (${requestedRange}) does not match content-range header (${parsedContentRange?.start})`);
|
|
95
|
-
}
|
|
96
|
-
if (requestedRange !== null && typeof requestedRange !== "number" && (parsedContentRange?.start !== requestedRange[0] || parsedContentRange?.end !== requestedRange[1])) {
|
|
97
|
-
throw new Error(`Range header (${requestedRange}) does not match content-range header (${parsedContentRange?.start})`);
|
|
98
|
-
}
|
|
99
|
-
return { supportsContentRange: true };
|
|
100
|
-
};
|
|
101
|
-
var fetchReadContent = async ({
|
|
102
|
-
src,
|
|
103
|
-
range,
|
|
104
|
-
controller
|
|
105
|
-
}) => {
|
|
106
|
-
if (typeof src !== "string" && src instanceof URL === false) {
|
|
107
|
-
throw new Error("src must be a string when using `fetchReader`");
|
|
108
|
-
}
|
|
109
|
-
const resolvedUrl = resolveUrl(src);
|
|
110
|
-
const resolvedUrlString = resolvedUrl.toString();
|
|
111
|
-
if (!resolvedUrlString.startsWith("https://") && !resolvedUrlString.startsWith("blob:") && !resolvedUrlString.startsWith("http://")) {
|
|
112
|
-
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().`));
|
|
113
|
-
}
|
|
114
|
-
const ownController = new AbortController;
|
|
115
|
-
const cache = typeof navigator !== "undefined" && navigator.userAgent.includes("Cloudflare-Workers") ? undefined : "no-store";
|
|
116
|
-
const requestedRange = range === null ? 0 : range;
|
|
117
|
-
const asString = typeof resolvedUrl === "string" ? resolvedUrl : resolvedUrl.pathname;
|
|
118
|
-
const requestWithoutRange = asString.endsWith(".m3u8");
|
|
119
|
-
const canLiveWithoutContentLength = asString.endsWith(".m3u8") || asString.endsWith(".ts");
|
|
120
|
-
const headers = requestedRange === 0 && requestWithoutRange ? {} : typeof requestedRange === "number" ? {
|
|
121
|
-
Range: `bytes=${requestedRange}-`
|
|
122
|
-
} : {
|
|
123
|
-
Range: `bytes=${`${requestedRange[0]}-${requestedRange[1]}`}`
|
|
124
|
-
};
|
|
125
|
-
const res = await fetch(resolvedUrl, {
|
|
126
|
-
headers,
|
|
127
|
-
signal: ownController.signal,
|
|
128
|
-
cache
|
|
129
|
-
});
|
|
130
|
-
const contentRange = res.headers.get("content-range");
|
|
131
|
-
const parsedContentRange = contentRange ? parseContentRange(contentRange) : null;
|
|
132
|
-
const { supportsContentRange } = validateContentRangeAndDetectIfSupported({
|
|
133
|
-
requestedRange,
|
|
134
|
-
parsedContentRange,
|
|
135
|
-
statusCode: res.status
|
|
136
|
-
});
|
|
137
|
-
controller._internals.signal.addEventListener("abort", () => {
|
|
138
|
-
ownController.abort(new MediaParserAbortError("Aborted by user"));
|
|
139
|
-
}, { once: true });
|
|
140
|
-
if (res.status.toString().startsWith("4") || res.status.toString().startsWith("5")) {
|
|
141
|
-
throw new Error(`Server returned status code ${res.status} for ${src} and range ${requestedRange}`);
|
|
142
|
-
}
|
|
143
|
-
const contentDisposition = res.headers.get("content-disposition");
|
|
144
|
-
const name = contentDisposition?.match(/filename="([^"]+)"/)?.[1];
|
|
145
|
-
const fallbackName = src.toString().split("/").pop();
|
|
146
|
-
const { contentLength, needsContentRange, reader } = await getLengthAndReader({
|
|
147
|
-
canLiveWithoutContentLength,
|
|
148
|
-
res,
|
|
149
|
-
ownController,
|
|
150
|
-
requestedWithoutRange: requestWithoutRange
|
|
151
|
-
});
|
|
152
|
-
if (controller) {
|
|
153
|
-
controller._internals.signal.addEventListener("abort", () => {
|
|
154
|
-
reader.reader.cancel().catch(() => {
|
|
155
|
-
});
|
|
156
|
-
}, { once: true });
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
reader,
|
|
160
|
-
contentLength,
|
|
161
|
-
contentType: res.headers.get("content-type"),
|
|
162
|
-
name: name ?? fallbackName,
|
|
163
|
-
supportsContentRange,
|
|
164
|
-
needsContentRange
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
var fetchReadWholeAsText = async (src) => {
|
|
168
|
-
if (typeof src !== "string" && src instanceof URL === false) {
|
|
169
|
-
throw new Error("src must be a string when using `fetchReader`");
|
|
170
|
-
}
|
|
171
|
-
const res = await fetch(src);
|
|
172
|
-
if (!res.ok) {
|
|
173
|
-
throw new Error(`Failed to fetch ${src} (HTTP code: ${res.status})`);
|
|
174
|
-
}
|
|
175
|
-
return res.text();
|
|
176
|
-
};
|
|
177
|
-
var fetchCreateAdjacentFileSource = (relativePath, src) => {
|
|
178
|
-
if (typeof src !== "string" && src instanceof URL === false) {
|
|
179
|
-
throw new Error("src must be a string or URL when using `fetchReader`");
|
|
180
|
-
}
|
|
181
|
-
return new URL(relativePath, src).toString();
|
|
182
|
-
};
|
|
183
|
-
var fetchReader = {
|
|
184
|
-
read: fetchReadContent,
|
|
185
|
-
readWholeAsText: fetchReadWholeAsText,
|
|
186
|
-
createAdjacentFileSource: fetchCreateAdjacentFileSource
|
|
187
|
-
};
|
|
188
|
-
export {
|
|
189
|
-
parseContentRange,
|
|
190
|
-
fetchReader,
|
|
191
|
-
fetchReadWholeAsText,
|
|
192
|
-
fetchReadContent,
|
|
193
|
-
fetchCreateAdjacentFileSource
|
|
194
|
-
};
|