2

I'm using 320 kbps roughly 1 hour long MP3 files. The project I'm working on would seek in a collection of music inside an MP3 file so that it can shuffle the songs. I would give the timestamps to the program and it would seek to the song. It would work if JavaFX's seek method wasn't highly inaccurate.

After using MediaPlayer.seek(duration) The MediaPlayer.getCurrentTime() returns the duration we seeked to as expected. However if we listen to the mp3 file(either without seeking or in an external mp3 player) we realize that the time reported and reality is very different, sometimes even seconds.

For example MediaPlayer.seek(Duration.millis(2000)) results seeking to 0 seconds. A 2 second failure rate is not acceptable.

With WAV it seems to work. Though it does not with MP3.

The two workarounds I think so far are possible:

  • Writing an MP3 Decoder and Player which doesn't have the bug
  • Using uncompressed WAV files

Does anyone know anything better?

If anyone needs the source code there isn't much more in it:

public static void main(String[] args) {
        MediaPlayer player = null;
        JFXPanel fxPanel = new JFXPanel(); //To initialize JavaFX
        try {
            String url = new File("E:\\Music\\test.mp3").toURI().toURL().toExternalForm();
            player = new MediaPlayer(new Media(url));
            System.out.println("File loaded!");
        } catch (MalformedURLException e) {
            //e.printStackTrace();
            System.out.println("Error with filename!");
            System.exit(0);
        }

        player.play();

        System.out.println("Playing!");

        while (true)
        {
            Scanner reader = new Scanner(System.in);
            String string = reader.nextLine();
            if (string.equals("Exit")) System.exit(0);
            else if (string.equals("Seek"))
            {
                player.seek(Duration.millis(2000)); //this seeks to the beggining of the file
                player.pause();
                try {
                    Thread.sleep(100); //player.getCurrentTime() doesn't update immediately
                } catch (InterruptedException e) { }
                System.out.println("Time: " + player.getCurrentTime().toMillis() + " / " + player.getTotalDuration().toMillis());
                player.play();
            }
        }
    }
Daniel Sharp
  • 169
  • 1
  • 2
  • 12
  • JavaFX [does not support OGG](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/media/package-summary.html), so I am unsure why you reference it in your question. – jewelsea Sep 28 '15 at 23:39
  • JavaFX is a maintains a [single-threaded programming model](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html) for user application code, you should probably rewrite your test program to ensure that all API calls (read or write) to the JavaFX media system are performed on the JavaFX application thread (see `Platform.runLater()` or just use an [`Application`](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html)). When you do so, be careful not to stall or sleep the JavaFX application thread. – jewelsea Sep 28 '15 at 23:54

2 Answers2

0

I would recommend using the javazoom library. It is an open source java library that already has this stuff written without errors(At least none that I found).

Source http://www.javazoom.net/index.shtml

kayleighsdaddy
  • 670
  • 5
  • 15
0

Place your call to the seek method off the UI thread or your UI will hang.

new Thread(() ->player.seek(Duration.millis(2000))).start();
Jason Pratt
  • 121
  • 4