A simple PHP client for fetching radio stream metadata and searching music tracks across streaming platforms.
composer require joeyboli/radioapisdk:dev-main
use RadioAPI\RadioAPI;
$api = new RadioAPI();
$api->setBaseUrl('https://api.example.com')
->setApiKey('your-api-key');
$metadata = $api->streamTitle()
->setStreamUrl('https://stream.example.com/radio')
->fetchArray();
echo "{$metadata['artist']} - {$metadata['song']}";
[
'name' => 'Hunter.FM - O Canal K-pop',
'bitrate' => 256,
'format' => 'AAC',
'elapsed' => 143,
'artist' => 'RESCENE',
'song' => 'LOVE ATTACK',
'metadataFound' => true,
'history' => [
[
'artist' => 'NewJeans',
'song' => 'OMG',
'timestamp' => '2025-10-12 11:44:06.353021',
'relative_time' => '5 hours ago'
]
]
]
[
'name' => 'Hunter.FM - O Canal K-pop',
'bitrate' => 0,
'format' => 'AAC',
'artist' => 'RESCENE',
'song' => 'LOVE ATTACK',
'album' => 'SCENEDROME',
'genre' => 'Asiatische Musik',
'artwork' => 'https://icdn2.streamafrica.net/stacks/e24820c67fecb4c0.jpg',
'year' => 2024,
'duration' => 181,
'elapsed' => 111,
'remaining' => 70,
'time' => '03:01',
'stream' => 'https://song.link/d/2966352091',
'explicit' => false,
'songinfoFound' => true,
'metadataFound' => true,
'history' => [
[
'artist' => 'ENHYPEN',
'song' => 'Bite Me',
'timestamp' => '2025-10-12 16:39:25.868785',
'relative_time' => '4 minutes ago',
'artwork' => 'https://icdn2.streamafrica.net/stacks/6a615f61aac53844.jpg'
],
// ... more history items
]
]
[
'artist' => 'SKKST',
'title' => 'Dance With My Hands',
'album' => 'Dance With My Hands',
'genre' => 'Dance',
'artwork' => [
'small' => 'https://cdn-images.dzcdn.net/images/cover/.../56x56-000000-80-0-0.jpg',
'medium' => 'https://cdn-images.dzcdn.net/images/cover/.../250x250-000000-80-0-0.jpg',
'large' => 'https://cdn-images.dzcdn.net/images/cover/.../500x500-000000-80-0-0.jpg',
'xl' => 'https://cdn-images.dzcdn.net/images/cover/.../1000x1000-000000-80-0-0.jpg'
],
'artist_artwork' => 'https://cdn-images.dzcdn.net/images/artist/.../1000x1000-000000-80-0-0.jpg',
'duration' => 124,
'stream' => 'https://www.deezer.com/track/2109711027',
'explicit' => false,
'year' => 2023
]
The most common use case is grabbing what's currently playing on a radio stream:
$stream = $api->streamTitle();
$stream->setStreamUrl('https://stream.example.com/radio');
$data = $stream->fetchArray();
if ($stream->hasMetadata()) {
echo $data['song'];
echo $data['artist'];
echo $data['album'];
}
Need to search for a track? Here's how:
$result = $api->musicSearch()
->search('Radiohead Creep')
->fetchArray();
echo "{$result['artist']} - {$result['title']}\n";
echo "Album: {$result['album']}\n";
echo "Stream: {$result['stream']}\n";
Want metadata from Spotify, Deezer, or other services? Just set a mount point:
// Spotify
$api->withService(RadioAPI::SPOTIFY);
// Deezer
$api->withService(RadioAPI::DEEZER);
// Apple Music
$api->withService(RadioAPI::APPLE_MUSIC);
// YouTube Music
$api->withService(RadioAPI::YOUTUBE_MUSIC);
Full example:
$spotify = $api->withService(RadioAPI::SPOTIFY)
->streamTitle()
->setStreamUrl('https://stream.example.com/radio')
->fetchArray();
// Now you have Spotify-specific data
$trackId = $spotify['spotify']['id'];
$spotifyUrl = $spotify['spotify']['external_urls']['spotify'];
For radio platforms like AzuraCast and Live365, use their specific mount points with the correct URL format:
AzuraCast:
$api->withService(RadioAPI::AZURACAST)
->streamTitle()
->setStreamUrl('https://azuracast.example.com/listen/stationid/mountpoint')
->fetchArray();
Live365:
$api->withService(RadioAPI::LIVE365)
->streamTitle()
->setStreamUrl('https://streaming.live365.com/mountid')
->fetchArray();
For StreamTitle and MusicSearch:
RadioAPI::SPOTIFY
- SpotifyRadioAPI::DEEZER
- DeezerRadioAPI::APPLE_MUSIC
- Apple Music (iTunes)RadioAPI::YOUTUBE_MUSIC
- YouTube MusicRadioAPI::FLO_MUSIC
- FLO MusicRadioAPI::LINE_MUSIC
- LINE MusicRadioAPI::AUTO
- Auto-detect
For StreamTitle only:
RadioAPI::AZURACAST
- AzuraCast (use withhttps://azuracast.example.com/listen/stationid/mountpoint
)RadioAPI::LIVE365
- Live365 (use withhttps://streaming.live365.com/mountid
)
Set the language for metadata responses:
$api->setLanguage('fr'); // French
$api->setLanguage('de'); // German
$api->setLanguage('es'); // Spanish
By default, the API includes track history. Turn it off if you don't need it:
$api->withHistory(false);
The SDK throws exceptions by default when something goes wrong. If you prefer to handle errors manually:
$api->setThrowOnApiErrors(false);
$data = $api->streamTitle()
->setStreamUrl('https://stream.example.com/radio')
->fetchArray();
if (isset($data['error'])) {
echo "Something went wrong: {$data['error']}";
}
Or catch exceptions:
use RadioAPI\Exceptions\ApiErrorException;
use RadioAPI\Exceptions\ClientErrorException;
use RadioAPI\Exceptions\ServerErrorException;
try {
$data = $api->streamTitle()
->setStreamUrl('https://stream.example.com/radio')
->fetchArray();
} catch (ClientErrorException $e) {
// 4xx errors
echo "Client error: {$e->getMessage()}";
} catch (ServerErrorException $e) {
// 5xx errors
echo "Server error: {$e->getMessage()}";
} catch (ApiErrorException $e) {
// Other API errors
echo "API error: {$e->getMessage()}";
}
Check if metadata was found:
$stream = $api->streamTitle();
$stream->setStreamUrl('https://stream.example.com/radio');
$stream->fetchArray();
if ($stream->hasMetadata()) {
// Do something with the data
}
Get the raw response:
$rawData = $stream->getData();
$services = [
RadioAPI::SPOTIFY,
RadioAPI::DEEZER,
RadioAPI::APPLE_MUSIC,
];
foreach ($services as $service) {
$data = $api->withService($service)
->streamTitle()
->setStreamUrl($streamUrl)
->fetchArray();
if (!empty($data['results'])) {
// Found it!
break;
}
}
- Always set your base URL and API key before making requests
- Use mount points when you need service-specific metadata
- The
withHistory(false)
option can speed up responses if you don't need historical data - Check
hasMetadata()
before accessing metadata fields to avoid errors - Use static helpers for quick one-off requests
- PHP 8.1 or higher
MIT