PHP streaming proxy

Here’s the problem: if you want to relay an Icecast stream, you need to set up a whole Icecast server. Or do you? I will show you an easy way to set up a simple proxy-like relay for an OGG stream using only Apache and PHP.

Let’s say that we have an Icecast server, broadcasting a radiostation. Let’s take for example this radio station. We want to create a PHP script which acts as a proxy between the listener and the server. What we need is PHP and Apache with mod_rewrite enabled.

The first thing we need to set up is an entry point for the clients. It must be something which ends with ‘.ogg’ – let it be ‘/stream.ogg’. We can’t name the php script with an ‘ogg’ extension because the server will not parse it. So, we use mod_rewrite to dynamically redirect the requests for ‘/stream.ogg’ to be handled by ‘stream.php’. This is acomplished by a simple file in the same directory called ‘.htaccess’. Here is what should be in it:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/stream.ogg$
RewriteRule ^(.*) /stream.php

Now, every request for ‘/stream.ogg’ will be redirected to ‘/stream.php’. Why do we need to have this ‘.ogg’ extension? Because Winamp gets confused by the ‘.php’ extension and doesn’t play the stream.

You should create a .m3u playlist file called something like “stream.ogg.m3u”, which contains only the full URL to the stream, like:

Link to this playlist, not to the stream itself.

The PHP script is a fairly simple one, since it has just one job to do – read the original stream and keep sending it to the client. Here’s the source code:

$s = fopen("","rb");
foreach ($http_response_header as $h) {
while (!feof($s)) {
	echo fread($s, 4096);

The “set_time_limit” limits the execution time of the script to 24 hours, which is pretty reasonable for the average listener (and the script will end if the listener drop the connection earlier). You can change this to whatever you like.

“$http_response_header” contains the HTTP headers received from the original stream, and is filled-in by fopen(). We just pass them through to the client, we don’t care what they are, but they contain information needed by the player.

This approach works not only with OGG-encoded streams, but with MP3 as well – just change the extension of the entry point.

Of course, this thing doesn’t scale well – every listener will start a new script, and the server will keep several connections to the original stream, which is just stupid. However, my initial problem was simply accessing a private stream with just one listener (me), so it didn’t bother me.

Leave a Reply


  1. Soho

    27 April 2007 at 04:55


    This was _exactly_ what I was looking for! Many, many, many thanks!

  2. Интернет маркетинг

    20 May 2008 at 12:35

    Много добра реализация, хитро измислени. Благодаря за идеята. Ще се опитам да я доразвия за моя проект. След това ще направя пост тук какво съм постигнал.