1

I need to create an Icecast client in C#. The main objective of this it's to send the incoming audio from two audio devices to be broadcast via Icecast.

When I was searching for some solution already made, I found Butt which was exactly what I needed but I also needed to send to the Icecast two audio devices individually.

I'm already getting the audio input from the two microphones and save them in a folder (one audio file for each microphone). Now I need to broadcast individually the two microphone to Icecast.

All this is because I need to broadcast the two microphones like a radio station (one station for each microphone).

The main solution it's something like this:

  • Microphone 1 => Broadcast to Icecast like Source Micro1 => Save audio like micro1.mp3 format (working).
  • Microphone 2 => Broadcast to Icecast like Source Micro2 => Save audio like micro2.mp3 format (working).

I need to know how can I broadcast to icecast, i'm using NAudio library to get the audio input and save it.

EDIT: I'm communicating with Icecast from C#, this is my code:

public static void commIcecast(string url)
    {
        WebClient client = new WebClient();

        client.Headers.Add("content-type", "audio/mpeg");
        client.Headers.Add("Authorization", "Basic c291cmNlOmhhY2ttZQ==");
        client.Headers.Add("ice-name", "This is my server name");
        client.Headers.Add("ice-url", "http://www.google.com");
        client.Headers.Add("ice-genre", "Rock");
        client.Headers.Add("ice-description", "This is my server description");
        client.Headers.Add("ice-audio-info", "ice-samplerate=44100;ice-bitrate=128;ice-channels=2");

        Stream data = client.OpenRead(url);
        StreamReader reader = new StreamReader(data);
        string s = reader.ReadToEnd();
        Console.WriteLine(s);
        data.Close();
        reader.Close();
    }

But i'm just reciving this answer from the Icecast server:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Icecast Streaming Media Server</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0">
<h2>Icecast2 Status</h2>
<br><div class="roundcont">
<div class="roundtop"><img src="/corner_topleft.jpg" class="corner" style="display: none"></div>
<table border="0" width="100%" id="table1" cellspacing="0" cellpadding="4"><tr><td bgcolor="#656565">
<a class="nav" href="admin/">Administration</a><a class="nav" href="status.xsl">Server Status</a><a class="nav" href="server_version.xsl">Version</a>
</td></tr></table>
<div class="roundbottom"><img src="/corner_bottomleft.jpg" class="corner" style="display: none"></div>
</div>
<br><br>&nbsp;


<div class="poster">Support icecast development at <a class="nav" target="_blank" href="http://www.icecast.org">www.icecast.org</a>
</div>
</body>
</html>

I've tried to send the "SOURCE /mp3test ICE/1.0" but the Headers.Add method don't allow me to do that.

EDIT: I'm sending this via tcp to Icecast, but i can't recibe the response, i just need to know if this way to send it , if it's right now i'll have to move the post to tcp issues. I'm not reciving any response of the Icecast server using this method of sending.

            System.Net.IPAddress address = System.Net.IPAddress.Parse(url);

            socketServer = new TcpClient(url, port);
            NetworkStream networkStream = socketServer.GetStream();

            data = Encoding.ASCII.GetBytes("SOURCE /csharp ICE/1.0");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("content-type: audio/mpeg");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("Authorization: Basic c291cmNlOmhhY2ttZQ==");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-name: lala");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-url: localhost");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-genre: Rock");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-bitrate: 128");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-private: 0");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-public: 1");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-description: This is my server description");
            networkStream.Write(data, 0, data.Length);

            data = Encoding.ASCII.GetBytes("ice-audio-info: ice-samplerate=44100;ice-bitrate=128;ice-channels=2");
            networkStream.Write(data, 0, data.Length);

            StreamReader reader = new StreamReader(networkStream);
            Console.WriteLine(reader.ReadToEnd());

With this i can connect to the Icecast server, at least the number of clients connected increase in the global statistics in Icecast, but then the connection it's lost and i can't get any response.

2 Answers2

1

First, you need to encode your captured audio with a codec. MP3 is popular and well supported. aacPlus is well supported (but not quite as much as MP3), and gives a better compression ratio in most cases.

I do not believe NAudio supports encoding (please correct me if I am wrong). You will need to look at something like FFMPEG (wide variety of codecs available) or LAME (quality MP3 codec). As a bonus, if you go with FFMPEG, it is able to capture from DirectShow sources for you, so you only need to write code to get data from STDOUT. (Note that there are potential licensing issues here, both with the source code of the libraries and with patents on the codecs.)

Now that you have encoded audio data, you need to implement the Icecast source protocol. To do that, see my answer here: https://stackoverflow.com/a/9985297/362536

Community
  • 1
  • 1
Brad
  • 159,648
  • 54
  • 349
  • 530
  • I'm not sure about the encoding support of NAudio, but i'm getting the audio of the two inputs and converting it to MP3/OGG/WAV format, i don't know if that respond your question about NAudio (i'm a bit noob in encoding/audio stuff). I've already checked your answer, but how can i implement that in a c# program? – Juan Enrique Riquelme Nov 26 '12 at 13:19
  • If you are already encoding to MP3, that is sufficient. Take the output of your MP3 encoder, and send it straight to the Icecast server as it is being encoded. The source protocol information can be found on the link in my answer. If you have specific questions (such as opening a TCP connection and sending data), you should ask those questions separately, and individually. There is a lot here, and it isn't possible to know what you are having trouble with as one whole question. Please do let me know however if you don't know how to get started, and I can outline what you need to do. – Brad Nov 26 '12 at 13:21
  • Ok, that's perfect. So let me see if i'm get it right: First: Get te MP3 encode (done). Second: Send the information via IceCast protocol (encoded audio) to Icecast via HTTPS Request? (guide me if i'm wrong please). – Juan Enrique Riquelme Nov 26 '12 at 13:29
  • Icecast does not use HTTPS. It uses its own proprietary protocol. Now, the headers that you send to Icecast are a lot like HTTP headers, but it is not the same thing. You won't find an HTTP client library that is compatible. You need to create a TCP connection to the Icecast server, send the appropriate headers, and then begin sending raw audio stream data. – Brad Nov 26 '12 at 14:03
  • I've been trying to send the headers to Icecast, but i'm not sure about the structure to send it. I'm already connecting to the server but i don't know how to send the headers based in the protocol. Can you give me an example in c#? – Juan Enrique Riquelme Nov 26 '12 at 17:31
  • Send the entire block like you would an HTTP request. Send it as it is, verbatim from the first block at http://stackoverflow.com/a/9985297/362536. I don't know what method you are using to connect to the server, so no, I cannot give you an example in C#. If you do not know how to send data over a TCP connection, please post a separate question for that. – Brad Nov 26 '12 at 17:40
  • As I told you earlier, you cannot simply use an HTTP client. You must create a TCP connection and send the header data yourself. That is why what you have above is not working. – Brad Nov 26 '12 at 20:50
  • I've made an update, now i'm using the tcp connection, but i'm not reciving the response. – Juan Enrique Riquelme Nov 27 '12 at 14:12
  • @JuanEnriqueRiquelme, It looks like you aren't sending line endings. Put `\r\n` at the end of your lines, and an extra one at the end of the headers. – Brad Nov 27 '12 at 17:06
0

To solve my problem I used Edcast. This is the url https://code.google.com/p/edcast-reborn/

Basically I used two instances of edcast, each one pointing a different audio input and they were connecting to the Icecast server.

With this configuration you can see the two edcast instances and listen the different audio inputs by accessing the Icecast server.

Thank you all for your help.