From 14c54b60f159a0c5fa18d4ec877f559fb276102c Mon Sep 17 00:00:00 2001 From: nemes Date: Fri, 29 May 2026 13:20:35 +0200 Subject: [PATCH] fix(frontend): apply output_profile and output_format in all live stream player calls getShowVideoUrl was building raw proxy URLs without calling buildLiveStreamUrl, so the web-player output profile preference stored in localStorage was silently ignored when starting a live stream from the TV Guide, Program Detail modal, DVR page, Recording Details modal, and Recording Card. Fix: import buildLiveStreamUrl in RecordingCardUtils and call it at the end of getShowVideoUrl so every caller inherits the correct output_format=mpegts param and any configured output_profile automatically. Fixes #1304 --- .../src/utils/cards/RecordingCardUtils.js | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/frontend/src/utils/cards/RecordingCardUtils.js b/frontend/src/utils/cards/RecordingCardUtils.js index 4920c8ba..68b0b3ce 100644 --- a/frontend/src/utils/cards/RecordingCardUtils.js +++ b/frontend/src/utils/cards/RecordingCardUtils.js @@ -1,30 +1,24 @@ -import API from '../../api.js'; -import useChannelsStore from '../../store/channels.jsx'; -import defaultLogo from '../../images/logo.png'; -import { formatSeasonEpisode } from '../guideUtils.js'; +import API from "../../api.js"; +import useChannelsStore from "../../store/channels.jsx"; +import defaultLogo from "../../images/logo.png"; +import { formatSeasonEpisode } from "../guideUtils.js"; +import { buildLiveStreamUrl } from "../components/FloatingVideoUtils.js"; export const removeRecording = (id) => { - // Optimistically remove immediately from UI try { useChannelsStore.getState().removeRecording(id); } catch (error) { - console.error('Failed to optimistically remove recording', error); + console.error("Failed to optimistically remove recording", error); } - // Fire-and-forget server delete; websocket will keep others in sync API.deleteRecording(id).catch(() => { - // On failure, fallback to refetch to restore state try { useChannelsStore.getState().fetchRecordings(); } catch (error) { - console.error('Failed to refresh recordings after delete', error); + console.error("Failed to refresh recordings after delete", error); } }); }; -/** - * Resolve the channel logo cache URL from either a full channel object - * (has logo.cache_url) or a summary object (has logo_id integer). - */ export const getChannelLogoUrl = (channel) => { if (!channel) return null; let url = channel.logo_id @@ -32,8 +26,8 @@ export const getChannelLogoUrl = (channel) => { : channel.logo?.cache_url || null; if ( url && - url.startsWith('/') && - typeof import.meta !== 'undefined' && + url.startsWith("/") && + typeof import.meta !== "undefined" && import.meta.env && import.meta.env.DEV ) { @@ -48,10 +42,10 @@ export const getPosterUrl = (posterLogoId, customProperties, posterUrl) => { : customProperties?.poster_url || posterUrl || null; if ( purl && - typeof import.meta !== 'undefined' && + typeof import.meta !== "undefined" && import.meta.env && import.meta.env.DEV && - purl.startsWith('/') + purl.startsWith("/") ) { purl = `${window.location.protocol}//${window.location.hostname}:5656${purl}`; } @@ -60,10 +54,10 @@ export const getPosterUrl = (posterLogoId, customProperties, posterUrl) => { export const getShowVideoUrl = (channel, env_mode) => { let url = `/proxy/ts/stream/${channel.uuid}`; - if (env_mode === 'dev') { + if (env_mode === "dev") { url = `${window.location.protocol}//${window.location.hostname}:5656${url}`; } - return url; + return buildLiveStreamUrl(url); }; export const runComSkip = async (recording) => { @@ -86,23 +80,23 @@ export const deleteSeriesAndRule = async (seriesInfo) => { const { tvg_id, title } = seriesInfo; try { await API.bulkRemoveSeriesRecordings({ - tvg_id: tvg_id || '', + tvg_id: tvg_id || "", title, - scope: 'title', + scope: "title", }); } catch (error) { - console.error('Failed to remove series recordings', error); + console.error("Failed to remove series recordings", error); } try { await API.deleteSeriesRule(tvg_id, title); } catch (error) { - console.error('Failed to delete series rule', error); + console.error("Failed to delete series rule", error); } }; export const getRecordingUrl = (customProps, env_mode) => { let fileUrl = customProps?.file_url || customProps?.output_file_url; - if (fileUrl && env_mode === 'dev' && fileUrl.startsWith('/')) { + if (fileUrl && env_mode === "dev" && fileUrl.startsWith("/")) { fileUrl = `${window.location.protocol}//${window.location.hostname}:5656${fileUrl}`; } return fileUrl;