From 5cf17f881aca10037659478777da6cae3a9a38c2 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Mon, 13 Oct 2025 10:11:33 +0300 Subject: [PATCH] fix: cache bust radio streams on play --- lib/Controller/RadioController.php | 12 +++++++++--- src/composables/usePlayback.ts | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Controller/RadioController.php b/lib/Controller/RadioController.php index 539ce17..27ba1bf 100644 --- a/lib/Controller/RadioController.php +++ b/lib/Controller/RadioController.php @@ -364,12 +364,16 @@ class RadioController extends OCSController { } try { - $stream = @fopen($streamUrl, 'rb'); + // Add cache-busting to the stream URL to prevent server-side caching + $separator = strpos($streamUrl, '?') !== false ? '&' : '?'; + $cacheBustedUrl = $streamUrl . $separator . '_t=' . time(); + + $stream = @fopen($cacheBustedUrl, 'rb'); if (!$stream) { throw new \RuntimeException('Unable to open stream'); } - $headers = @get_headers($streamUrl, true); + $headers = @get_headers($cacheBustedUrl, true); $contentType = is_array($headers) && isset($headers['Content-Type']) ? (is_array($headers['Content-Type']) ? $headers['Content-Type'][0] : $headers['Content-Type']) : 'audio/mpeg'; @@ -379,8 +383,10 @@ class RadioController extends OCSController { Http::STATUS_OK, [ 'Content-Type' => $contentType, - 'Cache-Control' => 'no-store, must-revalidate', + 'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0', 'Pragma' => 'no-cache', + 'Expires' => '0', + 'X-Accel-Buffering' => 'no', 'Content-Transfer-Encoding' => 'binary', ] ); diff --git a/src/composables/usePlayback.ts b/src/composables/usePlayback.ts index 3896147..856a6fd 100644 --- a/src/composables/usePlayback.ts +++ b/src/composables/usePlayback.ts @@ -65,7 +65,15 @@ function getStreamUrl(media: Playable): string { if (!pathResolver) { throw new Error(`Unsupported media type: ${media.type}`) } - return axios.defaults.baseURL + pathResolver(media) + const baseUrl = axios.defaults.baseURL + pathResolver(media) + + // Add cache-busting for radio streams to ensure fresh content + if (media.type === 'radio') { + const separator = baseUrl.includes('?') ? '&' : '?' + return `${baseUrl}${separator}_t=${Date.now()}` + } + + return baseUrl } function trackAction(media: Playable, action: 'play' | 'pause' | 'complete' | 'resume') { @@ -133,7 +141,9 @@ async function playMedia(media: Playable) { const src = getStreamUrl(media) - if (audio.src !== src) { + // For radio streams, always reload to get fresh content + // For other media types, only reload if the source changed + if (audio.src !== src || media.type === 'radio') { audio.pause() resumePosition.value = await getStartPosition(media) audio.src = src