Playing mp3 files in JavaFx from input stream


Question

I am using JavaFX media player to play an mp3 file using following code

 new MediaPlayer(new Media(FileObject.toURI().toString())).play();

However now I have a requirement that I have the mp3 byte data in memory instead of an File Object. The reason is the mp3 file is encrypted and then shipped along with the program. Hence I need to decrypt the mp3 file in memory or input stream.

I could decrypt the mp3 file to an temporary file in temp directory but this would be a performance overhead and the audio content would be insecure.

1
9
11/24/2012 9:06:40 AM

From the Media Javadoc

Only HTTP, FILE, and JAR URLs are supported. If the provided URL is invalid then an exception will be thrown. If an asynchronous error occurs, the error property will be set. Listen to this property to be notified of any such errors.

I'm not personally familiar with JavaFX, but that would suggest to me that without resorting to nasty hacks, you're not going to be able to read media directly from memory. Normally for this kind of URI only interface I'd suggest registering a custom UrlStreamHandler and a custom protocol that reads from memory. But assuming that JavaDoc is correct, the JavaFX uses it's own resolution so presumably this will not work.

Given this then I suspect the only way to make this work is to provide access to the in-memory MP3 over HTTP. You could do this using Jetty or any similar embeddable servlet container. Something along the following lines:

1) Start Up Jetty as per Quick Start Guide

2) Register a servlet that looks something like below. This servlet will expose your in-memory data:

public class MagicAccessServlet extends HttpServlet {
    private static final Map<String, byte[]> mediaMap = new ConcurrentHashMap();

    public static String registerMedia(byte[] media) {
        String key = UUID.randomUUID().toString();
        mediaMap.put(key, media);
        return key;
    }

    public static deregisterMedia(String key) {
        mediaMap.remove(key);
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String key = req.get("key");
        byte[] media = mediaMap.get(key);
        resp.setContentLength(media.length);
        resp.getOutputStream().write(media);
    }
}

Then you can access from within your application using an http url. E.g. something like

MagicAccessServlet.registerMedia(decodedMp3);
new MediaPlayer(new Media("http://localhost:<port>/<context>/<servlet>?key=" + key)).play();    
2
11/24/2012 9:36:12 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon