简体   繁体   中英

Seek method for javafx MediaPlayer does not seek correctly for 1.5 hr+ long audio files

I recently fixed a bug where the javafx MediaPlayer would break whenever I disconnected my bluetooth headphones. I fixed that by doing this.

    mediaPlayer.setOnError( () -> {
            mediaPlayer = new MediaPlayer(media);
            System.out.println(durationBackup.toMillis());
            mediaPlayer.setOnPlaying(() ->{
                mediaPlayer.seek(durationBackup);
                mediaPlayer.setOnPlaying(null);
            });
            mediaPlayer.play();
    });

durationBackup is just a backup of the duration before the MediaPlayer crashed. The above code works for a short 5 minute long mp3 file, the newly created MediaPlayer will correctly seek to the durationBackup. However, I then decided to test this code with a 1.5 hour long mp3 file, when tested, the newly created MediaPlayer failed to seek to the durationBackup. Instead, the MediaPlayer object created began to play from the start rather than the desired durationBackup.

After further testing, it seems that the seek method is failing since when I tried to seek 7 seconds from the start of the 1.5 hour long mp3 file, the MediaPlayer instead played from the start. When I used the seek method to seek 7 seconds from the start of the 5 minute long file, the MediaPlayer started playing 7 seconds from the start. I suspect this has to do with the size of the mp3 files, however I cannot seem to find a fix for this. Not only does seek(Duration.seconds(7)) not work with the 1.5 hour long mp3 file, setStartTime(Duration.seconds(7)) also does not work with 1.5 hour long mp3 file.

If anyone can help me fix this problem that would be great. There's a mini reproducible example below.

SevenSecondSeekClass

package apprunner;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.stage.Stage;
import javafx.util.Duration;

public class SevenSecondSeekClass extends Application {

    MediaPlayer mediaPlayer;

    public static void main(String[] args) throws MalformedURLException, IOException {
        launch(args);

    }

    public InvalidationListener il = new InvalidationListener() {
        public void invalidated(Observable ov) {
            //Here we just print the current time of the song
            System.out.println(mediaPlayer.getCurrentTime().toSeconds() + " seconds");
        }
    };

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("My");
        Button button0 = new Button("Play 7 seconds from start of 5min Song");
        Button button1 = new Button("Play 7 seconds from start of 1hr Song");
        StackPane layout = new StackPane(new VBox(button0, button1));
        Scene scene = new Scene(layout, 200, 100);
        stage.setScene(scene);
        stage.setWidth(400);
        stage.show();
        File file0 = new File("C:\\Users\\John Doe\\OneDrive\\Desktop\\YourLieInAprilTest\\5minsong.mp3");
        String path0 = file0.toURI().toASCIIString();
        Media media0 = new Media(path0);
        mediaPlayer = new MediaPlayer(media0);
        button0.setOnAction(new EventHandler() {
            @Override
            public void handle(Event arg0) {
                createNewPlayer(media0);
            }
        });

        File file1 = new File("C:\\Users\\John Doe\\downloadedMusic\\1andHalfHourSong.mp3");
        String path1 = file1.toURI().toASCIIString();
        Media media1 = new Media(path1);
        mediaPlayer = new MediaPlayer(media1);
        button1.setOnAction(new EventHandler() {
            @Override
            public void handle(Event arg0) {
                createNewPlayer(media1);
            }
        });
    }

    public void createNewPlayer(Media media) {
        mediaPlayer.stop();
        mediaPlayer.currentTimeProperty().removeListener(il);
        mediaPlayer = new MediaPlayer(media);
        mediaPlayer.setOnPlaying(() -> {
            mediaPlayer.seek(Duration.seconds(7));
            System.out.println("Trying to seek to 7 seconds from start of song");
            mediaPlayer.setOnPlaying(null);
        });
        mediaPlayer.currentTimeProperty().addListener(il);//This will help us print the current time of the song
        mediaPlayer.play();
    }
}

If you're wondering why I'm using.seek at the start of the MediaPlayer rather than just using.setStartTime() it's because.setStartTime() would change the values for.getTotalDuration and wouldn't allow be to go to durations less than the start time set. I need those aspects to be available in my program to maintain a usable UI. Also.setStartTime() isn't working with the 1.5 hour long mp3 file either.

Additional Info

Link to the 5 minute long Mp3 file I used to test. https://drive.google.com/file/d/1CvAafbMviQ7nvKyojnem9GK73LJsD6MJ/view?usp=sharing

Link to the 1.5 hour long mp3 file I used to test. https://drive.google.com/file/d/1KggQct1VnY18m0_4Wik5pfP4RN8-HbUT/view?usp=sharing

I am using JDK 11 and Javafx 17.0.2

System Type: 64-bit operating system, x64-based processor

JRE version: OpenJDK Runtime Environment (11.0.4+11) (build 11.0.4+11)

Java VM: OpenJDK 64-Bit Server VM (11.0.4+11, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)

Windows Edition: Windows 10 Home

I found out that I could fix my problem by converting my mp3 files into m4a files instead. The seeking issue no longer occurs with m4a files.

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