Skip to content
Advertisement

How to stream url from .pls file with java?

I want to stream a radio with Java, my approach is to download the playlist file (.pls), then extract one of the urls given in that same file and finally, stream it with java. However, it seems I cannot find a way to do it.. I tried with JMF, but I get java.io.IOException: Invalid Http response everytime I run the code.

Here is what I tried:

Player player = Manager.createPlayer(new URL("http://50.7.98.106:8398"));
player.start();

The .pls file:

NumberOfEntries=1
File1=http://50.7.98.106:8398/

In the piece of code above I’m setting the URL by hand, just for testing, but I’ve sucessfuly done the .pls downloading code and it’s working, and from this I make another question, is it a better approach to just simply play the .pls file locally? Can it be done?

Advertisement

Answer

You are connecting to an Icecast server, not a web server. That address/port is not sending back HTTP responses, it’s sending back Icecast responses.

The HTTP specification states that the response line must start with the HTTP version of the response. Icecast responses don’t do that, so they are not valid HTTP responses.

I don’t know anything about implementing an Icecast client, but I suspect such clients interpret an http: URL in a .pls file as being just a host and port specification, rather than a true HTTP URL.

You can’t use the URL class to download your stream, because it (rightly) rejects invalid HTTP responses, so you’ll need to read the data yourself. Fortunately, that part is fairly easy:

Socket connection = new Socket("50.7.98.106", 8398);

String request = "GET / HTTP/1.1nn";
OutputStream out = connection.getOutputStream();
out.write(request.getBytes(StandardCharsets.US_ASCII));
out.flush();

InputStream response = connection.getInputStream();

// Skip headers until we read a blank line.
int lineLength;
do {
    lineLength = 0;
    for (int b = response.read();
         b >= 0 && b != 'n';
         b = response.read()) {
        lineLength++;
    }
} while (lineLength > 0);

// rest of stream is audio data.
// ...

You still will need to find something to play the audio. Java Sound can’t play MP3s (without a plugin). JMF and JavaFX require a URL, not just an InputStream.

I see a lot of recommendations on Stack Overflow for JLayer, whose Player class accepts an InputStream. Using that, the rest of the code is:

Player player = new Player(response);
player.play();
Advertisement