Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/TooTallNate/node-icy

Node.js module for parsing and/or injecting ICY metadata
https://github.com/TooTallNate/node-icy

Last synced: about 2 months ago
JSON representation

Node.js module for parsing and/or injecting ICY metadata

Awesome Lists containing this project

README

        

node-icy
========
### Node.js module for parsing and/or injecting [ICY metadata][protocol]
[![Build Status](https://travis-ci.org/TooTallNate/node-icy.svg?branch=master)](https://travis-ci.org/TooTallNate/node-icy)

This module offers a `Reader` class for retrieving the raw audio data and
parsing the metadata from an ICY stream (commonly [SHOUTcast][] or
[Icecast][] broadcasts).

There's also a `Writer` class that allows you to inject your own metadata into a
data stream, which can then be displayed by another ICY client (like VLC).

But you'll probably be most interested in the `Client` class that builds off of
node's core `http` module, except this version works with servers that return
an **ICY** HTTP version, and automatically sends an "Icy-MetaData: 1" HTTP header
to notify the server that we want metadata, and finally it returns a `Reader`
instance in the "response" event, therefore the "res" object also emits "metadata"
events. See the example below to see how it works.

A good use case for this module is for HTML5 web apps that host to radio streams;
the `` tag doesn't know how to deal with the extra metadata and it is
impossible to extract (on the client-side). But a WebSocket connection could be
used in conjunction with this module to provide those `metadata` events to a
web browser, for instance.

Installation
------------

Install with `npm`:

``` bash
$ npm install icy
```

Example
-------

Here's a basic example of using the HTTP `Client` to connect to a remote ICY
stream, pipe the clean audio data to _stdout_, and print the HTTP response headers
and metadata events to _stderr_:

``` javascript
var icy = require('icy');
var lame = require('lame');
var Speaker = require('speaker');

// URL to a known ICY stream
var url = 'http://firewall.pulsradio.com';

// connect to the remote stream
icy.get(url, function (res) {

// log the HTTP response headers
console.error(res.headers);

// log any "metadata" events that happen
res.on('metadata', function (metadata) {
var parsed = icy.parse(metadata);
console.error(parsed);
});

// Let's play the music (assuming MP3 data).
// lame decodes and Speaker sends to speakers!
res.pipe(new lame.Decoder())
.pipe(new Speaker());
});
```

You are also able to add custom headers to your request:
```javascript
var url = require('url');

// URL to a known ICY stream
var opts = url.parse('http://yourstreamurl.tld/');

// add custom headers
opts.headers = { 'User-Agent': 'Your awesome useragent' };

// connect to the remote stream
icy.get(opts, callback);
```

API
---

- [Client()](#client)
- [request()](#request)
- [get()](#get)
- [Reader()](#reader)
- [Writer()](#writer)
- [.queue()](#writerqueuemetadata)
- [parse()](#parse)
- [stringify()](#stringify)

## Client()

The `Client` class is a subclass of the `http.ClientRequest` object.

It adds a stream preprocessor to make "ICY" responses work. This is only needed
because of the strictness of node's HTTP parser. I'll volley for ICY to be
supported (or at least configurable) in the http header for the JavaScript
HTTP rewrite (v0.12 of node?).

The other big difference is that it passes an `icy.Reader` instance
instead of a `http.ClientResponse` instance to the "response" event callback,
so that the "metadata" events are automatically parsed and the raw audio stream
it output without the ICY bytes.

Also see the [`request()`](#request) and [`get()`](#get) convenience functions.

## request()

`request()` convenience function. Similar to node core's
[`http.request()`](http://nodejs.org/docs/latest/api/http.html#http_http_request_options_callback),
except it returns an `icy.Client` instance.

## get()

`get()` convenience function. Similar to node core's
[`http.get()`](http://nodejs.org/docs/latest/api/http.html#http_http_get_options_callback),
except it returns an `icy.Client` instance with `.end()` called on it and
no request body written to it (the most common scenario).

## Reader()

ICY stream reader. This is a duplex stream that emits "metadata" events in
addition to stripping out the metadata itself from the output data. The result
is clean (audio and/or video) data coming out of the stream.

## Writer()

The `Writer` class is a duplex stream that accepts raw audio/video data and
passes it through untouched. It also has a `queue()` function that will
queue the Writer to inject the metadata into the stream at the next "metaint"
interval.

### Writer#queue(metadata)

Queues a piece of metadata to be sent along with the stream.
`metadata` may be a String and be any title (up to 4066 chars),
or may be an Object containing at least a "StreamTitle" key, with a String
value. The serialized metadata payload must be <= 4080 bytes.

## parse()

Parses a Buffer (or String) containing ICY metadata into an Object.

## stringify()

Takes an Object and converts it into an ICY metadata string.

[protocol]: http://www.smackfu.com/stuff/programming/shoutcast.html
[Icecast]: http://icecast.org
[SHOUTcast]: http://www.shoutcast.com