javaFX MediaPlayer getCurrentTime() unreliable


Question

To play a mp3 file, I am using the javafx.scene.media.MediaPlayer class. But I noticed that the currentTimeProperty is not reliable after using the seek() method.

The method initMediaPlayer() in the code below is called when the user has choosen a mp3 file. The playback time is shown in a time slider (=timeSlider) which the user can move to start the playback from any point in the song. The current position in the song is also displayed in a label (=timeLabel).

When I start the playback with play(), and when I pause or restart the song with pause() or stop(), everything works fine.

The problem is that after using seek() the currentTimeProperty is not longer correct. This is becomes very noticeable towards the end of the song, then the currentTimeProperty is sometimes up to 4 seconds longer than the total time of the song.

What is the cause of this problem and is there a way to work around it?

private void initMediaPlayer() {
    try {
        audio = new Media(audioFile.toURI().toURL().toString());
        audioPlayer = new MediaPlayer(audio);
    } catch (MalformedURLException ex) {
        Logger.getLogger(MainWindowController.class.getName())
            .log(Level.SEVERE, null, ex);
    }

    audioPlayer.currentTimeProperty().addListener(new InvalidationListener() {
        public void invalidated(Observable ov) {
            Duration time = audioPlayer.getCurrentTime();
            Duration total = audioPlayer.getTotalDuration();

            if (!timeSlider.isValueChanging() &&
                total.greaterThan(Duration.ZERO)){

                timeSlider.setValue(time.toMillis() / total.toMillis() * 100);
            }

            timeLabel.setText(formatTime(time,total));
        }
    });

    timeSlider.valueChangingProperty().addListener(new InvalidationListener() {
        public void invalidated(Observable ov) {
            audioPlayer.seek(audioPlayer.getTotalDuration()
                .multiply(timeSlider.getValue() / 100.0));
        }
    });

}
1
6
6/18/2013 9:47:45 AM

You want ChangeListener<Duration>, not InvalidationListener.

audioPlayer.currentTimeProperty().addListener((observableValue, oldDuration, newDuration) -> {
     System.out.println("Player:" + observableValue + " | Changed from playing at: " + oldDuration + " to play at " + newDuration);
});
1
8/25/2014 4:57:48 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon