Search code examples
javalinuxjavafxmp3

Error creating JavaFX MediaPlayer using mp3 on Ubuntu 23.10


The following code:

public class HelloWorld extends Application {
    @Override
    public void start(Stage primaryStage) {
//        String audioFilePath = "AudioFileWithWavFormat.wav";
        String audioFilePath = "AudioFileWithMp3Format.mp3";

        String url = getClass().getClassLoader().getResource(audioFilePath).toExternalForm();
        Media media = new Media(url);
        MediaPlayer mp3Player = new MediaPlayer(media);
        mp3Player.setOnPlaying(() -> System.out.println("Playback started"));
        mp3Player.play();

        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

...works for the .wav but the .mp3 causes this error:

MediaException: UNKNOWN : com.sun.media.jfxmedia.MediaException: Could not create player! : com.sun.media.jfxmedia.MediaException: Could not create player!
    at javafx.media@21/javafx.scene.media.MediaException.exceptionToMediaException(MediaException.java:147)
    at javafx.media@21/javafx.scene.media.MediaPlayer.init(MediaPlayer.java:518)
    at javafx.media@21/javafx.scene.media.MediaPlayer.<init>(MediaPlayer.java:421)
    at ca.footeware.javafx.squeaker/ca.footeware.javafx.squeaker.HelloWorld.start(HelloWorld.java:25)
    at javafx.graphics@21/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
    at javafx.graphics@21/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
    at javafx.graphics@21/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
    at javafx.graphics@21/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
    at javafx.graphics@21/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at javafx.graphics@21/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics@21/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$10(GtkApplication.java:263)
    at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.sun.media.jfxmedia.MediaException: Could not create player!
    at javafx.media@21/com.sun.media.jfxmediaimpl.NativeMediaManager.getPlayer(NativeMediaManager.java:298)
    at javafx.media@21/com.sun.media.jfxmedia.MediaManager.getPlayer(MediaManager.java:118)
    at javafx.media@21/javafx.scene.media.MediaPlayer.init(MediaPlayer.java:474)


❯ neofetch
            .-/+oossssoo+/-.               craig@notebook 
        `:+ssssssssssssssssss+:`           -------------- 
      -+ssssssssssssssssssyyssss+-         OS: Ubuntu 23.10 x86_64 
    .ossssssssssssssssssdMMMNysssso.       Host: XPS 13 9310 
   /ssssssssssshdmmNNmmyNMMMMhssssss/      Kernel: 6.5.0-14-generic 
  +ssssssssshmydMMMMMMMNddddyssssssss+     Uptime: 59 mins 
 /sssssssshNMMMyhhyyyyhmNMMMNhssssssss/    Packages: 2388 (dpkg), 55 (flatpak), 17 (snap) 
.ssssssssdMMMNhsssssssssshNMMMdssssssss.   Shell: bash 5.2.15 
+sssshhhyNMMNyssssssssssssyNMMMysssssss+   Resolution: 3456x2160 
ossyNMMMNyMMhsssssssssssssshmmmhssssssso   DE: GNOME 45.1 
ossyNMMMNyMMhsssssssssssssshmmmhssssssso   WM: Mutter 
+sssshhhyNMMNyssssssssssssyNMMMysssssss+   WM Theme: Adwaita 
.ssssssssdMMMNhsssssssssshNMMMdssssssss.   Theme: Yaru-sage-dark [GTK2/3] 
 /sssssssshNMMMyhhyyyyhdNMMMNhssssssss/    Icons: Yaru-sage [GTK2/3] 
  +sssssssssdmydMMMMMMMMddddyssssssss+     Terminal: gnome-terminal 
   /ssssssssssshdmNNNNmyNMMMMhssssss/      CPU: 11th Gen Intel i7-1195G7 (8) @ 5.000GHz 
    .ossssssssssssssssssdMMMNysssso.       GPU: Intel TigerLake-LP GT2 [Iris Xe Graphics] 
      -+sssssssssssssssssyyyssss+-         Memory: 6506MiB / 15692MiB 
        `:+ssssssssssssssssss+:`
            .-/+oossssoo+/-. 

Google told me this has happened several times in the past with the mp3 codec not being found. I've installed ubuntu-restricted-extras, libavcodec60, libavformat60 and ffmpeg. I can play mp3's in Rhythmbox and Audacious.

Any ideas?

EDIT: A little more env. detail:

❯ java -version
openjdk version "21.0.1" 2023-10-17
OpenJDK Runtime Environment (build 21.0.1+12-Ubuntu-223.10)
OpenJDK 64-Bit Server VM (build 21.0.1+12-Ubuntu-223.10, mixed mode, sharing)

Downloaded v21.0.1 javafx sdk and modules from https://gluonhq.com/products/javafx/ and extracted to home folder then referenced in Netbeans. Building using a pom that produces a module then I JLink together a runtime. Mostly running in Netbeans as I write code though.


Solution

  • As noted by CraigFoote in comments, an existing issue covers the problem with media playback on your setup.

    Ubuntu 23.10 uses libavcodec60 (https://packages.ubuntu.com/mantic/libavcodec60). We need to add support for libavcodec60.

    Note: Support will be added only for libavcodec based on ffmpeg. libav does not have release for libavcodec60.

    The issue is marked as affecting Ubuntu 23.10, JavaFX 21 and libavcodec 60 as installed through ffmpeg, which are the same software versions mentioned in your question.

    The issue is noted as fixed for JavaFX 22. JavaFX 22 is scheduled for a general availability (GA) release date of March 2024.

    As of the creation of this answer, JavaFX 22 development has not been finalized. However, early access versions of JavaFX are available to try new features and bug fixes for upcoming releases. These can be found in these places:

    I suggest trying one of the early access releases to see if the fix for JDK-8317508 has made it into one of those releases.

    Use the same version for all JavaFX components. For example, if you use version 22-ea+16 for JavaFX Media, use that version for your other JavaFX dependencies.

    The issue has been backported to the JavaFX 21.0.2 branch, which has not been released yet (the current latest stable version of JavaFX is 21.0.1). This means that when 21.0.2 is released, the fix will be available in a long-term support (LTS) release.


    The asker tested with JavaFX 22-ea+16 and noted it resolved the mp3 media playback issue in ubuntu 23.10:

    I modified my pom to bring in openjfx-22-ea+16 and upgraded my jdk to 22-ea (not sure if that was necessary) and ran in netbeans and it played the mp3!

    FAQ

    Does my using modules jlinked to make a runtime mean that others running the app on another machine doesn't need version 22-ea of either the jdk or javafx?

    The short answer to this is yes, the user does not need version 22-ea of either the jdk or javafx to be installed on their system to use your software.

    When you jlink with the 22-ea modules of Java and JavaFX, then jlink will produce a customized Java runtime image with those modules packed inside it. You may not see the JavaFX jmod files listed in a directory of the image. Even if not showing in a directory, they will still be packed inside the runtime image files in a jimage format.

    The user does not need a version of either the jdk or javafx installed separately on their machine to use your software, because everything needed from the Java runtime and JavaFX side, as well as all your application code, dependent Java libraries, and native components of the JDK and JavaFX are already packed in the image you created.

    You can bundle the image generated by jlink in a package format of your choosing (e.g. a .tgz or .zip file) and the user can download and unpack it, then directly run your software using the script generated by jlink.

    How to ensure ffmpeg is installed on the system.

    For JavaFX media capabilities to work, appropriate media playback facilities of the underlying native platform need to be installed.

    For Ubuntu 23.10, the ffmpeg package needs to be installed to allow some JavaFX playable media formats such as mp3 to work.

    The native packaging system of the OS (e.g. .deb packages for Ubuntu) can assist in packaging and installing a working application. In the package definition, specify the required dependent packages, e.g. ffmpeg. When somebody downloads and installs your software, the Ubuntu package manager will ensure that the correct dependencies are installed for your application to function.

    A .deb installation package based on a native Java image that has been output by jlink can be created:

    • Manually by using the command line tools of the OS OR
    • Using the jpackage software supplied with the JDK OR
    • Using a plugin in a build tool such as Maven or Gradle that invokes jpackage.

    An alternative to using a .deb package for your application, is to modify the default startup script generated by jlink to check if ffmpeg is installed before launching your application and use the native package manager on the system to install it if it is not yet available.

    Or you could run a check when the application starts up and, if the media fails, provide a message to the user that media functions are disabled until they install ffmpeg on their system. Perhaps a check using the ConditionalFeature.MEDIA would work to see if media playback is supported, but I think an additional test of media usage would be more reliable.