There are two simple ways to play audio in JavaFX, depending on both the size of the file, and the control you need to have over how it’s played.

Short sound files can be played in JavaFX by creating an AudioClip object from the sound file and invoking play(). Longer files can be opened more efficiently by loading the audio file in as a Media component and loading it into JavaFX’s MediaPlayer. Media objects are more memory-efficient, because they only decompress sections of audio as the file is played.

The MediaPlayer also has significantly more control over how the audio is played – from multi-track playback to jumping to particular time stamps in a track.

AudioClipMediaPlayer
Play
Pause
Stop
Rate
Right/Left Balance
Equalizer
Mute
Jump to timepoint
Playback Events
Internal Error Property
Internal volume
Memory buffering

Depending on how much control you need, you can get hugely different results from both objects. This article goes through how to create and play sounds using both.

What you’ll get from this tutorial

Because the two methods give you such different levels of control over a sound file’s playback, I’ve separated the first part of the article into two sections.

That covers how to play music in the background. To play a sound based on something the user’s done? For that, I’ll go through how to start a sound playing from an ActionEvent whenever your user clicks a button.

I mention this one because a lot of JavaFX UI development is event-driven. In fact, the vast majority of UI updates can be driven by events and property binding. Check out the links for my comprehensive guides on both.

Playing short sounds with an AudioClip

For short audio clips that won’t take up much memory, I’d always use the AudioClip object, which completely decompresses the sound file and holds it in memory. That’s great for firing off sounds with low latency, because the clip is immediately ready to play.

AudioClip buzzer = new AudioClip(getClass().getResource("/audio/buzzer.mp3").toExternalForm());

The AudioClip constructor accepts a String, but it’s really expecting the String form of a URL. The best way to do that in JavaFX is through the class’s URL-resolver which we access using getResource(). To convert the URL to a String, we call toExternalForm().

If you’ve not done that before, check out the drop-down for more details.

The AudioClip object is designed as a fire-and-forget. So, once you’ve instantiated it, just invoke play() and JavaFX will handle the rest.

buzzer.play();

You can stop the sound with stop(), but that’s about as much control as you’ll get with the AudioClip class. If you need more control, you might want to consider creating a Media object and loading that into a MediaPlayer. That’s also true if you sound file is large enough that loading it all into memory might cause problems.

Playing longer audio files with the JavaFX MediaPlayer

The downside of the AudioClip is that along with its limited media control options, it loads the entire clip – uncompressed – into memory. The Media object instead only loads a portion of the sound into memory during playback.

To load a sound file into a Media component, you instantiate it in exactly the same way as with the AudioClip, by getting its location as a URL. If you’ve skipped down and want to check out more information about the getResource() method, check out the green dropdown above on resources.

Media buzzer = new Media(getClass().getResource("/audio/buzzer.mp3").toExternalForm());

Once created, we can load the Media into a MediaPlayer object, which gives us control over the playback.

MediaPlayer mediaPlayer = new MediaPlayer(buzzer);

Now we have our MediaPlayer we can do significantly more with our audio file. In this case, however, we just want to take advantage of its memory buffering. To start the sound playing, you just need to invoke play().

mediaPlayer.play();

That covers starting music running, but what happens when you want to start it from something your user’s done? For that, we’ll need to hook into the Scene’s underlying event management.

Playing a sound on click with JavaFX

Almost all user interface interactions in JavaFX are driven by either events, or properties and binding. In this case, the user’s interaction with our button is going to set off an ActionEvent. We’ll use that to start our sound playing.

If you’re adding sound effects to user interactions, I’d probably use the AudioClip; for longer tracks, I’d use the MediaPlayer.

To make use of the ActionEvent the button creates, I’ll create an EventHandler that will make our sound play each time the button is clicked. Because event handlers are a Functional Interface, we can define them as a lambda for brevity.

AudioClip buzzer = new AudioClip(getClass().getResource("/audio/buzzer.mp3").toExternalForm());

Button myButton = new Button("Press me for sound!");
myButton.setOnAction(event -> {
    buzzer.play();
});

Obviously don’t forget to include your button in the Scene…

If you have a lot of sounds, and you don’t want to hold them all in memory, you could create an AudioClip anonymously every time your button gets clicked.

Button myButton = new Button("Press me for sound!");
myButton.setOnAction(event -> {
    new AudioClip(
            getClass()
                    .getResource("/audio/buzzer.mp3")
                    .toExternalForm())
            .play();
});

Once the reference to the AudioClip gets lost, the garbage collector will come and fetch it, freeing up the memory for you to use elsewhere.

Finally, if you need to keep track of a sound clip’s status once it’s started playing, you’ll need to use the MediaPlayer object. This tends to be more useful for longer tracks like music tracks, but you can use it for either really.

To do this, we can use the Media object inside a MediaPlayer, which will track the current status of the media through its status property.

Media buzzer = new Media(getClass().getResource("/audio/longTrack.mp3").toExternalForm());
MediaPlayer mediaPlayer = new MediaPlayer(buzzer);

Button myButton = new Button("Press me for sound!");
myButton.setOnAction(event -> {
    if(mediaPlayer.getStatus() != MediaPlayer.Status.PLAYING){
        mediaPlayer.play();
    }
});

Conclusions

Playing sounds in JavaFX can be as simple as loading the resource into an AudioClip. The AudioClip is designed for short sounds – completely loaded into memory – in cases where you don’t need to control playback.

For longer sounds, or in cases where you need more control over the sound’s playback, the Media component can be wrapped in a MediaPlayer to give you significantly more control over how the sound file is played.

In both cases, the sound file’s playback can be started by invoking play() on the AudioClip or MediaPlayer object you’ve created.