diff --git a/public/index.html b/public/index.html
index a7df279..fad8a46 100644
--- a/public/index.html
+++ b/public/index.html
@@ -309,6 +309,17 @@
directly.
+
+
+ Stream Output Format
+ Container format for Xtream streams. Try TS if you experience buffering
+ issues.
+
+
+
diff --git a/public/js/components/ChannelList.js b/public/js/components/ChannelList.js
index 063ee7e..143af70 100644
--- a/public/js/components/ChannelList.js
+++ b/public/js/components/ChannelList.js
@@ -216,13 +216,25 @@ class ChannelList {
groupedChannels['Favorites'] = favoritedChannels;
}
- // 4. Sort Groups
- this.sortedGroups = Object.keys(groupedChannels).sort((a, b) => {
+ // 4. Sort Groups and filter to only those with visible channels
+ const allGroups = Object.keys(groupedChannels).sort((a, b) => {
if (a === 'Favorites') return -1;
if (b === 'Favorites') return 1;
return a.localeCompare(b);
});
+ // Pre-filter to only include groups with visible channels (so hidden groups don't consume batch slots)
+ this.sortedGroups = allGroups.filter(groupName => {
+ if (groupName === 'Favorites') return true;
+ const channels = groupedChannels[groupName];
+ // Check if any channel in this group is visible
+ return channels.some(channel => {
+ const rawChannelId = channel.streamId || channel.id;
+ const isHidden = this.isHidden('channel', channel.sourceId, rawChannelId);
+ return !isHidden || showHidden;
+ });
+ });
+
this.groupedChannels = groupedChannels;
this.showHidden = showHidden;
@@ -819,7 +831,8 @@ class ChannelList {
// Get stream URL
let streamUrl;
if (channel.sourceType === 'xtream') {
- const result = await API.proxy.xtream.getStreamUrl(channel.sourceId, channel.streamId, 'live');
+ const streamFormat = localStorage.getItem('nodecast_tv_stream_format') || 'm3u8';
+ const result = await API.proxy.xtream.getStreamUrl(channel.sourceId, channel.streamId, 'live', streamFormat);
streamUrl = result.url;
} else {
streamUrl = channel.url;
diff --git a/public/js/pages/Settings.js b/public/js/pages/Settings.js
index 2ced51d..18dc27b 100644
--- a/public/js/pages/Settings.js
+++ b/public/js/pages/Settings.js
@@ -97,6 +97,19 @@ class SettingsPage {
localStorage.setItem('nodecast_tv_epg_refresh_interval', epgRefreshSelect.value);
});
}
+
+ // Stream output format
+ const streamFormatSelect = document.getElementById('setting-stream-format');
+ if (streamFormatSelect) {
+ // Load saved value
+ const savedFormat = localStorage.getItem('nodecast_tv_stream_format') || 'm3u8';
+ streamFormatSelect.value = savedFormat;
+
+ // Save on change
+ streamFormatSelect.addEventListener('change', () => {
+ localStorage.setItem('nodecast_tv_stream_format', streamFormatSelect.value);
+ });
+ }
}
switchTab(tabName) {