简体   繁体   中英

javaFX MediaPlayer getCurrentTime() unreliable

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));
        }
    });

}

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);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM