![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/public_html/radio/ |
# How the Live Radio Player Works
## 🎯 Overview
The live radio system has **two main components**:
1. **B2B Platform** (`/radio/`) - For radio stations to manage music licensing
2. **B2C Live Player** (`/radio/live.php`) - For listeners to tune in and vote
---
## 📊 System Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ RADIO STATION DASHBOARD │
│ /radio/dashboard/live_stream.php │
│ │
│ • Start/Stop Streams │
│ • View Now Playing │
│ • Manage Queue │
│ • Play Tracks │
└──────────────────────┬──────────────────────────────────────┘
│
│ API Calls
▼
┌─────────────────────────────────────────────────────────────┐
│ RADIO API v1 │
│ /radio/api/v1/stream/* │
│ │
│ POST /stream/start - Start live stream │
│ POST /stream/stop - Stop live stream │
│ POST /stream/now_playing - Update current track │
│ GET /stream/status - Get stream status │
│ GET /stream/queue - Get queue │
└──────────────────────┬──────────────────────────────────────┘
│
│ Database Updates
▼
┌─────────────────────────────────────────────────────────────┐
│ DATABASE TABLES │
│ │
│ radio_streams - Stream sessions │
│ radio_now_playing - Current track info │
│ radio_stream_queue - Upcoming tracks │
│ radio_votes - Listener votes │
│ radio_listeners - Active listeners │
└──────────────────────┬──────────────────────────────────────┘
│
│ Real-time Updates
▼
┌─────────────────────────────────────────────────────────────┐
│ PUBLIC LIVE PLAYER │
│ /radio/live.php │
│ │
│ • Display Now Playing │
│ • Show Listener Count │
│ • Voting Interface │
│ • Real-time Updates (SSE) │
└─────────────────────────────────────────────────────────────┘
```
---
## 🔄 How It Works - Step by Step
### 1. **Station Sets Up Stream**
**Station Dashboard** (`/radio/dashboard/live_stream.php`):
- Station logs into their dashboard
- Clicks "Start Stream"
- Enters stream name (optional: stream URL)
- System creates a `radio_streams` record with `is_live = TRUE`
**What Happens:**
```php
// API Call: POST /radio/api/v1/stream/start
{
"stream_name": "My Station Live",
"stream_url": "https://stream.example.com/live" // optional
}
// Creates record in radio_streams table:
// - station_id: Links to radio_stations table
// - is_live: TRUE
// - started_at: Current timestamp
```
---
### 2. **Station Plays a Track**
**Station Dashboard or API:**
- Station selects a track to play
- Calls API: `POST /radio/api/v1/stream/now_playing`
- System updates the database
**What Happens:**
```php
// 1. Ends previous track (if any)
UPDATE radio_now_playing
SET ended_at = NOW()
WHERE stream_id = ? AND ended_at IS NULL
// 2. Creates new now_playing record
INSERT INTO radio_now_playing (stream_id, track_id, started_at)
VALUES (?, ?, NOW())
// 3. Updates stream's current_track_id
UPDATE radio_streams
SET current_track_id = ?
WHERE id = ?
// 4. Logs the play (for compliance)
INSERT INTO radio_play_logs (...)
```
---
### 3. **Listeners Visit Live Player**
**Public Page** (`/radio/live.php`):
- Anyone can visit `/radio/live.php`
- Page automatically finds the first active stream
- Or: `/radio/live.php?station=123` for specific station
**What Happens:**
```php
// 1. Query for active stream
SELECT rs.*, rstr.*
FROM radio_stations rs
LEFT JOIN radio_streams rstr ON rs.id = rstr.station_id
WHERE rstr.is_live = 1
ORDER BY rstr.listener_count DESC
LIMIT 1
// 2. Get current track
SELECT np.*, mt.title, mt.audio_url, u.name as artist_name
FROM radio_now_playing np
JOIN music_tracks mt ON np.track_id = mt.id
LEFT JOIN users u ON mt.user_id = u.id
WHERE np.stream_id = ? AND np.ended_at IS NULL
// 3. Get queue (upcoming tracks)
SELECT q.*, mt.title, mt.audio_url
FROM radio_stream_queue q
JOIN music_tracks mt ON q.track_id = mt.id
WHERE q.stream_id = ? AND q.played_at IS NULL
ORDER BY q.vote_count DESC
```
---
### 4. **Real-Time Updates (Server-Sent Events)**
**SSE Endpoint** (`/radio/api/live/stream.php`):
- Browser opens SSE connection
- Server sends updates every second
**What Gets Updated:**
```javascript
// Listener connects
const eventSource = new EventSource('/radio/api/live/stream.php?stream_id=123');
// Receives updates:
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
// Update listener count
if (data.type === 'listener_count') {
document.getElementById('listener-count').textContent = data.count;
}
// Track changed
if (data.type === 'now_playing') {
// Reload page or update UI
location.reload();
}
// Vote count changed
if (data.type === 'vote_update') {
document.getElementById('votes-' + data.track_id).textContent =
data.vote_count + ' votes';
}
};
```
**Server-Side (SSE):**
```php
// Every 1 second, check for changes:
while (true) {
// Check listener count
$listener_count = getListenerCount($stream_id);
if ($listener_count != $last_count) {
echo "data: " . json_encode(['type' => 'listener_count', 'count' => $listener_count]) . "\n\n";
flush();
}
// Check if track changed
$current_track = getCurrentTrack($stream_id);
if ($current_track != $last_track) {
echo "data: " . json_encode(['type' => 'now_playing', 'track' => $current_track]) . "\n\n";
flush();
}
sleep(1);
}
```
---
### 5. **Listener Voting System**
**Voting Flow:**
1. Listener sees upcoming tracks in queue
2. Clicks "Vote" button
3. JavaScript calls: `POST /radio/api/live/vote.php`
**What Happens:**
```php
// 1. Check if already voted (prevent duplicates)
SELECT id FROM radio_votes
WHERE stream_id = ? AND track_id = ?
AND (user_session = ? OR user_ip = ?)
AND voted_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)
// 2. Record vote
INSERT INTO radio_votes (stream_id, track_id, user_session, user_ip)
VALUES (?, ?, ?, ?)
// 3. Update queue vote count
UPDATE radio_stream_queue
SET vote_count = vote_count + 1
WHERE stream_id = ? AND track_id = ?
// 4. Queue is sorted by: priority DESC, vote_count DESC, queued_at ASC
```
**Queue Priority:**
- Tracks with more votes play first
- Station can manually set priority
- Older tracks in queue get slight preference
---
### 6. **Listener Tracking**
**Connection Tracking:**
```javascript
// When page loads
fetch('/radio/api/live/listener.php', {
method: 'POST',
body: JSON.stringify({
stream_id: 123,
action: 'connect'
})
});
// When page closes
window.addEventListener('beforeunload', () => {
navigator.sendBeacon('/radio/api/live/listener.php', JSON.stringify({
stream_id: 123,
action: 'disconnect'
}));
});
```
**Database:**
```php
// Record listener connection
INSERT INTO radio_listeners (stream_id, user_session, user_ip, connected_at)
VALUES (?, ?, ?, NOW())
// Update listener count
UPDATE radio_streams
SET listener_count = (
SELECT COUNT(*) FROM radio_listeners
WHERE stream_id = ?
AND disconnected_at IS NULL
AND last_seen > DATE_SUB(NOW(), INTERVAL 5 MINUTE)
)
```
---
## 🔗 Integration with `/radio` System
### **B2B Features (Existing)**
- **Music Catalog** - Stations browse licensed tracks
- **Playlists** - Create and manage playlists
- **Play Logging** - Track all plays for compliance
- **Analytics** - View play statistics
- **API Access** - Integrate with broadcast software
### **B2C Features (New)**
- **Live Streaming** - Public-facing radio player
- **Real-Time Updates** - SSE for live data
- **Voting** - Listeners influence playlist
- **Listener Stats** - Real-time count
### **How They Connect:**
1. **Stations use B2B dashboard** to:
- Start streams
- Select tracks to play
- View queue and votes
- Manage their live broadcast
2. **Listeners use B2C player** to:
- Listen to live stream
- See what's playing
- Vote for next tracks
- See listener count
3. **System connects them:**
- Station actions update database
- Database changes trigger SSE updates
- Listeners see updates in real-time
- Votes from listeners appear in station dashboard
---
## 📡 API Integration Example
**Broadcast Software Integration:**
```php
// When your broadcast software plays a track:
// 1. Log the play (existing API)
POST /radio/api/v1/plays
{
"track_id": 123,
"played_at": "2025-01-15T10:30:00Z",
"duration_played": 180,
"play_type": "full"
}
// 2. Update now playing (new API)
POST /radio/api/v1/stream/now_playing
{
"track_id": 123
}
// This automatically:
// - Updates the live player
// - Logs the play for compliance
// - Updates listener displays
```
---
## 🎵 Complete Flow Example
**Scenario: Station plays a song**
1. **Station Dashboard:**
- DJ clicks "Play Now" on track #456
- Calls: `POST /radio/api/v1/stream/now_playing` with `track_id: 456`
2. **Backend:**
- Updates `radio_now_playing` table
- Sets `radio_streams.current_track_id = 456`
- Logs play in `radio_play_logs`
3. **SSE Server:**
- Detects track change
- Sends update to all connected listeners
4. **Live Player:**
- Receives SSE update
- Updates "Now Playing" display
- Shows new track title, artist, artwork
- Updates audio player (if track has audio_url)
5. **Listeners:**
- See new track instantly
- Can vote for next track
- Listener count updates in real-time
---
## 🔧 Key Files
| File | Purpose |
|------|---------|
| `/radio/live.php` | Public-facing live player |
| `/radio/dashboard/live_stream.php` | Station stream management |
| `/radio/api/live/stream.php` | SSE endpoint for real-time updates |
| `/radio/api/live/vote.php` | Handle listener votes |
| `/radio/api/live/listener.php` | Track listener connections |
| `/radio/api/v1/stream/*` | Station API endpoints |
| `/radio/migrations/add_live_streaming_tables.php` | Database setup |
---
## 💡 Key Features
✅ **Real-Time Updates** - No page refresh needed
✅ **Voting System** - Listeners influence playlist
✅ **Listener Tracking** - Real-time count
✅ **Queue Management** - Prioritized by votes
✅ **API Integration** - Works with broadcast software
✅ **Compliance** - All plays logged automatically
---
## 🚀 Getting Started
1. **Run Migration:**
```
/radio/migrations/add_live_streaming_tables.php
```
2. **Station Starts Stream:**
- Login to `/radio/dashboard/`
- Go to "Live Stream" section
- Click "Start Stream"
3. **Station Plays Track:**
- Use dashboard or API
- Select track to play
- System updates live player automatically
4. **Listeners Tune In:**
- Visit `/radio/live.php`
- See current track
- Vote for next tracks
- Real-time updates happen automatically
---
This creates a complete **B2B + B2C hybrid platform** where stations manage their broadcast and listeners interact in real-time! 🎉