feat: Add fetchWithRetry utility, improve proxy M3U8 handling, and warn about HEVC codecs in HLS player.

This commit is contained in:
kuekhaoyang
2025-11-29 15:55:24 +08:00
parent bdae587bd5
commit f9cf4fdfb2
5 changed files with 266 additions and 76 deletions
+45 -14
View File
@@ -1,3 +1,24 @@
/**
* Extract and proxy URI from HLS tags like EXT-X-KEY, EXT-X-MAP, EXT-X-MEDIA
*/
function proxyUriInTag(line: string, base: URL, origin: string): string {
const uriMatch = line.match(/URI="([^"]+)"/);
if (uriMatch && uriMatch[1]) {
const uri = uriMatch[1];
// Skip if already proxied
if (uri.includes('/api/proxy')) {
return line;
}
try {
const absoluteUrl = new URL(uri, base).toString();
const proxiedUrl = `${origin}/api/proxy?url=${encodeURIComponent(absoluteUrl)}`;
return line.replace(/URI="[^"]+"/, `URI="${proxiedUrl}"`);
} catch {
return line;
}
}
return line;
}
export async function processM3u8Content(
content: string,
@@ -10,20 +31,25 @@ export async function processM3u8Content(
const processedLines = lines.map(line => {
const trimmed = line.trim();
// Handle EXT-X-KEY encryption keys
// Handle EXT-X-KEY (encryption keys)
if (trimmed.startsWith('#EXT-X-KEY:')) {
// Extract URI from the key tag
const uriMatch = trimmed.match(/URI="([^"]+)"/);
if (uriMatch && uriMatch[1]) {
const keyUri = uriMatch[1];
try {
const absoluteUrl = new URL(keyUri, base).toString();
const proxiedUrl = `${origin}/api/proxy?url=${encodeURIComponent(absoluteUrl)}`;
return trimmed.replace(/URI="[^"]+"/, `URI="${proxiedUrl}"`);
} catch {
return line;
}
}
return proxyUriInTag(trimmed, base, origin);
}
// Handle EXT-X-MAP (fMP4 initialization segments)
if (trimmed.startsWith('#EXT-X-MAP:')) {
return proxyUriInTag(trimmed, base, origin);
}
// Handle EXT-X-MEDIA (alternative audio/subtitle tracks)
if (trimmed.startsWith('#EXT-X-MEDIA:')) {
return proxyUriInTag(trimmed, base, origin);
}
// Handle EXT-X-STREAM-INF (master playlist variants)
// The URL is on the NEXT line after this tag
if (trimmed.startsWith('#EXT-X-STREAM-INF:')) {
return line;
}
// Skip other comments and empty lines
@@ -31,7 +57,12 @@ export async function processM3u8Content(
return line;
}
// Resolve relative URLs for segments
// Resolve relative URLs for segments and variant playlists
// Skip if already proxied
if (trimmed.includes('/api/proxy')) {
return line;
}
try {
const absoluteUrl = new URL(trimmed, base).toString();
return `${origin}/api/proxy?url=${encodeURIComponent(absoluteUrl)}`;