Caprica Software

vlcj 3.x Tutorial

Java IO

With LibVLC 3.0.0+ and the most recent version of vlcj it is now possible to play media using standard Java IO.

There are however some limitations, and in some cases they may be critical limitations.

The vast majority of applications will not need to use this feature and can instead rely on the native media playback via a Media Resource Locator (MRL) as has always been the case with vlcj.


How it Works

LibVLC 3.0.0 added new native "media callbacks" which are used to open, read, seek and close a media "stream". Essentially this enables VLC to callback into a Java application to open the media, read a sequence of bytes from the media data to populate a native IO buffer, seek to any position within the media data, and when done to close the media.

The key step is to populate a supplied native IO buffer with media data on demand.

vlcj provides Media classes that help you use Java IO to play your media, without you needing to consider any of the interaction with native code.


Seekability

The first consideration is that of "seekability" - is it possible, using Java IO, to seek to any position within the media?

The natural choice for seekability is to use a RandomAccessFile, where by definition it is possible to seek to any position within such a file before reading the data.

Just about every Java InputStream is not seekable - rather the data is consumed from the stream in a linear manner from start to finish. Some InputStream implementations allow to seek forwards by skipping bytes, but seeking backwards within a stream is rarely possible. It is possible to create a bespoke implementation of an InputStream that allows seeking, but this may not be straightforward, and in the simplest case it would require that the entire media data be held in an in-memory buffer.

Seekability is therefore a factor that you must consider - some media types simply can not be played without the ability to seek.


Let's Get Started

You should now already have a basic template for how to create a vlcj application, so this tutorial will no longer duplicate all of the code each time - instead we'll just show the new code fragments.

We start by assuming we already have a media player component:

mediaPlayerComponent = new EmbeddedMediaPlayerComponent();

Rather than play an MRL as is the norm with vlcj, we play a Media instance...


Create a Media Instance

For seekable media, we use the vlcj RandomAccessFileMedia class, and pass it when invoke playMedia on the media player:

Media media = new RandomAccessFileMedia(new File("MyCoolMovie.mp4"));
mediaPlayerComponent.getMediaPlayer().playMedia(media);

For non-seekable media, in this case we want to use a FileInputStream and the vlcj FileInputStreamMedia class:

Media media = new FileInputStreamMedia(new File("MyCoolMusic.mp3"));
mediaPlayerComponent.getMediaPlayer().playMedia(media);

If you want to play a simple MRL, you can keep doing this as you have always done using the playMedia method that takes a String.

If you prefer to use a consistent API for playing simple MRLs, you can optionally choose to use the vlcj SimpleMedia class:

Media media = new SimpleMedia("MyCoolMovie.mp4");
mediaPlayerComponent.getMediaPlayer().playMedia(media);

Media Options

You can pass media options when you create your Media instance. These are the same media options that are ordinarily passed when you invoke playMedia on the media player instance. All of the concrete vlcj Media sub-classes accept zero or more media options in their constructors.

String[] mediaOptions = {...};
Media media = new RandomAccessFileMedia(new File("MyCoolMovie.mp4"), mediaOptions);
mediaPlayerComponent.getMediaPlayer().playMedia(media);

Custom Media Types

vlcj provides scaffolding and implementations for the most common use-cases, but if you need to it is possible to extend the vlcj classes to implement your own bespoke behaviour.


Summary

You can play media with vlcj using standard Java IO - however, there are constraints particularly with regard to the non-seekability of the standard Java input streams.