Update TurboVidPlay.ts
Add height on both direct and proxied.
This commit is contained in:
parent
f65e6dea40
commit
e6c5201b97
1 changed files with 33 additions and 16 deletions
|
|
@ -43,6 +43,7 @@ export class TurboVidPlay extends Extractor {
|
|||
Referer: url.origin,
|
||||
};
|
||||
|
||||
// ---- 1. Fetch embed HTML ----
|
||||
const html = await this.fetcher.text(ctx, url, headers);
|
||||
if (
|
||||
!html
|
||||
|
|
@ -52,7 +53,7 @@ export class TurboVidPlay extends Extractor {
|
|||
throw new NotFoundError();
|
||||
}
|
||||
|
||||
// Extract media URL via named capture group
|
||||
// ---- 2. Extract media URL via named capture group ----
|
||||
const match = html.match(
|
||||
/(?:urlPlay|data-hash)\s*=\s*['"](?<url>[^"']+)/,
|
||||
);
|
||||
|
|
@ -64,14 +65,17 @@ export class TurboVidPlay extends Extractor {
|
|||
throw new NotFoundError('Video link not found');
|
||||
}
|
||||
|
||||
const masterUrl
|
||||
= mediaUrl.startsWith('//')
|
||||
// ---- 3. Build master playlist URL ----
|
||||
const masterUrl =
|
||||
mediaUrl.startsWith('//')
|
||||
? `https:${mediaUrl}`
|
||||
: mediaUrl.startsWith('/')
|
||||
? url.origin + mediaUrl
|
||||
: mediaUrl;
|
||||
|
||||
// ---- 4. Parse playlist → height + /data/ direct stream ----
|
||||
let directDataStream: string | null = null;
|
||||
let height: number | undefined;
|
||||
|
||||
try {
|
||||
const playlistText = await this.fetcher.text(
|
||||
|
|
@ -80,34 +84,44 @@ export class TurboVidPlay extends Extractor {
|
|||
headers,
|
||||
);
|
||||
|
||||
const variantMatches = [
|
||||
...playlistText.matchAll(/#EXT-X-STREAM-INF[^\n]*\n([^\n]+)/g),
|
||||
];
|
||||
const variants = playlistText.matchAll(
|
||||
/#EXT-X-STREAM-INF:([^\n]+)\n([^\n]+)/g,
|
||||
);
|
||||
|
||||
for (const m of variantMatches) {
|
||||
const variantUrl = m[1];
|
||||
if (!variantUrl) continue;
|
||||
for (const v of variants) {
|
||||
const attrs = v[1];
|
||||
const variantUrl = v[2];
|
||||
if (!attrs || !variantUrl) continue;
|
||||
|
||||
if (variantUrl.includes('/data/')) {
|
||||
// Always attempt to extract height (max height wins)
|
||||
const resMatch = attrs.match(/RESOLUTION=\d+x(\d+)/);
|
||||
if (resMatch) {
|
||||
const h = Number(resMatch[1]);
|
||||
if (!height || h > height) {
|
||||
height = h;
|
||||
}
|
||||
}
|
||||
|
||||
// Decide if direct playback possible (first /data/ wins)
|
||||
if (!directDataStream && variantUrl.includes('/data/')) {
|
||||
const base = new URL(masterUrl);
|
||||
|
||||
directDataStream
|
||||
= variantUrl.startsWith('http')
|
||||
directDataStream =
|
||||
variantUrl.startsWith('http')
|
||||
? variantUrl
|
||||
: variantUrl.startsWith('/')
|
||||
? new URL(variantUrl, base.origin).href
|
||||
: new URL(variantUrl, base.href).href;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Ignore playlist parsing errors
|
||||
// Ignore playlist parsing errors → fallback to MediaFlow only
|
||||
}
|
||||
|
||||
// ---- 5. Title ----
|
||||
const $ = cheerio.load(html);
|
||||
const title = $('title').text().trim() || this.label;
|
||||
|
||||
// ---- 6. Direct play if /data/ available ----
|
||||
if (directDataStream) {
|
||||
return [
|
||||
{
|
||||
|
|
@ -119,12 +133,14 @@ export class TurboVidPlay extends Extractor {
|
|||
requestHeaders: headers,
|
||||
meta: {
|
||||
...meta,
|
||||
height,
|
||||
title,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// ---- 7. MediaFlow proxy fallback ----
|
||||
const proxiedUrl = await buildMediaFlowProxyExtractorStreamUrl(
|
||||
ctx,
|
||||
this.fetcher,
|
||||
|
|
@ -143,6 +159,7 @@ export class TurboVidPlay extends Extractor {
|
|||
requestHeaders: headers,
|
||||
meta: {
|
||||
...meta,
|
||||
height,
|
||||
title,
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue