Added experimental force remux setting to remux raw ts streams to mp4 container
This commit is contained in:
@@ -365,6 +365,17 @@
|
||||
but no audio (fixes Dolby/AC3/EAC3). Requires ffmpeg-static.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label class="setting-toggle">
|
||||
<input type="checkbox" id="setting-force-remux">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
<div class="setting-info">
|
||||
<span class="setting-label">Force Remux</span>
|
||||
<span class="setting-hint">Remux streams to MP4 container (no re-encoding). Enable for raw .ts streams
|
||||
from IPTV middleware like m3u-editor or dispatcharr. Very lightweight.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="setting-info" style="flex: 1;">
|
||||
<span class="setting-label">Stream Output Format</span>
|
||||
|
||||
@@ -34,7 +34,8 @@ class VideoPlayer {
|
||||
lastVolume: 80, // Last used volume (if rememberVolume is true)
|
||||
autoPlayNextEpisode: false, // Auto-play next episode in series
|
||||
forceProxy: false, // Force all streams through backend proxy
|
||||
forceTranscode: false // Force audio transcoding (fixes Dolby/AC3 audio)
|
||||
forceTranscode: false, // Force audio transcoding (fixes Dolby/AC3 audio)
|
||||
forceRemux: false // Force remux to MP4 (fixes raw .ts streams, lightweight)
|
||||
};
|
||||
try {
|
||||
const saved = localStorage.getItem('nodecast_tv_player_settings');
|
||||
@@ -263,9 +264,40 @@ class VideoPlayer {
|
||||
const finalUrl = needsProxy ? this.getProxiedUrl(streamUrl) : streamUrl;
|
||||
|
||||
// Detect if this is likely an HLS stream (vs direct video file like MP4)
|
||||
// Note: .ts files are raw MPEG-TS, NOT HLS manifests - exclude them
|
||||
const looksLikeHls = finalUrl.includes('.m3u8') ||
|
||||
finalUrl.includes('m3u8') ||
|
||||
(!finalUrl.includes('.mp4') && !finalUrl.includes('.mkv') && !finalUrl.includes('.avi'));
|
||||
(!finalUrl.includes('.mp4') && !finalUrl.includes('.mkv') &&
|
||||
!finalUrl.includes('.avi') && !finalUrl.includes('.ts'));
|
||||
|
||||
// Check for raw TS streams that browsers can't play directly
|
||||
const isRawTs = finalUrl.includes('.ts') && !finalUrl.includes('.m3u8');
|
||||
if (isRawTs) {
|
||||
// If Force Remux is enabled, route through remux endpoint
|
||||
if (this.settings.forceRemux) {
|
||||
console.log('[Player] Raw TS stream detected. Using remux to convert to MP4...');
|
||||
const remuxUrl = this.getRemuxUrl(streamUrl);
|
||||
this.video.src = remuxUrl;
|
||||
this.video.play().catch(e => console.log('[Player] Autoplay prevented:', e));
|
||||
|
||||
// Update UI and dispatch events
|
||||
this.updateNowPlaying(channel);
|
||||
this.showNowPlayingOverlay();
|
||||
this.fetchEpgData(channel);
|
||||
window.dispatchEvent(new CustomEvent('channelChanged', { detail: channel }));
|
||||
return;
|
||||
}
|
||||
|
||||
console.warn('[Player] Raw MPEG-TS stream detected. Browsers cannot play .ts files directly.');
|
||||
this.showError(
|
||||
'This stream uses raw MPEG-TS format (.ts) which browsers cannot play directly.<br><br>' +
|
||||
'<strong>To fix this:</strong><br>' +
|
||||
'1. Enable <strong>"Force Remux"</strong> in Settings → Streaming (lightweight)<br>' +
|
||||
'2. Or enable <strong>"Force Audio Transcode"</strong> if you also have audio issues<br>' +
|
||||
'3. Or configure your source to output HLS (.m3u8) format'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Priority 1: Use HLS.js for HLS streams on browsers that support it
|
||||
if (looksLikeHls && Hls.isSupported()) {
|
||||
@@ -465,6 +497,14 @@ class VideoPlayer {
|
||||
return `/api/transcode?url=${encodeURIComponent(url)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remuxed URL for a stream (container conversion only, no re-encoding)
|
||||
* Used for raw .ts streams that browsers can't play directly
|
||||
*/
|
||||
getRemuxUrl(url) {
|
||||
return `/api/remux?url=${encodeURIComponent(url)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode base64 EPG data
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@ class SettingsPage {
|
||||
const autoPlayNextToggle = document.getElementById('setting-autoplay-next');
|
||||
const forceProxyToggle = document.getElementById('setting-force-proxy');
|
||||
const forceTranscodeToggle = document.getElementById('setting-force-transcode');
|
||||
const forceRemuxToggle = document.getElementById('setting-force-remux');
|
||||
|
||||
// Load current settings
|
||||
if (this.app.player?.settings) {
|
||||
@@ -45,6 +46,9 @@ class SettingsPage {
|
||||
if (forceTranscodeToggle) {
|
||||
forceTranscodeToggle.checked = this.app.player.settings.forceTranscode || false;
|
||||
}
|
||||
if (forceRemuxToggle) {
|
||||
forceRemuxToggle.checked = this.app.player.settings.forceRemux || false;
|
||||
}
|
||||
}
|
||||
|
||||
// Arrow keys toggle
|
||||
@@ -93,6 +97,12 @@ class SettingsPage {
|
||||
this.app.player.saveSettings();
|
||||
});
|
||||
|
||||
// Force remux toggle
|
||||
forceRemuxToggle?.addEventListener('change', () => {
|
||||
this.app.player.settings.forceRemux = forceRemuxToggle.checked;
|
||||
this.app.player.saveSettings();
|
||||
});
|
||||
|
||||
// EPG refresh interval
|
||||
const epgRefreshSelect = document.getElementById('epg-refresh-interval');
|
||||
if (epgRefreshSelect) {
|
||||
|
||||
Reference in New Issue
Block a user