Search code examples
javajavasoundbufferedinputstreamjlayer

Write mp3 file to disk while playing in Java


I have an application playing remote MP3 files over HTTP using the JLayer/BasicPlayer libraries. I want to save the played mp3 files to disk without re-downloading them.

This is the code using the JLayer based BasicPlayer for Playing the MP3 file.

String mp3Url = "http://ia600402.us.archive.org/6/items/Stockfinster.-DeadLinesutemos025/01_Push_Push.mp3";
URL url = new URL(mp3Url);
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);

BasicPlayer player = new BasicPlayer();
player.open(bis);
player.play();

How would I save the mp3 file to disk?


Solution

  • To avoid having to go through the bytes twice, you need to wrap the input stream from the connection in a filter that writes any data that is read to an output stream, i.e. a kind of a "tee pipe input stream." Such a class is not that difficult to write yourself, but you can save the work by using TeeInputStream from the Apache Commons IO library.

    Apache Commons IO: http://commons.apache.org/io/
    TeeInputStream javadoc: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/TeeInputStream.html

    Edit: Proof-of-concept:

    import java.io.*;
    
    public class TeeInputStream extends InputStream {
        private InputStream in;
        private OutputStream out;
    
        public TeeInputStream(InputStream in, OutputStream branch) {
            this.in=in;
            this.out=branch;
        }
        public int read() throws IOException {
            int read = in.read();
            if (read != -1) out.write(read);
            return read;
        }
        public void close() throws IOException {
            in.close();
            out.close();
        }
    }
    

    How to use it:

    ...
    BufferedInputStream bis = new BufferedInputStream(is);
    TeeInputStream tis = new TeeInputStream(bis,new FileOutputStream("test.mp3"));
    
    BasicPlayer player = new BasicPlayer();
    player.open(tis);
    player.play();