feat: implement Xtream Codes API service for managing IPTV connections, streams, and channel data.

This commit is contained in:
Michael committed 2025-12-14 00:17:13 +01:00
1 parent b589a834a0
commit 85deb540d2
3 files changed
+48 -12

No files matched your search

+10 -2
View File
@@ -72,16 +72,24 @@ class XtreamService {
String getVodStreamUrl(String streamId, String containerExtension) {
if (_currentPlaylist == null) throw Exception('No playlist configured');
// Use FFmpeg transcoding to ensure audio compatibility (converts AC3/DTS to AAC)
final url = '${_currentPlaylist!.dns}/movie/${_currentPlaylist!.username}/${_currentPlaylist!.password}/$streamId.$containerExtension';
return _wrapWithProxy(url);
final baseUrl = html.window.location.origin;
final encodedUrl = Uri.encodeComponent(url);
return '$baseUrl/api/stream/$streamId?url=$encodedUrl';
}
/// Generate stream URL for series episodes
String getSeriesStreamUrl(String streamId, String containerExtension) {
if (_currentPlaylist == null) throw Exception('No playlist configured');
// Use FFmpeg transcoding to ensure audio compatibility
final url = '${_currentPlaylist!.dns}/series/${_currentPlaylist!.username}/${_currentPlaylist!.password}/$streamId.$containerExtension';
return _wrapWithProxy(url);
final baseUrl = html.window.location.origin;
final encodedUrl = Uri.encodeComponent(url);
return '$baseUrl/api/stream/$streamId?url=$encodedUrl';
}
/// Authenticate and get server info
+14
View File
@@ -511,6 +511,20 @@
log('Stream URL: ' + streamUrl.substring(0, 80) + '...');
// SPECIAL: /api/stream/ endpoint outputs MPEG-TS, use mpegts.js directly
if (streamUrl.includes('/api/stream/')) {
log('Detected /api/stream/ endpoint - using MPEG-TS player for transcoded stream');
showLoading('Initializing stream (transcoding audio)...');
if (mpegts.isSupported()) {
await playWithMpegTS(streamUrl);
return;
} else {
showError('MPEG-TS playback not supported on this device');
return;
}
}
// Determine stream type and try appropriate player
const lowerUrl = streamUrl.toLowerCase();
const ext = urlParams.get('ext') ? urlParams.get('ext').toLowerCase() : '';
+24 -10
View File
@@ -239,8 +239,8 @@
return true;
}
async function playWithMpegTS(url) {
log('Trying mpegts.js with: ' + url);
async function playWithMpegTS(url, isLive = true) {
log('Trying mpegts.js with: ' + url + ' (isLive: ' + isLive + ')');
showLoading('Loading MPEG-TS stream...');
if (!mpegts.isSupported()) {
@@ -252,17 +252,21 @@
mpegts.getLoggingControl().enableError = true;
}
// Configure player differently for VOD vs Live
const playerConfig = {
enableWorker: true,
enableStashBuffer: !isLive, // Enable for VOD, disable for live
stashInitialSize: isLive ? 384 * 1024 : 512 * 1024,
autoCleanupSourceBuffer: true,
fixAudioTimestampGap: isLive, // Only for live streams
liveBufferLatencyChasing: isLive, // Disable for VOD
};
const player = mpegts.createPlayer({
type: 'mpegts',
isLive: true,
isLive: isLive, // Use parameter to enable/disable seeking
url: url,
}, {
enableWorker: true,
enableStashBuffer: true,
stashInitialSize: 384 * 1024,
autoCleanupSourceBuffer: true,
fixAudioTimestampGap: true
});
}, playerConfig);
player.attachMediaElement(video);
player.load();
@@ -357,6 +361,16 @@
log('Stream type: ' + streamType);
const lowerUrl = streamUrl.toLowerCase();
// SPECIAL: /api/stream/ endpoint outputs MPEG-TS, use mpegts.js directly
if (streamUrl.includes('/api/stream/')) {
log('Detected /api/stream/ endpoint - using MPEG-TS player for transcoded stream');
showLoading('Initializing stream (transcoding audio)...');
// For VOD, use isLive:false to enable seeking/duration
const isVodStream = (streamType === 'vod');
await playWithMpegTS(streamUrl, !isVodStream); // true for live, false for vod
return;
}
// Use type parameter if available, otherwise detect from URL
if (streamType === 'vod') {
// VOD content - use direct HTML5 playback