IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

QML Media Player Example

Playing audio and video using Qt Quick.

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

QML Media Player Example

Image non disponible

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.

Image non disponible

Using MediaPlayer and VideoOutput

In main.qml a MediaPlayer instance is connected to a VideoOutput to play back the video:

 
Sélectionnez
    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:

 
Sélectionnez
    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

Image non disponible

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:

 
Sélectionnez
    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:

 
Sélectionnez
    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:

 
Sélectionnez
    MenuBar {
        id: menuBar
        anchors.left: parent.left
        anchors.right: parent.right

        Menu {
            title: qsTr("&File")
            Action {
                text: qsTr("&Open")
                onTriggered: fileDialog.open()

loadUrl

Image non disponible

While urlPopup handles prompting and capturing a url, it is the loadUrl function that interacts with mediaPlayer like so:

 
Sélectionnez
    function loadUrl(url) {
        mediaPlayer.stop()
        mediaPlayer.source = url
        mediaPlayer.play()
    }

Getting meta data

Image non disponible

In the declaration of mediaPlayer, in main.qml, there is the function updateMetadata():

 
Sélectionnez
        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:

 
Sélectionnez
        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

 
Sélectionnez
    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:

 
Sélectionnez
    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:

 
Sélectionnez
        ListView {
            id: trackList
            visible: elements.count > 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:

 
Sélectionnez
        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

Image non disponible

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.

 
Sélectionnez
    required property MediaPlayer mediaPlayer
    property int mediaPlayerState: mediaPlayer.playbackState

Connections:

 
Sélectionnez
        target: mediaPlayer
        function onPlaybackStateChanged() { updateOpacity() }
        function onHasVideoChanged() { updateOpacity() }
    }

Play Pause Stop

Image non disponible

Play, stop and pause interactions with the MediaPlayer object are done like so:

 
Sélectionnez
                    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:

 
Sélectionnez
        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:

 
Sélectionnez
        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:

 
Sélectionnez
        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:

 
Sélectionnez
        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

Image non disponible

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.

 
Sélectionnez
    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

Example project

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+