18

I need to write an Icecast 2 client that will be able to stream audio from the computer (mp3-files, soundcard recording and so forth) to the server. I decided to write such a client on C#.

Two questions:

1) It will be very useful to know common guidelines (best practices, maybe tricks) I may/should/must use to seamlessly work with streamed audio (streamed over network, of course) in C#. Some general technical documentation about streaming over TCP/IP in common and ICY in particular, advices and notes on the overall architecture of the application will be very appreciated.

2) Is there any good documentation regarding the Icecast 2 streaming protocol? I couldn't find those docs on the official site of Icecast. I don't want to extract the protocol description directly from the source code of it. If the protocol is really simple and neat, could anybody provide a summary of it right here?

Daniel O'Hara
  • 13,307
  • 3
  • 46
  • 68

4 Answers4

31

As far as I know, there is no protocol spec anywhere, outside of the Icecast source code. Here's what I've found from packet sniffing:

Audio Stream

The protocol is similar to HTTP. The source client will connect to the server make a request with the mountpoint, and pass some headers with information about the stream:

SOURCE /mp3test ICE/1.0
content-type: audio/mpeg
Authorization: Basic c291cmNlOmhhY2ttZQ==
ice-name: This is my server name
ice-url: http://www.google.com
ice-genre: Rock
ice-bitrate: 128
ice-private: 0
ice-public: 1
ice-description: This is my server description
ice-audio-info: ice-samplerate=44100;ice-bitrate=128;ice-channels=2

If all is good, the server responds with:

HTTP/1.0 200 OK

The source client then proceeds to send the binary stream data. Note that it seems some encoders don't even wait for the server to respond with 200 OK before they start sending stream data. Just headers, an empty line, and then stream data.

Meta Data

Meta data is sent using an out-of-band HTTP request. The source client sends:

GET /admin/metadata?pass=hackme&mode=updinfo&mount=/mp3test&song=Even%20more%20meta%21%21 HTTP/1.0
Authorization: Basic c291cmNlOmhhY2ttZQ==
User-Agent: (Mozilla Compatible)

The server responds with:

HTTP/1.0 200 OK
Content-Type: text/xml
Content-Length: 113

<?xml version="1.0"?>
<iceresponse><message>Metadata update successful</message><return>1</return></iceresponse>

Also note that both the audio stream and meta data requests are sent on the same port. Unlike SHOUTcast, this is the base port that the server is running on.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • 3
    @JonathanC, There is no format... just send the raw encoded audio data. You can even start an at arbitrary place in the stream. – Brad Oct 30 '12 at 19:04
  • This is not entirely clear to me. So as I record and encode to mp3 in chunks: do I put these same headers for each raw binary chunk? What I am not completely clear on is "just send raw encoded data". Do I send dump it in the body of an HTTP request? – JonathanC Oct 30 '12 at 19:17
  • i guess what I mean is: what protocol is expected by icecast for this raw binary data? – JonathanC Oct 30 '12 at 19:26
  • @JonathanC, There is nothing expected. Once you have sent the headers after connecting, all you need to do is send the data output from your encoder. The headers are only sent once... not for every chunk. The server doesn't care much about the format. It will buffer data and send it as-is to clients. – Brad Oct 30 '12 at 21:25
  • I see. Thank you for the answer. So the chunks are sent in a simple HTTP body right? I had initially thought I would have to open a socket connection or something. So I send the following HTTP request with the body being the raw binary data: "SOURCE /mp3test ICE/1.0 content-type: audio/mpeg" is this correct? – JonathanC Oct 30 '12 at 21:44
  • @JonathanC, That is sort of correct, but this is not compatible with HTTP. The headers are HTTP-like, but the fact that you send the headers, complete the headers (pair of `CrLf`), and then send your stream data makes it out of the realm of what standard HTTP clients and servers will give you. – Brad Oct 31 '12 at 02:13
  • so does this mean I should create my own http-like node.js server (for example) that accepts the stream of raw data and passes it on to my icecast server? If that is so, I don't understand why it was designed this way. – JonathanC Oct 31 '12 at 19:00
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18880/discussion-between-brad-and-jonathanc) – Brad Oct 31 '12 at 19:50
  • Please note, `ice-audio-info: ice-samplerate=44100;ice-bitrate=128;ice-channels=2` is not very common, instead following should be used (no ice-prefix for the keys): `ice-audio-info: samplerate=44100;bitrate=128;channels=2` – ePirat May 26 '14 at 14:22
  • @ePirat Thanks. I saw those headers when testing with Edcast as a source. Are you saying that the `ice-*` headers still work? It shouldn't matter a lot anyway as these are just hints, not used in the actual stream, but it would be good to get them right for directory purposes. – Brad May 26 '14 at 14:53
  • @Brad The `ice-*` inside the ice-audio-info will work, yes. But a lot clients do not use them anymore. This information is currently directly passed on to the yp directory, but in future versions they might be parsed by Icecast and then it is very likely that the `ice-*` will be dropped some time in the future. (Note this only applies for the keys inside the `ice-audio-info`, this does not affect the headers itself!) – ePirat May 26 '14 at 15:08
