[PR #2194] Direct radio streaming #2134

Open
opened 2026-02-26 03:33:22 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/koel/koel/pull/2194
Author: @pwqw
Created: 1/10/2026
Status: 🔄 Open

Base: masterHead: master


📝 Commits (4)

  • 243ee55 feat: enhance queue state saving to include episodes and filter out deleted songs
  • 5453337 feat: implement direct radio streaming with CORS handling and enhance validation for radio station URLs
  • dce0d59 feat(csp): Add dynamic stream host whitelisting for radio stations
  • 0b3839f fix(csp): enhance stream host caching with error handling

📊 Changes

18 files changed (+777 additions, -45 deletions)

View changed files

📝 app/Http/Controllers/StreamRadioController.php (+74 -2)
app/Http/Middleware/ContentSecurityPolicy.php (+67 -0)
📝 app/Models/RadioStation.php (+1 -0)
📝 app/Observers/RadioStationObserver.php (+47 -0)
📝 app/Rules/ValidRadioStationUrl.php (+128 -3)
database/migrations/2026_01_19_122025_add_stream_host_to_radio_stations_table.php (+44 -0)
📝 resources/assets/js/App.vue (+12 -2)
📝 resources/assets/js/components/layout/app-footer/AudioPlayer.vue (+5 -1)
📝 resources/assets/js/components/layout/app-footer/FooterExtraControls.vue (+10 -4)
📝 resources/assets/js/components/layout/app-footer/index.vue (+6 -7)
📝 resources/assets/js/components/radio/RadioStationCard.vue (+7 -3)
📝 resources/assets/js/services/QueuePlaybackService.ts (+29 -0)
📝 resources/assets/js/services/RadioPlaybackService.ts (+174 -7)
📝 resources/assets/js/services/audioService.ts (+49 -0)
📝 resources/assets/js/stores/queueStore.ts (+30 -5)
📝 resources/assets/js/stores/radioStationStore.spec.ts (+5 -4)
📝 resources/assets/js/stores/radioStationStore.ts (+3 -1)
📝 tests/Unit/Rules/ValidRadioStationUrlTest.php (+86 -6)

📄 Description

Description

Initially, I tried adding a simple radio "icecast" and it returned an "invalid URL" error.

After modifying the validation, I discovered that the radio station playback needed to be proxyed with PHP to work, so I was forced to use a plain <audio> element. This meant the equalizer functionality was disabled during radio station playback.

Finally, while testing it, I had to adjust some details in the queuing and instantiation of the audio elements.

Motivation

It seemed likely to me that the radio station could play almost any streaming service directly from the client without consuming server resources.

Implementation

While it was thoroughly tested and, in my case, works as expected... I'm certainly not 100% sure about this implementation and I hope I'm not taking up any more of your time.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/koel/koel/pull/2194 **Author:** [@pwqw](https://github.com/pwqw) **Created:** 1/10/2026 **Status:** 🔄 Open **Base:** `master` ← **Head:** `master` --- ### 📝 Commits (4) - [`243ee55`](https://github.com/koel/koel/commit/243ee55f8c47302056a5480971bce36bcbfe3378) feat: enhance queue state saving to include episodes and filter out deleted songs - [`5453337`](https://github.com/koel/koel/commit/54533370e04fa3335a662ef8e28c5103f5c7e400) feat: implement direct radio streaming with CORS handling and enhance validation for radio station URLs - [`dce0d59`](https://github.com/koel/koel/commit/dce0d59936d57e9fd4899c5179296eef51b82ce9) feat(csp): Add dynamic stream host whitelisting for radio stations - [`0b3839f`](https://github.com/koel/koel/commit/0b3839fe0cf722f98077576239083c043350a42f) fix(csp): enhance stream host caching with error handling ### 📊 Changes **18 files changed** (+777 additions, -45 deletions) <details> <summary>View changed files</summary> 📝 `app/Http/Controllers/StreamRadioController.php` (+74 -2) ➕ `app/Http/Middleware/ContentSecurityPolicy.php` (+67 -0) 📝 `app/Models/RadioStation.php` (+1 -0) 📝 `app/Observers/RadioStationObserver.php` (+47 -0) 📝 `app/Rules/ValidRadioStationUrl.php` (+128 -3) ➕ `database/migrations/2026_01_19_122025_add_stream_host_to_radio_stations_table.php` (+44 -0) 📝 `resources/assets/js/App.vue` (+12 -2) 📝 `resources/assets/js/components/layout/app-footer/AudioPlayer.vue` (+5 -1) 📝 `resources/assets/js/components/layout/app-footer/FooterExtraControls.vue` (+10 -4) 📝 `resources/assets/js/components/layout/app-footer/index.vue` (+6 -7) 📝 `resources/assets/js/components/radio/RadioStationCard.vue` (+7 -3) 📝 `resources/assets/js/services/QueuePlaybackService.ts` (+29 -0) 📝 `resources/assets/js/services/RadioPlaybackService.ts` (+174 -7) 📝 `resources/assets/js/services/audioService.ts` (+49 -0) 📝 `resources/assets/js/stores/queueStore.ts` (+30 -5) 📝 `resources/assets/js/stores/radioStationStore.spec.ts` (+5 -4) 📝 `resources/assets/js/stores/radioStationStore.ts` (+3 -1) 📝 `tests/Unit/Rules/ValidRadioStationUrlTest.php` (+86 -6) </details> ### 📄 Description <!-- Thank you for contributing to Koel! Please provide a clear description of your changes below. --> ## Description Initially, I tried adding a simple radio "icecast" and it returned an "invalid URL" error. After modifying the validation, I discovered that the radio station playback needed to be proxyed with PHP to work, so I was forced to use a plain `<audio>` element. This meant the equalizer functionality was disabled during radio station playback. Finally, while testing it, I had to adjust some details in the queuing and instantiation of the audio elements. ## Motivation It seemed likely to me that the radio station could play almost any streaming service directly from the client without consuming server resources. ## Implementation While it was thoroughly tested and, in my case, works as expected... I'm certainly not 100% sure about this implementation and I hope I'm not taking up any more of your time. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/koel-koel#2134
No description provided.