QML Media Player Example▲
This example demonstrates a simple multimedia player that can play audio and video files using various codecs.
Running the Example▲
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.
Overview▲
At its core this is a QML application, see Getting Started Programming with Qt Quick for information specific to that. This documentation is focused on how this example utilizes the Qt Multimedia QML types.
Using MediaPlayer and VideoOutput▲
In main.qml a MediaPlayer instance is connected to a VideoOutput to play back the video:
MediaPlayer {
id
:
mediaPlayer
function updateMetadata() {
metadataInfo.clear();
metadataInfo.read(mediaPlayer.metaData);
metadataInfo.read(mediaPlayer.audioTracks[mediaPlayer.activeAudioTrack]);
metadataInfo.read(mediaPlayer.videoTracks[mediaPlayer.activeVideoTrack]);
}
videoOutput
:
videoOutput
videoOutput is declared like so:
VideoOutput {
id
:
videoOutput
property bool
fullScreen: false
anchors.top: fullScreen ? parent.top : menuBar.bottom
anchors.bottom: playbackControl.top
anchors.left: parent.left
anchors.right: parent.right
TapHandler {
onDoubleTapped
:
{
parent.fullScreen ? showNormal() : showFullScreen()
parent.fullScreen =
!
parent.fullScreen
}
onTapped
:
{
metadataInfo.visible =
false
audioTracksInfo.visible =
false
videoTracksInfo.visible =
false
subtitleTracksInfo.visible =
false
}
}
}
PlayerMenuBar▲
This QML type handles media selection from a url or local file, exiting the application, viewing meta data, and the selection of available video, audio or subtitle tracks.
Accessing the mediaPlayer object is done through properties:
required property MediaPlayer mediaPlayer
required property VideoOutput videoOutput
required property MetadataInfo metadataInfo
required property TracksInfo audioTracksInfo
required property TracksInfo videoTracksInfo
required property TracksInfo subtitleTracksInfo
fileDialog▲
A FileDialog, fileDialog, is created with an onAccepted function that will stop mediaPlayer, load the source by setting the source property and then play it automatically:
FileDialog {
id
:
fileDialog
title
:
"Please choose a file"
onAccepted
:
{
mediaPlayer.stop()
mediaPlayer.source =
fileDialog.currentFile
mediaPlayer.play()
}
}
This is triggered in the Menu File, which is a child of the MenuBar:
MenuBar {
id
:
menuBar
anchors.left: parent.left
anchors.right: parent.right
Menu {
title
:
qsTr("&File"
)
Action {
text
:
qsTr("&Open"
)
onTriggered
:
fileDialog.open()
loadUrl▲
While urlPopup handles prompting and capturing a url, it is the loadUrl function that interacts with mediaPlayer like so:
function loadUrl(url) {
mediaPlayer.stop()
mediaPlayer.source =
url
mediaPlayer.play()
}
Getting meta data▲
In the declaration of mediaPlayer, in main.qml, there is the function updateMetadata():
function updateMetadata() {
metadataInfo.clear();
metadataInfo.read(mediaPlayer.metaData);
metadataInfo.read(mediaPlayer.audioTracks[mediaPlayer.activeAudioTrack]);
metadataInfo.read(mediaPlayer.videoTracks[mediaPlayer.activeVideoTrack]);
It is called in the following places:
onMetaDataChanged
:
{
updateMetadata() }
onTracksChanged
:
{
audioTracksInfo.read(mediaPlayer.audioTracks);
audioTracksInfo.selectedTrack =
mediaPlayer.activeAudioTrack;
videoTracksInfo.read(mediaPlayer.videoTracks);
videoTracksInfo.selectedTrack =
mediaPlayer.activeVideoTrack;
subtitleTracksInfo.read(mediaPlayer.subtitleTracks);
subtitleTracksInfo.selectedTrack =
mediaPlayer.activeSubtitleTrack;
updateMetadata()
}
Reading MetaData is done by the MetadataInfo type's read() function
function read(metadata) {
if
(metadata) {
for
(var key of metadata.keys()) {
if
(metadata.stringValue(key)) {
elements.append(
{
name: metadata.metaDataKeyToString(key)
, value: metadata.stringValue(key)
}
)
}
}
}
}
The information is displayed via an Overlay item.
Tracks information and control▲
Cliquez pour lire la vidéo
This is defined in TracksInfo.qml and reading available tracks is done in a similar way to MetadataInfo:
function read(metadataList) {
var LanguageKey =
6
;
elements.clear()
elements.append(
{
language: "No Selected Track"
, trackNumber: -
1
}
)
if
(!
metadataList)
return
;
metadataList.forEach(function (metadata, index) {
var language =
metadata.stringValue(LanguageKey);
var label =
language ? metadata.stringValue(LanguageKey) : "track "
+
(index +
1
)
elements.append(
{
language: label
, trackNumber: index
}
)
}
);
}
To set a track, the property selectedTrack is set like so:
ListView {
id
:
trackList
visible
:
elements.count &
gt; 0
anchors.fill: parent
model
:
elements
delegate
:
RowLayout {
width
:
trackList.width
RadioButton {
checked
:
model.trackNumber ===
selectedTrack
text
:
model.language
ButtonGroup.group: group
onClicked
:
selectedTrack =
model.trackNumber
}
}
}
The onSelectectedTrackChanged signal, in each relevant TracksInfo instance in main.qml, is what makes changes to mediaPlayer like so:
id
:
audioTracksInfo
anchors.right: parent.right
anchors.top: videoOutput.fullScreen ? parent.top : menuBar.bottom
anchors.bottom: playbackControl.opacity ? playbackControl.bottom : parent.bottom
visible
:
false
onSelectedTrackChanged
:
mediaPlayer.activeAudioTrack =
audioTracksInfo.selectedTrack
playbackControlPanel▲
This item has controls for Playback control, Play Pause Stop, Playback rate control and Playback seek control.
Playback control▲
This qml type handles media playback and interacts with the MediaPlayer in main.qml.
Here are the property definitions.
required property MediaPlayer mediaPlayer
property int
mediaPlayerState: mediaPlayer.playbackState
Connections:
target
:
mediaPlayer
function onPlaybackStateChanged() {
updateOpacity() }
function onHasVideoChanged() {
updateOpacity() }
}
Play Pause Stop▲
Play, stop and pause interactions with the MediaPlayer object are done like so:
RoundButton {
id
:
pauseButton
radius
:
50.0
text
:
"
\u2016
"
;
onClicked
:
mediaPlayer.pause()
}
RoundButton {
id
:
playButton
radius
:
50.0
text
:
"
\u25B6
"
;
onClicked
:
mediaPlayer.play()
}
RoundButton {
id
:
stopButton
radius
:
50.0
text
:
"
\u25A0
"
;
onClicked
:
mediaPlayer.stop()
}
}
Playback states done using playbackstate like so:
State {
name
:
"playing"
when
:
mediaPlayerState ==
MediaPlayer.PlayingState
PropertyChanges {
target: pauseButton; visible: true
}
PropertyChanges {
target: playButton; visible: false
}
PropertyChanges {
target: stopButton; visible: true
}
}
,
State {
name
:
"stopped"
when
:
mediaPlayerState ==
MediaPlayer.StoppedState
PropertyChanges {
target: pauseButton; visible: false
}
PropertyChanges {
target: playButton; visible: true
}
PropertyChanges {
target: stopButton; visible: false
}
}
,
State {
name
:
"paused"
when
:
mediaPlayerState ==
MediaPlayer.PausedState
PropertyChanges {
target: pauseButton; visible: false
}
PropertyChanges {
target: playButton; visible: true
}
PropertyChanges {
target: stopButton; visible: true
}
}
]
Playback seek control▲
Cliquez pour lire la vidéo
Defined in PlaybackSeekControl.qml, this component comprises of an item with a Text, mediaTime, and Slider, mediaSlider, in a RowLayout.
mediaTime uses MediaPlayer's position property like so:
Text {
id
:
mediaTime
Layout.minimumWidth: 50
Layout.minimumHeight: 18
horizontalAlignment
:
Text.AlignRight
text
:
{
var m =
Math.floor(mediaPlayer.position /
60000
)
var ms =
(mediaPlayer.position /
1000
-
m *
60
).toFixed(1
)
return
`${
m}
:${
ms.padStart(4
, 0
)}
`
}
}
mediaSlider uses the MediaPlayer seekable, duration, and position properties like so:
Slider {
id
:
mediaSlider
Layout.fillWidth: true
enabled
:
mediaPlayer.seekable
to
:
1.0
value
:
mediaPlayer.position /
mediaPlayer.duration
onMoved
:
mediaPlayer.setPosition(value *
mediaPlayer.duration)
}
Playback rate control▲
Cliquez pour lire la vidéo
This type is defined in PlaybackRateControl.qml like so:
Slider {
id
:
slider
Layout.fillWidth: true
snapMode
:
Slider.SnapOnRelease
enabled
:
true
from
:
0.5
to
:
2.5
stepSize
:
0.5
value
:
1.0
onMoved
:
{
mediaPlayer.setPlaybackRate(value) }
}
Text {
text
:
"Rate "
+
slider.value +
"x"
Audio control▲
This type is defined in AudioControl.qml, and utilizes the muted and volume properties of the AudioOutput instantiated within the MediaPlayer, which is instantiated in main.qml.
required property MediaPlayer mediaPlayer
property bool
muted: false
property real volume: volumeSlider.value/
100.
implicitHeight
:
buttons.height
RowLayout {
anchors.fill: parent
Item {
id
:
buttons
width
:
muteButton.implicitWidth
height
:
muteButton.implicitHeight
RoundButton {
id
:
muteButton
radius
:
50.0
icon.source: muted ? "qrc:///Mute_Icon.svg"
: "qrc:///Speaker_Icon.svg"
onClicked
:
{
muted =
!
muted }
}
}
Slider {
id
:
volumeSlider
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
enabled
:
true
to
:
100.0
value
:
100.0