From a7ca1a087fa9ea6baea12d0859c12e5e6dcb0b50 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Sun, 14 Dec 2025 16:43:23 +0100 Subject: [PATCH] feat: add Xtream service for IPTV integration and a lite player HTML file. --- .../iptv/services/xtream_service.dart | 11 +++-- web/player_lite.html | 46 ++++++++----------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/lib/features/iptv/services/xtream_service.dart b/lib/features/iptv/services/xtream_service.dart index 20ec6e9..cab804d 100644 --- a/lib/features/iptv/services/xtream_service.dart +++ b/lib/features/iptv/services/xtream_service.dart @@ -37,10 +37,15 @@ class XtreamService { return html.window.location.protocol == 'https:'; } - /// Wrap URL with proxy if needed (for HTTPS to HTTP bridge) + /// Wrap URL with proxy for all external IPTV URLs + /// + /// Always use proxy for HTTP URLs to: + /// 1. Handle HTTPS->HTTP mixed content + /// 2. Provide Range header support for seeking + /// 3. Normalize headers and handle redirects String _wrapWithProxy(String url) { - // If we're on HTTPS and the target URL is HTTP, use the proxy - if (_isHttps && url.startsWith('http://')) { + // Always proxy HTTP URLs for consistent streaming behavior + if (url.startsWith('http://')) { final baseUrl = html.window.location.origin; return '$baseUrl/api/xtream/$url'; } diff --git a/web/player_lite.html b/web/player_lite.html index 1173b73..adca23a 100644 --- a/web/player_lite.html +++ b/web/player_lite.html @@ -361,38 +361,30 @@ log('Stream type: ' + streamType); const lowerUrl = streamUrl.toLowerCase(); - // SPECIAL: /api/stream/ endpoint handling - differentiate Live vs VOD + // SPECIAL: /api/stream/ endpoint handling - ALWAYS returns JSON with HLS playlist if (streamUrl.includes('/api/stream/')) { - if (streamType === 'live') { - // LIVE TV: Use MPEG-TS direct streaming - log('Live TV via /api/stream/ - using MPEG-TS direct'); - showLoading('Connecting to live stream...'); - await playWithMpegTS(streamUrl, true); // isLive=true - return; - } else { - // VOD: Fetch JSON to get HLS playlist URL (transcoding mode) - log('VOD via /api/stream/ - fetching HLS playlist...'); - showLoading('Initializing stream (transcoding audio)...'); + // Both Live TV and VOD use /api/stream/ which returns JSON with HLS playlist URL + log((streamType === 'live' ? 'Live TV' : 'VOD') + ' via /api/stream/ - fetching HLS...'); + showLoading(streamType === 'live' ? 'Connecting to live stream...' : 'Initializing stream...'); - try { - const response = await fetch(streamUrl); - const data = await response.json(); + try { + const response = await fetch(streamUrl); + const data = await response.json(); - if (data.playlist) { - const playlistUrl = window.location.origin + data.playlist; - log('Got HLS playlist: ' + playlistUrl); - showLoading('Loading HLS stream...'); - await playWithHLS(playlistUrl); - return; - } else { - showError('Invalid stream response'); - return; - } - } catch (err) { - log('Error fetching playlist: ' + err); - showError('Failed to initialize stream'); + if (data.playlist) { + const playlistUrl = window.location.origin + data.playlist; + log('Got HLS playlist: ' + playlistUrl); + showLoading('Loading HLS stream...'); + await playWithHLS(playlistUrl); + return; + } else { + showError('Invalid stream response'); return; } + } catch (err) { + log('Error fetching playlist: ' + err); + showError('Failed to initialize stream'); + return; } }