7

I'm going to comment here despite this question being quite old.

Icecast is HTTP compliant. This was always the case for the listener side (plain and simple HTTP1.0, RFC 1945), starting with 2.4.0 it's also true for the source client side.

To implement a source client it's a PUT request in compliance with HTTP 1.1 aka RFC2616. Some options can be set through HTTP headers, for details please refer to the current Icecast documentation.

If you send one of the supported container formats: Ogg or WebM (technically EBML), then this is all you need to know. To make it clear this covers at leastOpus, Vorbis, Theora and VP8 codecs.

Please note that while generally working fine, other formats are technically not supported. Icecast only passes through the stream without any processing in such a case.

If you need help or have further questions, then the official mailing lists and the IRC channel are the right place to go.

Community
  • 1
  • 1
TBR
  • 2,790
  • 1
  • 12
  • 22
  • Hey there! Great to see that Icecast now supports a simple HTTP PUT request. Any thoughts as to when 2.4 will be considered stable? And, got a link to this documentation? I can't find any except for the release announcement. – Brad Aug 19 '13 at 00:10
  • Icecast 2.4.0 was released on 2014-05-06. Current release, as of writing is 2.4.1, with many bug fixes. – TBR Nov 25 '14 at 14:22
4

Looked at Icecast2 a good long while ago: best reference I could find was at http://forums.radiotoolbox.com/viewtopic.php?t=74 link (I should print that out, took me forever to figure out the proper Google spell to cast to surface that again). It appears to cover source to server and server to client.

Questions remain about just how accurate it is: I got about halfway through an Android implementation before other things consumed me, and I can't quite remember what was wrong with the communication between my implementation of that and VLC/Winamp, but honestly it was the closest thing I could find to a spec.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • 1
    Note that this is for the SHOUTcast source protocol. Icecast supports a single source client using this protocol at a time. There is a separate source protocol for Icecast which is essentially HTTP. – Brad Apr 01 '12 at 16:56
  • URL to spec? Would love to get my hands on that. – Femi Apr 02 '12 at 18:36
  • You and me both... unfortunately, I haven't found it documented anywhere. It seems the only documentation is in the source code. I've just been packet sniffing connections to get it figured out. It isn't that complicated. You can see the general flow in the first block of my question here: http://stackoverflow.com/questions/9970679/keeping-socket-open-after-http-request-response-to-node-js-server – Brad Apr 02 '12 at 18:41
2

The best description I know is here: https://gist.github.com/ePirat/adc3b8ba00d85b7e3870

@ePirat is xpiph/icecast core committer.

Niko
  • 558
  • 5
  • 14