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

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

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

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

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

来自Media Javadoc

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

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

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

1)按照快速入门指南启动Jetty

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

 public class MagicAccessServlet extends HttpServlet { private static final Map 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); } } 

然后,您可以使用httpurl从您的应用程序中访问。 比如像

 MagicAccessServlet.registerMedia(decodedMp3); new MediaPlayer(new Media("http://localhost://?key=" + key)).play(); 

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

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