Fix
Fix: HLS Proxy Rewriting for Vixsrc (and similar providers)
Problem Summary
When using the built-in stream proxy (enableProxy: true), streams from Vixsrc (and potentially other providers using similar HLS structures) failed to play with the following errors:
HTTP error 403 Forbidden — sub-playlist video renditions (480p/720p/1080p)
HTTP error 404 Not Found — /storage/enc.key (AES-128 encryption key)
Both errors caused complete playback failure in any HLS-capable player (mpv, VLC, ffmpeg).
Root Cause Analysis
Bug 1 — Video sub-playlists not proxied (403)
The rewriteM3u8 function in proxy/proxyServer.js rewrites URLs found in plain lines (non-# lines) of the master playlist. However, it only proxied URLs ending in .m3u8 or .ts:
if (/\.m3u8(\?|$)/i.test(abs)) {
out.push(`${baseProxyUrl}/m3u8-proxy?url=...`);
} else if (/\.ts(\?|$)/i.test(abs)) {
out.push(`${baseProxyUrl}/ts-proxy?url=...`);
} else out.push(line); // ← BUG: URL without extension passed through as-is
Vixsrc sub-playlist URLs look like:
https://vixsrc.to/playlist/214325?type=video&rendition=1080p&token=...&expires=...&edge=sc-u16-01
These have no .m3u8 extension, so they fell into the else branch and were written directly into the rewritten playlist — causing the player to request them without the required Referer and User-Agent headers, resulting in 403 Forbidden.
Bug 2 — AES-128 encryption key not proxied (404)
The #EXT-X-KEY handler used a regex to find the key URL:
const regex = /https?:\/\/[^""\s]+/g;
const keyUrl = regex.exec(line)?.[0];
This regex only matches absolute URLs starting with http:// or https://. However, Vixsrc uses a relative path for the encryption key:
#EXT-X-KEY:METHOD=AES-128,URI="/storage/enc.key",IV=0x...
Since /storage/enc.key doesn't match the regex, keyUrl was null and the line was passed through unchanged. The player then requested /storage/enc.key directly from the proxy server, which has no such route, resulting in 404 Not Found and making all segments undecryptable.
Fix
Fix 1 — Proxy all sub-playlist URLs regardless of extension
In rewriteM3u8, change the fallback else branch to proxy any non-.ts URL as an m3u8:
// Before
} else out.push(line);
// After
} else {
// Proxy any other URL (e.g. Vixsrc sub-playlists without .m3u8 extension)
out.push(`${baseProxyUrl}/m3u8-proxy?url=${encodeURIComponent(abs)}&headers=${encodeURIComponent(JSON.stringify(headers))}`);
}
Fix 2 — Handle relative URIs in #EXT-X-KEY
Replace the absolute-only regex with a URI-aware extraction that resolves relative paths against the playlist's base URL:
// Before
if (line.startsWith('#EXT-X-KEY:')) {
const regex = /https?:\/\/[^""\s]+/g;
const keyUrl = regex.exec(line)?.[0];
if (keyUrl) {
const proxyUrl = `${baseProxyUrl}/ts-proxy?url=${encodeURIComponent(keyUrl)}&headers=...`;
out.push(line.replace(keyUrl, proxyUrl));
} else out.push(line);
}
// After
if (line.startsWith('#EXT-X-KEY:')) {
const uriMatch = line.match(/URI="([^"]+)"/);
const rawKeyUrl = uriMatch?.[1];
const keyUrl = rawKeyUrl
? (rawKeyUrl.startsWith('http') ? rawKeyUrl : new URL(rawKeyUrl, targetUrl).href)
: null;
if (keyUrl) {
const proxyUrl = `${baseProxyUrl}/ts-proxy?url=${encodeURIComponent(keyUrl)}&headers=...`;
out.push(line.replace(rawKeyUrl, proxyUrl)); // replace rawKeyUrl, not resolved keyUrl
} else out.push(line);
}
Key detail: line.replace(rawKeyUrl, proxyUrl) replaces the original string (e.g. /storage/enc.key) in the m3u8 line, not the resolved absolute URL — otherwise the substitution would fail to match.
Result
After both fixes, the full HLS chain passes through the proxy correctly:
Master playlist → /m3u8-proxy ✓
Audio sub-playlist → /m3u8-proxy ✓
Subtitle playlist → /m3u8-proxy ✓
Video sub-playlist → /m3u8-proxy ✓ (was bypassing proxy → 403)
AES-128 key → /ts-proxy ✓ (was 404, relative URI not resolved)
Video segments (.ts)→ /ts-proxy ✓
Tested with Vixsrc provider, movie TMDB ID 603 (The Matrix), 1080p stream with Italian audio and subtitles. Playback confirmed working in mpv and VLC.
Affected Providers
Any provider whose master playlist contains:
- Sub-playlist URLs without
.m3u8 extension (query-string based routing)
#EXT-X-KEY with a relative URI path
Known affected: Vixsrc. Potentially others with similar CDN setups.
Files Changed
proxy/proxyServer.js — rewriteM3u8 function, two locations
Fix
Fix: HLS Proxy Rewriting for Vixsrc (and similar providers)
Problem Summary
When using the built-in stream proxy (
enableProxy: true), streams from Vixsrc (and potentially other providers using similar HLS structures) failed to play with the following errors:Both errors caused complete playback failure in any HLS-capable player (mpv, VLC, ffmpeg).
Root Cause Analysis
Bug 1 — Video sub-playlists not proxied (403)
The
rewriteM3u8function inproxy/proxyServer.jsrewrites URLs found in plain lines (non-#lines) of the master playlist. However, it only proxied URLs ending in.m3u8or.ts:Vixsrc sub-playlist URLs look like:
These have no
.m3u8extension, so they fell into theelsebranch and were written directly into the rewritten playlist — causing the player to request them without the requiredRefererandUser-Agentheaders, resulting in 403 Forbidden.Bug 2 — AES-128 encryption key not proxied (404)
The
#EXT-X-KEYhandler used a regex to find the key URL:This regex only matches absolute URLs starting with
http://orhttps://. However, Vixsrc uses a relative path for the encryption key:Since
/storage/enc.keydoesn't match the regex,keyUrlwasnulland the line was passed through unchanged. The player then requested/storage/enc.keydirectly from the proxy server, which has no such route, resulting in 404 Not Found and making all segments undecryptable.Fix
Fix 1 — Proxy all sub-playlist URLs regardless of extension
In
rewriteM3u8, change the fallbackelsebranch to proxy any non-.tsURL as an m3u8:Fix 2 — Handle relative URIs in
#EXT-X-KEYReplace the absolute-only regex with a URI-aware extraction that resolves relative paths against the playlist's base URL:
Key detail:
line.replace(rawKeyUrl, proxyUrl)replaces the original string (e.g./storage/enc.key) in the m3u8 line, not the resolved absolute URL — otherwise the substitution would fail to match.Result
After both fixes, the full HLS chain passes through the proxy correctly:
Tested with Vixsrc provider, movie TMDB ID
603(The Matrix), 1080p stream with Italian audio and subtitles. Playback confirmed working in mpv and VLC.Affected Providers
Any provider whose master playlist contains:
.m3u8extension (query-string based routing)#EXT-X-KEYwith a relativeURIpathKnown affected: Vixsrc. Potentially others with similar CDN setups.
Files Changed
proxy/proxyServer.js—rewriteM3u8function, two locations