I'm trying to make an embedded video player in a program using Java swing and vlcj and would like a video scrubber. I'm coding between MacOS and windows and using vlcj 4.8.2.
I am currently trying to use a JSlider to create the video scrubber and am struggling with the media event listeners. I have put a test output in an event listener for when the time changes in the video but it never seems to fire even though the video is playing on my screen.
I have a main class that calls a UI class that calls the initializeMediaPlayer.
Is there a reason this isnt outputting the time change or an easier way to create a video scrubber?
I am still quite new to this library so I assume I'm missing a fairly easy thing.
This is my media player class:
import java.awt.BorderLayout;
import uk.co.caprica.vlcj.factory.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.player.component.CallbackMediaPlayerComponent;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventAdapter;
import static uk.co.caprica.vlcj.player.base.State.PLAYING;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
public class MediaPlayer {
public static void initializeMediaPlayer(JPanel videoPanel) {
JButton uploadFootageButton = new JButton("<html>Click to Upload Footage<br />(or drag and drop)</html>"); //upload footage button
//over two lines
videoPanel.add(uploadFootageButton, BorderLayout.CENTER);
uploadFootageButton.addActionListener(new ActionListener() { //adds the action listener
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser footageUpload = new JFileChooser(); //load file explorer
int result = footageUpload.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) { //if a file is selected
new NativeDiscovery().discover(); //find the vlc path
String selectedFilePath = footageUpload.getSelectedFile().getAbsolutePath(); //path of video
videoPanel.remove(uploadFootageButton); //remove upload button when video is uploaded
JPanel mediaBar = new JPanel();
videoPanel.add(mediaBar, BorderLayout.SOUTH);
CallbackMediaPlayerComponent mediaPlayerComponent = new CallbackMediaPlayerComponent();
videoPanel.add(mediaPlayerComponent); //add the media player
EmbeddedMediaPlayer mediaPlayer = mediaPlayerComponent.mediaPlayer();
mediaPlayer.media().prepare(selectedFilePath); //prepare the video
mediaPlayer.controls().play(); //play the video
videoPanel.revalidate(); //make sure video panel is correct
videoPanel.repaint();
initialiseMediaSettings(mediaBar, mediaPlayer, mediaPlayerComponent); //create video settings and buttons
}
}
});
}
public static void initialiseMediaSettings(JPanel mediaBar, EmbeddedMediaPlayer mediaPlayer, CallbackMediaPlayerComponent mediaPlayerComponent) {
//code here that adds:
//mute audio button
//play/pause button
//playback speed options
//scrubber
/*-----------------------------------------------------------------------------------------------------------------------------------*/
JSlider videoScrubber = new JSlider();
while (mediaPlayer.status().state() != PLAYING) { //while its not playing
try {
Thread.sleep(100); // Sleep for a short interval to avoid busy-waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
videoScrubber.setMinimum(0); //cant have negative time in video
videoScrubber.setMaximum((int) mediaPlayer.status().length()); //max of slider is video length
mediaPlayer.controls().setRepeat(true);
videoScrubber.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (!videoScrubber.getValueIsAdjusting()) { //stops updating whilst scrubber is being moved
mediaPlayer.controls().setPosition(((float) videoScrubber.getValue()) / videoScrubber.getMaximum());
}
}
});
mediaPlayerComponent.mediaPlayer().events().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
public void timeChanged(MediaPlayer mediaPlayer, long newTime) {
System.err.println("Time changed: " + newTime);
}
});
mediaBar.add(videoScrubber);
}
/*-----------------------------------------------------------------------------------------------------------------------------------*/
}
I have tried just having a reccuring excecute function that updates the scrubber but it just ends up being laggy and not working correctly.