Parses ICY metadata from a web stream
npm install @music-metadata/icy


StreamTitle) from HTTP responses while passing through clean audio chunks for playback or further processing.
strtok3
bash
npm install @music-metadata/icy
`
Or with Yarn:
`bash
yarn add @music-metadata/icy
`
---
Demo
* ICY Radio Stream Player
---
๐ฆ Usage
`ts
import { parseIcyResponse } from '@music-metadata/icy';
const response = await fetch('https://example.com/radio-stream', {
headers: {
'Icy-MetaData': '1'
}
});
const audioStream = parseIcyResponse(response, ({ metadata }) => {
const title = metadata.StreamTitle;
if (title) {
console.log('Now Playing:', title);
}
});
// You can now pipe audioStream to a decoder or audio player.
`
---
๐ง API
$3
Process a fetch-compatible HTTP response and extract ICY metadata on the fly.
#### Parameters
* response: Response
A standard Fetch API Response object with streaming body.
* handler: (update: MetadataUpdate) => void
A callback triggered when new ICY metadata is available.
#### Returns
* ReadableStream
A web-compatible readable stream containing only the audio payload, excluding metadata.
#### Example
`ts
{
metadata: {
StreamTitle: 'Cool Song',
StreamUrl: 'https://example.com',
...
},
stats: {
totalBytesRead: 20480,
audioBytesRead: 19200,
icyBytesRead: 1280
}
}
`
---
$3
Lower-level function to extract ICY metadata from a ReadableStream where the metadata interval is already known.
#### Parameters
* stream: ReadableStream or Node's ReadableStream
* metaInt: number โ The icy metadata interval in bytes.
* handler: (update: MetadataUpdate) => void โ Metadata callback, same as above.
#### Returns
* ReadableStream โ Cleaned stream without metadata blocks.
Use this method if you already know the icy-metaint (e.g., from headers or external configuration).
---
๐งบ ICY Metadata Parsing
ICY metadata is parsed from raw string format:
`ts
"StreamTitle='song';StreamUrl='url';"
`
Parsed result:
`ts
{
StreamTitle: 'song',
StreamUrl: 'url'
}
`
Internally handled by:
`ts
function parseRawIcyMetadata(raw: string): Map
`
---
๐ Types
$3
`ts
type IcyMetadata = {
StreamTitle?: string;
StreamUrl?: string;
icyName?: string;
icyGenre?: string;
icyUrl?: string;
bitrate?: string;
contentType?: string;
[key: string]: string | undefined;
}
`
$3
`ts
type MetadataUpdate = {
metadata: IcyMetadata;
stats: {
totalBytesRead: number;
audioBytesRead: number;
icyBytesRead: number;
};
};
`
---
๐งฑ Internals
If Icy-Metaint is not provided by the server, the module attempts to auto-detect the metadata interval by scanning the stream for known ICY patterns such as "StreamTitle=".
---
๐งญ How It Works
The following diagram shows how @music-metadata/icy fits into a web-based ICY audio streaming pipeline, parsing interleaved metadata while passing clean audio through to playback:
`mermaid
graph TD
%% Node Styles
style A fill:#bbf,stroke:#333,stroke-width:2px
style B fill:#ddf,stroke:#333,stroke-width:2px
style C fill:#afa,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5
style D fill:#ffe4b3,stroke:#333,stroke-width:2px
style E fill:#fcc,stroke:#333,stroke-width:2px,stroke-dasharray: 3 3
style F fill:#fcf,stroke:#333,stroke-width:2px
style G fill:#cff,stroke:#333,stroke-width:2px,stroke-dasharray: 2 4
%% Nodes
A["๐ง ICY Web Stream
(Icecast via Fetch)"]
B["๐ Fetch with
ICY-MetaData Header"]
C["๐งฉ @music-metadata/icy
(ICY Parser)"]
D["๐ Decoded Audio Stream"]
E["๐ต HTML5 Audio
<audio> Element"]
F["๐ฐ๏ธ ICY Metadata Events"]
G["๐ฅ๏ธ Metadata Display
in React UI"]
%% Flow
A --> B
B -->|ICY Interleaved Audio| C
C -->|Audio Stream| D
D --> E
C -->|Metadata Events| F
F -->|Track Info etc.| G
``