从输入流播放JavaFx中的mp3文件

时间:2012-11-24 09:06:41

标签: java streaming mp3 javafx-2 javafx

我正在使用JavaFX媒体播放器使用以下代码播放mp3文件

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

但是现在我要求我在内存中使用mp3字节数据而不是文件对象。原因是mp3文件已加密,然后随程序一起发货。因此我需要在内存或输入流中解密mp3文件。

我可以将mp3文件解密到临时目录中的临时文件,但这会带来性能开销,音频内容也会不安全。

2 个答案:

答案 0 :(得分:2)

来自Media Javadoc

  

仅支持HTTP,FILE和JAR URL。如果提供的URL无效,则会引发异常。如果发生异步错误,将设置error属性。收听此属性以获得任何此类错误的通知。

我并不熟悉JavaFX,但这对我来说,如果不诉诸讨厌的黑客,你将无法直接从内存中读取媒体。通常对于这种仅URI的接口,我建议注册自定义UrlStreamHandler和从内存中读取的自定义协议。但假设JavaDoc是正确的,JavaFX使用它自己的分辨率,所以可能这不起作用。

鉴于此,我怀疑使这项工作的唯一方法是通过HTTP提供对内存中MP3的访问。您可以使用Jetty或任何类似的可嵌入servlet容器来执行此操作。以下内容:

1)根据Quick Start Guide

启动Jetty

2)注册一个类似于下面的servlet。该servlet将公开您的内存数据:

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);
    }
}

然后,您可以使用http网址从您的应用程序中进行访问。例如。

之类的东西
MagicAccessServlet.registerMedia(decodedMp3);
new MediaPlayer(new Media("http://localhost:<port>/<context>/<servlet>?key=" + key)).play();    

答案 1 :(得分:0)

不幸的是,随着Media构造函数的出现,除了临时文件方法之外,我认为没有简单的方法可以做到这一点。请注意,虽然我同意性能会产生开销,但如果文件不是太大(大多数mp3文件通常不是),那么在这种意义上开销应该是最小的。从技术上讲,将内容解码到内存也会使其不安全(尽管难以提取)。

我想到的一个稍微疯狂的方法是使用套接字。您可以设置应用程序的单独部分,解密未加密的内容,然后将原始mp3字节流式传输到localhost上的某个端口。然后,您可以将此作为HTTP URI提供给Media构造函数。