3

We have shoutcast/icecast audio streams. I'd like to be able to provide a link such as mobiledroid.php on our web site that will open using default player. I've seen this done on another site so I do know it's possible.

I assume it uses php headers and streams via the php file as a stream?


Using Brad's instructions, the android actually gives the option to open with sound player. Nice one.

It also plays on WMP through PC but not on the android how the above link plays

header("Content-type: audio/mpeg"); 
header("Transfer-Encoding: chunked"); 
header("Connection: close");

$sock = fsockopen($streamname,$port); //$streamname is the IP

fputs($sock, "GET $path HTTP/1.0\r\n"); //path in my case is /;stream.mp3
fputs($sock, "Host: $ip\r\n"); 
fputs($sock, "User-Agent: WinampMPEG/2.8\r\n"); 
fputs($sock, "Accept: */*\r\n"); 
fputs($sock, "Icy-MetaData:1\r\n"); 
fputs($sock, "Connection: close\r\n\r\n"); 


fpassthru($sock); 

fclose($sock);

On the android, it says "Sorry, this player does not support this type of audio file"


Update 2:

Removing "Transfer-Encoding" will play on android but as usual will take a long time to begin stream with "Preparing" status due to a live stream not having "Content-Length"

header("Transfer-Encoding: none"); also removed from above code:

Quoting Brad:

Android 2.3 and later has an issue with Transfer-Encoding set to "none". Removing that hard-set header puts the stream back to chunked Transfer-Encoding. This works great for Android 2.3+. Originally I had disabled chunked encoding as VLC doesn't support it. It also seems that Android 2.2 and older does not support chunked encoding.

Noting here that although it works on android, most live streams will take an awful amount of time to begin.

Community
  • 1
  • 1
Onimusha
  • 3,348
  • 2
  • 26
  • 32
  • Anything useful here -> http://stackoverflow.com/questions/2568665/icecast-shoutcast-streaming-on-android?rq=1 – ethrbunny Jul 13 '12 at 15:18
  • I have checked plenty of links from what you posted and before that too. So I can't use fopen etc as php won't read mp3 streams. You will get **HTTP request failed! ICY 200 OK** - Still checking – Onimusha Jul 13 '12 at 17:02
  • @Onimusha, Of course you can read SHOUTcast/Icecast streams with PHP... I do this every day. Also, I'm **very** curious what site you have found that works the way you want it to. – Brad Jul 14 '12 at 14:16
  • @Brad The site I came across is in saved in this link http://textsave.de/?p=127811 - had to save link sorry – Onimusha Jul 15 '12 at 11:00
  • The way this is working on Android is by linking directly to the MP3 stream. I've tried this with SHOUTcast/Icecast in the past and could never get it working directly. However, using some test server I've got going, it does work. I will figure out what the difference is, and will get back to you shortly. – Brad Jul 15 '12 at 15:08

1 Answers1

5

Problem

Traditionally, you would serve a playlist file which would be saved by your browser, and then opened in whatever player software was configured to open such playlists. The player would then read the URL of the stream, connect to it, and begin streaming.

On Android, they (for some crazy reason) chose not to support playlist files as supported media. Because of this, there is no direct way to launch the player using the traditional method.

Solution

On Android it seems that if you link directly to an MP3 file/stream, instead of downloading the file the default action is to open up a media player and try to stream it. This means that you can easily link directly to the URL of your stream (bypassing the playlist step entirely).

There is a catch... streams served with SHOUTcast aren't exactly HTTP compliant. They are close, but not perfect. The real hangup here seems to be one of content length. Typically, HTTP servers send a Content-Length response header. With streaming media, the length is unknown. There are two ways around the problem:

  1. Use chunked transfer encoding. You can do this by setting the following headers:
    Transfer-Encoding: chunked
    Then, use chunked encoding for the stream, and you're good to go.
  2. Use no transfer encoding, and specify that the connection will be closed when the resource is finished transferring, with these headers:
    Transfer-Encoding: none
    Connection: close

Your example link uses method one. I'm using method two successfully as well.

Once your server is talking valid HTTP, playback on Android seems to be a breeze.

Implementation

There are a handful of ways to go about implementing this fix. You have mentioned a PHP solution. If cURL won't work, you can always fsockopen() or stream_socket_client() to make a direct TCP connection, and handle the incoming stream data yourself. From there, you simply need to send the correct response headers and relay the data as it comes in. Keep in mind that a PHP instance will be running for each connected client, and each instance will make a connection to your server as well. This isn't ideal, but depending on what you have available, might be the only method for you.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • Remarkable. I've marked this as solved as the above has fixed the issues in question. However, I've updated the initial code as the stream itself does not work on the android. It works perfectly through PC wmp – Onimusha Jul 15 '12 at 18:28
  • @Onimusha, Can you post a link to your stream? – Brad Jul 15 '12 at 18:52
  • The stream I'm testing with is 159.253.143.4 port 8000 - Thanks – Onimusha Jul 15 '12 at 20:30
  • @Onimusha, Good choice in music! BassDrive.com is one of my favorites. Do you work with those guys? Anyway, the IP/port you gave seems to be for your SHOUTcast server directly. Can you post a link to your script? If this is your script, I don't see the appropriate headers. Also, the `ICY 200 OK` status line needs to be re-written as `HTTP/1.0 200 OK`. – Brad Jul 15 '12 at 21:06
  • I see. No I'm just creating the script for them. I don't have access to the server. I have uploaded the script for you http://shouthostdirect.com/tools/android1.php?ip=159.253.143.4&port=8000 - adding &mount=SOMETHING will add /SOMETHING to the stream url e.g. /;stream.mp3 – Onimusha Jul 15 '12 at 22:14
  • I think I might need help on what you meant by rewriting ICY 200 OK to HTTP/1.0 200 OK - Still haven't progressed on this. Hope to hear from you – Onimusha Jul 17 '12 at 17:46
  • @Onimusha, When you first get a response from a SHOUTcast server, its status line will say `ICY 200 OK`. Normal HTTP status lines will be like `HTTP/1.0 200 OK`. Most clients don't care... they only look at the status code. However, some do, and will complain that the response HTTP version doesn't seem right. You can intercept this and rewrite that status line with PHP. For reference, you can see how I've done this with a Node.js JavaScript application here: http://stackoverflow.com/a/9916603/362536 – Brad Jul 17 '12 at 23:53
  • @Onimusha, I'll also point out that I have this type of streaming working in a manner that should be much more efficient than doing it with PHP. I haven't released this software yet, but might be willing to let it out for a test drive for BassDrive.com. Please e-mail me at brad@musatcha.com if interested. Currently it is running the streams at http://waug.fm. – Brad Jul 17 '12 at 23:54
  • Hi @Brad could you please help me out with this issue too? https://stackoverflow.com/questions/49322222/live-audio-stream-socket-get-stuck-in-browser – Kootsj Mar 20 '18 at 12:22