What the Media API is
How to play short audio clips
How to play back media (audios and videos) and how to track different aspects of the playback such as playback rate, volume, playback time, repeating the playback, and media errors
Understanding the Media API
JavaFX supports playing audio and video through the JavaFX Media API. HTTP live streaming of static media files and live feeds are also supported. A number of media formats are supported, including AAC, AIFF, WAV, and MP3. FLV containing VP6 video and MP3 audio and MPEG-4 multimedia container with H.264/AVC video formats are also supported. The support for a specific media format is platform dependent. Some media playback features and formats do not require any additional installations; some require third-party software to be installed. Please refer to the web page at https://openjfx.io/javadoc/17/javafx.media/javafx/scene/media/package-summary.html#SupportedMediaTypes for details on the system requirements and supported media formats in JavaFX.
AudioClip is used to play a short audio clip with minimal latency. Typically, this is useful for sound effects, which are usually short audio clips. Use the Media, MediaPlayer, and MediaView classes for playing audios and videos of longer length.
The Media and MediaPlayer classes are used to play audios as well as videos. An instance of the Media class represents a media resource, which could be an audio or a video. It provides the information about the media, for example, the duration of the media. An instance of the MediaPlayer class provides controls for playing a media.
An instance of the MediaView class provides the view of a media being played by a MediaPlayer. A MediaView is used for viewing a video.
Several things can go wrong when you attempt to play a media, for example, the media format may not be supported or the media content may be corrupt. An instance of the MediaException class represents a specific type of media error that may occur during media playback. When a media-related error occurs, a MediaErrorEvent is generated. You can handle the error by adding an appropriate event handler to the media objects.
I will cover the details of using these classes and other supporting classes in the Media API in this chapter.
Playing Short Audio Clips
An instance of the AudioClip class is used to play a short audio clip with minimal latency. Typically, this is useful for playing short audio clips, for example, a beep sound when the user makes an error or producing short sound effects in gaming applications.
The AudioClip class provides only one constructor that takes a URL in string form, which is the URL of the audio source. The audio clip is immediately loaded into memory in raw, uncompressed form. This is the reason why you should not use this class for long-playing audio clips. The source URL could use the HTTP, file, and JAR protocols. This means that you can play an audio clip from the Internet, the local file system, and a JAR file.
Playing Back an Audio Clip Using an AudioClip Instance
cycleCount
volume
rate
balance
pan
priority
All of the preceding properties, except the cycleCount, can be set on the AudioClip class. Subsequent calls to the play() method will use them as defaults. The play() method may also override the defaults for a specific playback. The cycleCount property must be specified on the AudioClip, and all subsequent playbacks will use the same value.
AudioClip.INDEFINITE
MediaPlayer.INDEFINITE
Animation.INDEFINITE
The volume specifies the relative volume of the playback. The valid range is 0.0 to 1.0. A value of 0.0 represents muted, whereas 1.0 represents full volume.
The rate specifies the relative speed at which the audio is played. The valid range is 0.125 to 8.0. A value of 0.125 means the clip is played eight times slower, and the value of 8.0 means the clip will play eight times faster. The rate affects the playtime and the pitch. The default rate is 1.0, which plays the clip at the normal rate.
The balance specifies the relative volume for the left and right channels. The valid range is –1.0 to 1.0. A value of –1.0 sets the playback in the left channel at normal volume and mutes the right channel. A value of 1.0 sets the playback in the right channel at normal volume and mutes the left channel. The default value is 0.0, which sets the playback in both channels at normal volume.
The pan specifies the distribution of the clip between the left and right channels. The valid range is –1.0 to 1.0. A value of –1.0 shifts the clip entirely to the left channel. A value of 1.0 shifts the clip entirely to the right channel. The default value is 0.0, which plays the clip normally. Setting the value for pan for a mono clip has the same effect of setting the balance. You should change the default for this property only for audio clips using stereo sound.
The priority specifies the priority of the clip relative to other clips. It is used only when the number of playing clips exceeds the system limits. The playing clips with the lower priority will be stopped. It can be set to any integer. The default priority is set to zero.
Void play()
void play(double volume)
void play(double volume, double balance, double rate, double pan, int priority)
The no-args version of the method uses all of the properties set on the AudioClip. The other two versions can override the specified properties for a specific playback. Suppose the volume for the AudioClip is set to 1.0. Calling play() will play the clip at volume 1.0, and calling play(0.20) will play the clip at volume 0.20, leaving the volume property for the AudioClip unchanged at 1.0. That is, the play() method with parameters allows you to override the AudioClip properties on a per-playback basis.
The AudioClip class contains an isPlaying() method to check if the clip is still playing. It returns true if the clip is playing. Otherwise, it returns false.
Playing Media
JavaFX provides a unified API to work with audio and videos. You use the same classes to work with both. The Media API internally treats them as two different types of media that is transparent to the API users. From here onward, I will use the term media to mean both audio and video, unless specified otherwise.
Media
MediaPlayer
MediaView
Creating a Media Object
duration
width
height
error
onError
The duration specifies the duration of the media in seconds. It is a Duration object. If the duration is unknown, it is Duration.UNKNOWN.
The width and height give the width and height of the source media in pixels, respectively. If the media does not have width and height, they are set as zero.
Creating a MediaPlayer Object
You can get the reference of the media from the MediaPlayer using the getMedia() method of the MediaPlayer class.
Like the Media class, the MediaPlayer class also contains error and onError properties to report errors. When an error occurs on the MediaPlayer, the same error is also reported on the Media object.
The MediaPlayer class contains many properties and methods. I will discuss them in subsequent sections.
Creating a MediaView Node
A MediaView is a node. It provides the view of a media being played by a MediaPlayer. Note that an audio clip does not have visuals. If you try creating a MediaView for an audio content, it would be empty. To watch a video, you create a MediaView and add it to a scene graph.
public MediaView()
public MediaView(MediaPlayer mediaPlayer)
Combining Media, MediaPlayer, and MediaView
The content of a media can be used simultaneously by multiple Media objects . However, one Media object can be associated with only one media content in its lifetime.
A Media object can be associated with multiple MediaPlayer objects. However, a MediaPlayer is associated with only one Media in its lifetime.
A Media Player Example
Using the Media, MediaPlayer, and MediaView Classes to Play a Media
The size of the MediaView is set 400px wide by 300px tall. If the media is a video, the video will be scaled to fit in this size. You will see an empty area for the audios. You can enhance the MediaView later, so it will take as much space as the media needs.
The Play and Stop buttons are created. Event handlers are added to them. They can be used to begin and stop the playback, respectively. When the media is already playing, clicking the Play button stops the playback and plays the media again.
When you run the program, the video should play automatically. You can stop and replay it using the buttons at the bottom of the screen. If there is an error, you will see an error message on the console.
The QuickMediaPlayer class can play audios as well as videos. All you need to do is change the URL of the source to point to the media you want to play.
Handling Playback Errors
MEDIA_CORRUPTED
MEDIA_INACCESSIBLE
MEDIA_UNAVAILABLE
MEDIA_UNSPECIFIED
MEDIA_UNSUPPORTED
OPERATION_UNSUPPORTED
PLAYBACK_HALTED
PLAYBACK_ERROR
UNKNOWN
The MEDIA_CORRUPTED error type indicates that the media is corrupted or invalid. The MEDIA_INACCESSIBLE error type indicates that the media is inaccessible. However, the media may exist. The MEDIA_UNAVAILABLE error type indicates that the media does not exist or it is unavailable. The MEDIA_UNSPECIFIED error type indicates that the media has not been specified. The MEDIA_UNSUPPORTED error type indicates that the media is not supported by the platform. The OPERATION_UNSUPPORTED error type indicates that the operation performed on the media is not supported by the platform. The PLAYBACK_HALTED error type indicates an unrecoverable error that has halted the playback. The PLAYBACK_ERROR error type indicates a playback error that does not fall into any other described categories. The UNKNOWN error type indicates that an unknown error has occurred.
Media error handlers are invoked on the JavaFX Application Thread. Therefore, it is safe to update the scene graph from the handlers.
State Transitions of the MediaPlayer
UNKNOWN
READY
PLAYING
PAUSED
STALLED
STOPPED
HALTED
DISPOSED
play()
pause()
stop()
dispose()
When a MediaPlayer is created, its status is UNKNOWN. Once the media is prerolled and it is ready to be played, the MediaPlayer transitions from UNKNOWN to READY. Once the MediaPlayer exits the UNKNOWN status, it cannot reenter it in its lifetime.
The MediaPlayer transitions to the PLAYING status when the play() method is called. This status indicates that the media is playing. Note if the autoPlay property is set to true, the MediaPlayer may enter the PLAYING status without calling the play() method explicitly after it is created.
When the MediaPlayer is playing, it may enter the STALLED status if it does not have enough data in its buffer to play. This status indicates that the MediaPlayer is buffering data. When enough data are buffered, it goes back to the PLAYING status. When a MediaPlayer is stalled, calling the pause() and stop() methods, it transitions to the PAUSED and STOPPED status, respectively. In that case, the buffering continues; however, the MediaPlayer does not transition to the PLAYING status once enough data are buffered. Rather, it stays in the PAUSED or STOPPED status.
Calling the pause() method transitions the MediaPlayer to the PAUSED status. Calling the stop() method transitions the MediaPlayer to the STOPPED status.
In cases of an unrecoverable error, the MediaPlayer transitions to the HALTED terminal status. This status indicates that the MediaPlayer cannot be used again. You must create a new MediaPlayer if you want to play the media again.
The dispose() method frees all of the resources associated with the MediaPlayer. However, the Media object used by the MediaPlayer can still be used. Calling the dispose() method transitions the MediaPlayer to the terminal status DISPOSED.
It is common to display the status of the MediaPlayer in an application. Add a ChangeListener to the status property to listen for any status changes.
By adding a ChangeListener to the status property
By setting status change handlers
onReady
onPlaying
onRepeat
onStalled
onPaused
onStopped
onHalted
Repeating Media Playback
Tracking Media Time
The current duration of a media playing media
The duration of the media playback
The duration of the media play for one cycle
The start offset time
The end offset time
startTime
stopTime
The read-only currentTime property is the current time offset in the media playback. The read-only cycleDuration property is the difference between the stopTime and startTime. It is the length of playback for each cycle. The read-only totalDuration property specifies the total duration of the playback if the playback is allowed to continue until finished. Its value is the cycleDuration multiplied by the cycleCount. If the cycleCount is INDEFINITE, the totalDuration will be INDEFINITE. If the media duration is UNKNOWN, the totalDuration will be UNKNOWN.
When you play a media from the network, the MediaPlayer may get stalled because it does not have enough data to continue the playback. The read-only bufferProgressTime property gives you the duration for which the media can be played without stalling.
Controlling the Playback Rate
Controlling the Playback Volume
volume
mute
balance
The volume specifies the volume of the audio. The range is 0.0 to 1.0. A value of 0.0 makes the audio inaudible, whereas a value of 1.0 plays it at full volume. The default value is 1.0.
The balance specifies the relative volume for the left and right channels. The valid range is –1.0 to 1.0. A value of –1.0 sets the playback in the left channel at normal volume and mutes the right channel. A value of 1.0 sets the playback in the right channel at normal volume and mutes the left channel. The default value is 0.0, which sets the playback in both channels at normal volume.
Positioning the MediaPlayer
The MediaPlayer is in the STOPPED status.
The media duration is Duration.INDEFINITE.
You pass null or Duration.UNKNOWN to the seek() method.
In all other cases, the position is clamped between the startTime and stopTime of the MediaPlayer.
Marking Positions in the Media
You can associate markers with specific points on the media timeline. Markers are simply text that are useful in a number of ways. You can use them to insert advertisements. For example, you can insert a URL as the marker text. When the marker is reached, you can pause playing the media and play another media. Note that playing another media involves creating new Media and MediaPlayer objects. You can reuse a MediaView. When you are playing the advertisement video, associate the MediaView with the new MediaPlayer. When the advertisement playback is finished, associate the MediaView back to the main MediaPlayer.
Showing Media Metadata
You cannot be sure whether there are metadata in a media or the type of metadata a media may contain. In your application, you can just look for the title, artist, album, and year. Alternatively, you could read all of the metadata and display them in a two-column table. Sometimes, the metadata may contain an embedded image of the artist. You would need to check the class name of the value in the map to use the image.
Customizing the MediaView
fitHeight
fitWidth
preserveRatio
smooth
viewport
x
y
The fitWidth and fitHeight properties specify the resized width and height of the video, respectively. By default, they are zero, which means that the original width and height of the media will be used.
The preserveRatio property specifies whether to preserve the aspect ratio of the media while resizing. By default, it is false.
The smooth property specifies the quality of the filtering algorithm to be used in resizing the video. The default value is platform dependent. If it is set to true, a better-quality filtering algorithm is used. Note that a better-quality filtering takes more processing time. For smaller-sized videos, you may set it to false. For bigger-sized videos, it is recommended to set the property to true.
A viewport is a rectangular region to view part of a graphic. The viewport, x, and y properties together let you specify the rectangular area in the video that will be shown in the MediaView. The viewport is a Rectangle2D that is specified in the coordinate system of the original media frame. The x and y properties are the coordinates of the upper-left corner of the viewport. Recall that you can have multiple MediaViews associated with a MediaPlayer. Using multiple MediaViews with viewports, you can give the audience the impression of splitting the video. Using one MediaView with a viewport, you can let the audience view only part of the viewable area of the video.
A MediaView is a node. Therefore, to give a better visual experience to the audience, you can also apply effects and transformations to the MediaView.
Developing a Media Player Application
The application should have the ability to specify a media source.
The application should provide a UI to control the media playback.
When the media source changes, you will need to create a new Media object and a MediaPlayer. You can reuse the MediaView by setting the new MediaPlayer using its setMediaPlayer() method.
Summary
JavaFX supports playing audio and video through the JavaFX Media API. HTTP live streaming of static media files and live feeds are also supported. A number of media formats are supported, such as AAC, AIFF, WAV, and MP3. FLV containing VP6 video and MP3 audio and MPEG-4 multimedia container with H.264/AVC video formats are supported. The support for a specific media format is platform dependent. Some media playback features and formats do not require any additional installations; but some require third-party software to be installed. The Media API consists of several classes. All classes in the API are included in the javafx.scene.media package.
An AudioClip is used to play a short audio clip with minimal latency. Typically, this is useful for sound effects, which are usually short audio clips. Use the Media, MediaPlayer, and MediaView classes for playing audios and videos of longer length.
The Media and MediaPlayer classes are used to play audios as well as videos. An instance of the Media class represents a media resource, which could be an audio or a video. It provides the information about the media, for example, the duration of the media. An instance of the MediaPlayer class provides controls for playing a media. A MediaPlayer always indicates the status of the playback. The current status of a MediaPlayer is indicated by the read-only status property. The status changes when an action is performed on the MediaPlayer. The status can be unknown, ready, playing, paused, stalled, stopped, halted, or disposed.
An instance of the MediaView class provides the view of a media being played by a MediaPlayer. A MediaView is used for viewing a video.
Several things can go wrong when you attempt to play a media, for example, the media format may not be supported or the media content may be corrupt. An instance of the MediaException class represents a specific type of media error that may occur during media playback. When a media-related error occurs, a MediaErrorEvent is generated. You can handle the error by adding an appropriate event handler to the media objects.
The next chapter will discuss FXML, which is an XML-based language to build user interfaces for a JavaFX application.