oleh-exe / mp3-stream-title
Fetch and parse current track metadata from Icecast and Shoutcast MP3 streams.
Requires
- php: ^8.2
- ext-curl: *
Requires (Dev)
- phpstan/phpstan: ^2.2
- squizlabs/php_codesniffer: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-17 21:59:50 UTC
README
MP3 Stream Title is a small PHP library for reading the current StreamTitle
metadata from Icecast and Shoutcast MP3 radio streams.
It sends an ICY metadata request, reads only the part of the stream needed to
reach the metadata block, and returns the current StreamTitle metadata as a string.
Features
- Fetches current track metadata from online MP3 radio streams.
- Supports cURL, PHP streams, and socket-based transports.
- Uses typed PHP 8.2 APIs, strict validation, and exceptions.
- Parses ICY metadata through focused request, response, and metadata helpers.
- Includes helpers for UTF-8 fallback conversion and HTML entity decoding.
- Provides
MetadataWatcherfor polling a stream and yielding title changes. - Ships with Composer PSR-4 autoloading.
Requirements
- PHP 8.2 or newer.
- PHP cURL extension.
- Composer.
composer.json declares ext-curl, and the default transport is
StreamTransport::CURL. Although stream and socket transports are available, the package currently requires the PHP cURL extension.
Installation
composer require oleh-exe/mp3-stream-title
For development from a checkout, install dependencies first:
composer install
All examples below assume Composer autoloading is available through
vendor/autoload.php.
Usage
<?php require_once __DIR__ . '/vendor/autoload.php'; use Mp3StreamTitle\Mp3StreamTitle; $client = new Mp3StreamTitle(); $streamUrl = 'https://example.com/radio-stream'; try { echo $client->fetchStreamTitle($streamUrl); // B.B. King - The Thrill Is Gone } catch (Throwable $exception) { echo $exception->getMessage(); }
Transport Configuration
The default transport is cURL. To choose another transport, pass an
Mp3StreamTitleConfig instance:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Mp3StreamTitle\Mp3StreamTitle; use Mp3StreamTitle\Config\Mp3StreamTitleConfig; use Mp3StreamTitle\Config\StreamTransport; $streamUrl = 'https://example.com/radio-stream'; try { $client = new Mp3StreamTitle( new Mp3StreamTitleConfig( streamTransport: StreamTransport::SOCKET, userAgent: 'MyRadioApp/1.0', metaMaxLength: 4080, ) ); echo $client->fetchStreamTitle($streamUrl); } catch (Throwable $exception) { echo $exception->getMessage(); }
Available transports:
StreamTransport::CURLStreamTransport::STREAMStreamTransport::SOCKET
FOLLOWLOCATION support is available for StreamTransport::CURL and
StreamTransport::STREAM. StreamTransport::SOCKET does not support
FOLLOWLOCATION / follow-location behavior at the moment because this feature
is not implemented for the socket transport.
Metadata Encoding
Some streams publish metadata in legacy encodings or with HTML entities. The
library ships with small helpers that can be used when you need to normalize
metadata values outside the main fetchStreamTitle() flow.
The example below uses hex2bin() only to create reproducible sample bytes for
the README. In real code, pass the raw metadata string you received from the
stream:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Mp3StreamTitle\Encoding\HtmlEntityDecoder; use Mp3StreamTitle\Encoding\FallbackEncodingConverter; $decoder = new HtmlEntityDecoder(); // Example input: raw bytes as they might arrive from an ISO-8859-1 stream $rawTitle = hex2bin('416e746f6e696f205069f165726f202d204d6174656f'); try { $converter = new FallbackEncodingConverter(); echo $decoder->decode( $converter->convertToUtf8($rawTitle) ); // Antonio PiƱero - Mateo } catch (Throwable $exception) { echo $exception->getMessage(); }
Watching Title Changes
MetadataWatcher polls a stream and yields a title only when it changes:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Mp3StreamTitle\Watcher\MetadataWatcher; use Mp3StreamTitle\Mp3StreamTitle; $streamUrl = 'https://example.com/radio-stream'; try { $watcher = new MetadataWatcher( client: new Mp3StreamTitle(), interval: 10, // In seconds ); foreach ($watcher->watch($streamUrl) as $title) { echo '[' . date('H:i:s') . '] ' . $title . PHP_EOL; } } catch (Throwable $exception) { echo $exception->getMessage(); }
Experimental API
The following APIs are considered experimental and may change or be removed in future versions without prior notice:
-
Mp3StreamTitle\Encoding\FallbackEncodingConverter- The fallback encoding strategy and supported fallback encodings may evolve as additional ICY metadata edge cases are identified.
-
Mp3StreamTitle\Encoding\HtmlEntityDecoder- The entity decoding behavior and integration with metadata normalization workflows may change based on real-world usage and feedback.
-
Mp3StreamTitle\Watcher\MetadataWatcher- The metadata watching API, polling behavior, and iteration model may change in future versions.
These APIs are provided as optional helpers and are not considered part of the library's stable core functionality at this time.
Upgrade Notes
Version 1.0.0 is a PHP 8.2 rewrite and changes the public API.
- Use
fetchStreamTitle(string $streamingUrl): stringinstead ofsendRequest($streaming_url). - Use
Mp3StreamTitleConfigandStreamTransportinstead of mutable public properties such as$send_type,$user_agent,$show_errors, and$meta_max_length. - Use Composer autoloading instead of requiring only
src/Mp3StreamTitle.php. - Handle exceptions instead of checking for
0or error strings.
Development
composer install vendor/bin/phpcs vendor/bin/phpstan