Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

live audio stream socket get stuck in browser

I'm trying to setup a page where several (private) streams can be listened from. Unfortunately I'm not able to get it running. I tried Using php to opening live audio stream on android already, but for some reason the browser get stuck when loading the script.

See below script with an example of a working host (see http://icecast.omroep.nl/radio4-bb-mp3)

Could someone please enlighten me.

Tnx in advance!

    $host = "icecast.omroep.nl";
    $port = 80;
    $sub = "/radio4-bb-mp3";


    $sock = fsockopen($host,$port, $errno, $errstr, 30);
    if (!$sock){
        throw new Exception("$errstr ($errno)");
    }

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

    fputs($sock, "GET $sub HTTP/1\r\n");
    fputs($sock, "Host: $host \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);
like image 992
Kootsj Avatar asked Mar 16 '18 13:03

Kootsj


1 Answers

Following comments the solution you are looking is:

<?php

$host = "icecast.omroep.nl";
$sub = "/radio4-bb-mp3";
header("Location:  http://{$host}{$sub}");

Now I will explain what was wrong with your code

You have a problem with the headers. You are adding your own headers and the remote headers as part of the body.

icecast.omroep.nl headers

HTTP/1.0 200 OK
Content-Type: audio/mpeg
Date: Sat, 24 Mar 2018 16:01:23 GMT
icy-br:192
ice-audio-info: samplerate=48000;channels=2;bitrate=192
icy-br:192
icy-genre:Classical
icy-metadata:1
icy-name:NPO Radio4
icy-pub:0
icy-url:http://www.radio4.nl
Server: Icecast 2.4.0-kh8
Cache-Control: no-cache, no-store
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
Access-Control-Allow-Methods: GET, OPTIONS, HEAD
Connection: Close
Expires: Mon, 26 Jul 1997 05:00:00 GMT
icy-metaint:16000

Given your script index.php

<?php

$host = "icecast.omroep.nl";
$port = 80;
$sub = "/radio4-bb-mp3";


$sock = fsockopen($host,$port, $errno, $errstr, 30);
if (!$sock){
    throw new Exception("$errstr ($errno)");
}

fputs($sock, "GET $sub HTTP/1\r\n");
fputs($sock, "Host: $host \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);

request.txt

GET /
[Blank line]

Serving your script

$ php -S 0.0.0.0:8000 index.php

Your script response:

$ (nc 127.0.0.1 8000 < request.txt) | head -n 27

HTTP/0.9 200 OK
Date: Sat, 24 Mar 2018 16:01:23 +0000
Connection: close
X-Powered-By: PHP/7.1.14
Content-type: text/html; charset=UTF-8

HTTP/1.0 200 OK
Content-Type: audio/mpeg
Date: Sat, 24 Mar 2018 16:01:23 GMT
icy-br:192
ice-audio-info: samplerate=48000;channels=2;bitrate=192
icy-br:192
icy-genre:Classical
icy-metadata:1
icy-name:NPO Radio4
icy-pub:0
icy-url:http://www.radio4.nl
Server: Icecast 2.4.0-kh8
Cache-Control: no-cache, no-store
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type
Access-Control-Allow-Methods: GET, OPTIONS, HEAD
Connection: Close
Expires: Mon, 26 Jul 1997 05:00:00 GMT
icy-metaint:16000

PHP is adding his own headers.

You need to process the headers received from http://icecast.omroep.nl/radio4-bb-mp3 and return them using the method header() and then you can do the fpassthru().

HTTP separate the headers from the body with a new line: https://www.rfc-editor.org/rfc/rfc2616#section-6

[header]
CRLF
[body]

So it should be easy to parse line by line and calling header() until CRLF (empty line) is found and then trigger the fpassthru().

like image 132
albert Avatar answered Nov 14 '22 14:11

albert