@xhub-short/adapters 1.0.0-beta.26 → 1.0.0-beta.27
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/index.d.ts +8 -0
- package/dist/index.js +73 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1672,6 +1672,14 @@ declare class BrowserVideoLoader implements IVideoLoader {
|
|
|
1672
1672
|
* Full segment preload requires hls.js which is optional
|
|
1673
1673
|
*/
|
|
1674
1674
|
private preloadHLS;
|
|
1675
|
+
/**
|
|
1676
|
+
* Parse M3U8 manifest and pre-fetch the first N segments into the Cache API.
|
|
1677
|
+
* Runs concurrently for speed; tolerates individual segment fetch failures.
|
|
1678
|
+
*
|
|
1679
|
+
* Resolves relative segment paths against the manifest URL base.
|
|
1680
|
+
* Only runs when a cache is available - gracefully no-ops otherwise.
|
|
1681
|
+
*/
|
|
1682
|
+
private preloadHLSSegments;
|
|
1675
1683
|
/**
|
|
1676
1684
|
* Cancel preload
|
|
1677
1685
|
*/
|
package/dist/index.js
CHANGED
|
@@ -4196,11 +4196,42 @@ var BrowserVideoLoader = class {
|
|
|
4196
4196
|
* Full segment preload requires hls.js which is optional
|
|
4197
4197
|
*/
|
|
4198
4198
|
async preloadHLS(url, signal) {
|
|
4199
|
+
const _isDev = globalThis.process?.env?.NODE_ENV !== "production";
|
|
4200
|
+
const _t0 = _isDev ? performance.now() : 0;
|
|
4201
|
+
if (_isDev) {
|
|
4202
|
+
performance.mark("sv-preload:hls:start");
|
|
4203
|
+
console.debug(
|
|
4204
|
+
"%c\u{1F504} [HLS Preload] manifest fetch start",
|
|
4205
|
+
"color:#7c3aed;font-size:11px;",
|
|
4206
|
+
url.slice(url.lastIndexOf("/") + 1).slice(0, 60)
|
|
4207
|
+
);
|
|
4208
|
+
}
|
|
4199
4209
|
const response = await fetch(url, { signal });
|
|
4200
4210
|
if (!response.ok) {
|
|
4201
4211
|
throw new Error(`HTTP error: ${response.status}`);
|
|
4202
4212
|
}
|
|
4203
4213
|
const text = await response.text();
|
|
4214
|
+
if (_isDev) {
|
|
4215
|
+
performance.mark("sv-preload:hls:done");
|
|
4216
|
+
try {
|
|
4217
|
+
performance.measure(
|
|
4218
|
+
"sv-preload:hls:manifest",
|
|
4219
|
+
"sv-preload:hls:start",
|
|
4220
|
+
"sv-preload:hls:done"
|
|
4221
|
+
);
|
|
4222
|
+
} catch {
|
|
4223
|
+
}
|
|
4224
|
+
const segCount = text.split("\n").filter(
|
|
4225
|
+
(l) => l.endsWith(".ts") || l.endsWith(".m4s") || l.includes(".ts?") || l.includes(".m4s?")
|
|
4226
|
+
).length;
|
|
4227
|
+
console.debug(
|
|
4228
|
+
"%c\u2705 [HLS Preload] manifest done",
|
|
4229
|
+
"color:#059669;font-size:11px;",
|
|
4230
|
+
`+${(performance.now() - _t0).toFixed(0)}ms`,
|
|
4231
|
+
`${text.length} bytes`,
|
|
4232
|
+
`segments: ${segCount}`
|
|
4233
|
+
);
|
|
4234
|
+
}
|
|
4204
4235
|
if (this.cache) {
|
|
4205
4236
|
try {
|
|
4206
4237
|
const cacheResponse = new Response(text, {
|
|
@@ -4212,8 +4243,50 @@ var BrowserVideoLoader = class {
|
|
|
4212
4243
|
} catch {
|
|
4213
4244
|
}
|
|
4214
4245
|
}
|
|
4246
|
+
await this.preloadHLSSegments(url, text, signal);
|
|
4215
4247
|
return text.length;
|
|
4216
4248
|
}
|
|
4249
|
+
/**
|
|
4250
|
+
* Parse M3U8 manifest and pre-fetch the first N segments into the Cache API.
|
|
4251
|
+
* Runs concurrently for speed; tolerates individual segment fetch failures.
|
|
4252
|
+
*
|
|
4253
|
+
* Resolves relative segment paths against the manifest URL base.
|
|
4254
|
+
* Only runs when a cache is available - gracefully no-ops otherwise.
|
|
4255
|
+
*/
|
|
4256
|
+
async preloadHLSSegments(manifestUrl, manifestText, signal, maxSegments = 3) {
|
|
4257
|
+
if (!this.cache) return;
|
|
4258
|
+
const baseUrl = manifestUrl.substring(0, manifestUrl.lastIndexOf("/") + 1);
|
|
4259
|
+
const segmentUrls = manifestText.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#")).slice(0, maxSegments).map((l) => l.startsWith("http") ? l : `${baseUrl}${l}`);
|
|
4260
|
+
if (segmentUrls.length === 0) return;
|
|
4261
|
+
const _isDev = globalThis.process?.env?.NODE_ENV !== "production";
|
|
4262
|
+
if (_isDev) {
|
|
4263
|
+
console.debug(
|
|
4264
|
+
"%c\u{1F4E6} [HLS Preload] fetching first segments",
|
|
4265
|
+
"color:#7c3aed;font-size:11px;",
|
|
4266
|
+
segmentUrls.map((u) => u.slice(u.lastIndexOf("/") + 1).slice(0, 40))
|
|
4267
|
+
);
|
|
4268
|
+
}
|
|
4269
|
+
const cache = this.cache;
|
|
4270
|
+
await Promise.allSettled(
|
|
4271
|
+
segmentUrls.map(async (segUrl) => {
|
|
4272
|
+
const existing = await cache.match(segUrl);
|
|
4273
|
+
if (existing) return;
|
|
4274
|
+
const segResponse = await fetch(segUrl, { signal });
|
|
4275
|
+
if (segResponse.ok) {
|
|
4276
|
+
await cache.put(segUrl, segResponse.clone());
|
|
4277
|
+
if (_isDev) {
|
|
4278
|
+
const size = Number(segResponse.headers.get("content-length") ?? 0);
|
|
4279
|
+
console.debug(
|
|
4280
|
+
"%c \u2713 segment cached",
|
|
4281
|
+
"color:#059669;font-size:11px;",
|
|
4282
|
+
segUrl.slice(segUrl.lastIndexOf("/") + 1).slice(0, 50),
|
|
4283
|
+
size ? `${(size / 1024).toFixed(0)}KB` : ""
|
|
4284
|
+
);
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4287
|
+
})
|
|
4288
|
+
);
|
|
4289
|
+
}
|
|
4217
4290
|
/**
|
|
4218
4291
|
* Cancel preload
|
|
4219
4292
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xhub-short/adapters",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "1.0.0-beta.
|
|
4
|
+
"version": "1.0.0-beta.27",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@xhub-short/contracts": "1.0.0-beta.
|
|
23
|
+
"@xhub-short/contracts": "1.0.0-beta.27"
|
|
24
24
|
},
|
|
25
25
|
"optionalDependencies": {
|
|
26
26
|
"hls.js": "^1.5.0"
|