javajavafxbytearrayinputstream

How can I create a Media object in javafx from a byte array?


I am trying to play media in javafx using MediaView, MediaPlayer, and Media. The Media class seems to only accept a URL source to create Media (which is used to pass to the MediaPlayer). I would like to pass a cached byte array to create the Media object. Is this supported?

I was able to play media using a URL and a file, but not a byte array.


Solution

  • For most people, I think there isn't a requirement to have media in memory, as the JavaFX media system is based on gstreamer, which is designed to stream media from secondary storage efficiently.

    From the media doc “Only HTTP, HTTPS, FILE, and JAR URIs are supported.”. So you need to serve your bytes from a provider on one of those protocols.

    You could run an embedded HTTP server and serve the bytes from that using the HTTP protocol.

    Or you could use an in-memory file system, serving the bytes using the file or jar protocols..

    Example embedded http server serving content from bytes in memory.

    The example serves image mime types, but serving other content types for media would work as long as the input stream is correct (e.g. represents correctly encoded mp3 or mp4 data).

    Just wondering, what would a solution using an in-memory file system look like?

    From Slaw's comment on testing an in-memory fileysystem approach, it is not compatible with the JavaFX 21 media system.

    It would probably be tricky to implement from scratch.

    Likely, you need to implement a FileSystem and a FileSystemProvider.

    Rather than doing that yourself, you could use an existing implementation such as jimfs.

    It may be necessary to reference your custom file system indirectly using the jar protocol rather than the default file protocol. For example, using jar:jimfs://, wrapping the custom file system in a zip to allow a jar protocol. It would be necessary to create a proof of concept to prove it could be done.

    Alternative: Fork JavaFX code

    You could fork some of the media code from JavaFX and modify the fork to allow other protocols or constructors that support your in-memory object.

    Easy workaround

    It is easier though just to write the media bytes to a temp file and access that using the file: protocol instead, as suggested in Slaw's answer.

    Consider AudioClip if latency is a concern

    @Slaw agreed, based on your analysis, that the in-memory file approach probably isn't going to work.

    AudioClip stores in memory the raw, uncompressed audio data for the entire sound, which can be quite large for long audio clips. A MediaPlayer will only have enough decompressed audio data pre-rolled in memory to play for a short amount of time so it is much more memory efficient for long clips, especially if they are compressed.