QML 媒体播放器示例

使用 QMLMediaPlayer 类型播放音频和视频。

本示例演示了一个简单的多媒体播放器,可使用各种编解码器播放音频和视频文件。

运行示例

要从 Qt Creator,打开Welcome 模式,然后从Examples 中选择示例。更多信息,请参阅Qt Creator: 教程:构建并运行

实例化媒体播放器

本例中 QML 代码的入口点是Main.qml 。这里创建了ApplicationWindow ,并设置了idtitlewidthheight 等属性。

ApplicationWindow {
    id: root
    title: qsTr("Multimedia Player")
    width: 1280
    height: 720

接下来创建MediaPlayer ,并定义负责视频和音频输出的两个属性。首先是渲染视频取景器的videoOutput ,其次是为播放器提供音频输出的audioOutput

MediaPlayer {
    id: mediaPlayer
    ...
videoOutput: videoOutput
audioOutput: AudioOutput {
    id: audio
    muted: playbackController.muted
    volume: playbackController.volume
}
    ...
VideoOutput {
    id: videoOutput
    anchors.fill: parent
    visible: mediaPlayer.mediaStatus > 0

    TapHandler {
        onDoubleTapped: {
            root.fullScreen ?  root.showNormal() : root.showFullScreen()
            root.fullScreen = !root.fullScreen
        }
    }
}

MediaPlayermediaStatus 属性大于 0 时,VideoOutput 类型的visible 属性将被设置为truemediaStatus 是枚举类型,当未设置媒体时等于 0,否则大于 0。因此,当媒体已设置时,VideoOutput 是可见的。

MediaPlayer 类型有一个名为onErrorOccurred 的信号属性,可专门用于处理错误。在这种情况下,信号会使用open() 方法打开MessageDialog ,并将其text 属性设置为MediaPlayer 属性errorString

onErrorOccurred: {
    mediaError.text = mediaPlayer.errorString
    mediaError.open()
}

播放控制

为了拥有一个可用的媒体播放器,需要有一个控制播放的界面。该界面在它自己的组件文件PlaybackControl.qml 中创建,并在Main.qml 中实例化。

PlaybackControl {
    id: playbackController
    ...
onTracksChanged: {
    audioTracksInfo.read(mediaPlayer.audioTracks)
    videoTracksInfo.read(mediaPlayer.videoTracks)
    subtitleTracksInfo.read(mediaPlayer.subtitleTracks, 6) /* QMediaMetaData::Language = 6 */
    updateMetadata()
    mediaPlayer.play()
}

创建时,对象会被转发到这一类型,如音轨信息、元数据信息和MediaPlayer 对象本身。在PlaybackControl.qml 中,每个对象都有一个required property ,这意味着在创建PlaybackControl 对象时必须设置这些属性。

Item {
    id: playbackController

    required property MediaPlayer mediaPlayer
    required property MetadataInfo metadataInfo
    required property TracksInfo audioTracksInfo
    required property TracksInfo videoTracksInfo
    required property TracksInfo subtitleTracksInfo

这些重放控制可分为多个部分。面板左上方有一组用于打开文件的按钮,可以从文件资源管理器中选择文件,也可以输入 URL。文件通过设置source 属性加载到MediaPlayer 中。这两个按钮都是通过CustomButton custom component 实例化的。

CustomButton {
    id: fileDialogButton
    icon.source: "../images/open_new.svg"
    flat: false
    onClicked: fileDialog.open()
}

CustomButton {
    id: openUrlButton
    icon.source: "../images/link.svg"
    flat: false
    onClicked: urlPopup.open()
}

在该面板上创建了三个按钮并置于中心位置,分别用于播放、暂停和向前或向后搜索 10 秒钟。媒体的播放和暂停分别使用play()pause() 方法。要知道何时绘制播放或暂停按钮,需要查询playbackState 属性。例如,当它等于枚举值MediaPlayer.PlayingState 时,就会绘制暂停按钮。

CustomRoundButton {
    id: playButton
    visible: playbackController.mediaPlayer.playbackState !== MediaPlayer.PlayingState
    icon.source: "../images/play_symbol.svg"
    onClicked: playbackController.mediaPlayer.play()
}

CustomRoundButton {
    id: pauseButton
    visible: playbackController.mediaPlayer.playbackState === MediaPlayer.PlayingState
    icon.source: "../images/pause_symbol.svg"
    onClicked: playbackController.mediaPlayer.pause()
}

要向前或向后浏览 10 秒,MediaPlayer 类型的position 将递增 10,000 毫秒,并使用setPosition() 方法进行设置。

CustomRoundButton {
    id: forward10Button
    icon.source: "../images/forward10.svg"
    onClicked: {
        const pos = Math.min(playbackController.mediaPlayer.duration,
                           playbackController.mediaPlayer.position + 10000)
        playbackController.mediaPlayer.setPosition(pos)
    }
}

播放搜索和音频

PlaybackControl.qml 中,一个AudioControl 和一个PlaybackSeekControl 类型被实例化。它们都在各自的组件文件中定义,分别负责音量控制和播放搜索。AudioControl 类型定义了一个静音按钮和一个Slider ,来自QtQuick Controls ,用于设置播放器的音量。这两个属性都是通过定义mutevolume 属性公开的,并可通过Main.qml 中的AudioOutput 定义访问。

property alias muted: muteButton.checked
property real volume: slider.value

PlaybackSeekControl 使用一个RowLayout ,其中包含一个Slider 和两侧的一个Text 项。这两个Text 项显示当前时间和正在播放的媒体的剩余时间。这两个时间都是通过MediaPlayer 类型的两个属性计算得出的:position (以毫秒为单位显示当前播放位置)和duration (以毫秒为单位显示媒体持续时间)。

Text {
    id: currentTime
    Layout.preferredWidth: 45
    text: seekController.formatToMinutes(seekController.mediaPlayer.position)
    horizontalAlignment: Text.AlignLeft
    font.pixelSize: 11
}
    ...
Text {
    id: remainingTime
    Layout.preferredWidth: 45
    text: seekController.formatToMinutes(seekController.mediaPlayer.duration - seekController.mediaPlayer.position)
    horizontalAlignment: Text.AlignRight
    font.pixelSize: 11
}

只有当媒体播放器是可寻址的,而不是实时媒体时,才会启用SliderMediaPlayer 类型有一个名为seekable 的属性。Slidervalue 是通过MediaPlayerpositionduration 属性计算得出的。

enabled: seekController.mediaPlayer.seekable
value: seekController.mediaPlayer.position / seekController.mediaPlayer.duration

元数据和轨道信息

PlaybackControl 类型实例化了一个SettingsPopup ,其中包含当前加载媒体的元数据信息和曲目选择,以及更新播放速率的功能。该PopupSettingsPopup.qml 中定义。

元数据包含在自己的组件文件MetadataInfo.qml 中。它包含一个ListModel 、一个用于清除元数据的函数clear() 和一个用于填充元数据的函数read(MediaMetadata metadata)read(MediaMetadata metadata) 函数将MediaMetaData 类型的对象作为参数,并浏览其键值结构,将其数据提取到ListViewmodel 中。使用的方法有keys() 和 {stringValue(Key键)},前者返回MediaMetaData 的所有键值,后者返回给定keyvalue

function read(metadata) {
    if (!metadata)
        return
    for (const key of metadata.keys())
        if (metadata.stringValue(key))
            listModel.append({
                                name: metadata.metaDataKeyToString(key),
                                value: metadata.stringValue(key)
                            })
}

ListModel {
    id: listModel
}

然后,数据会以ListView 类型显示在SettingsPopup.qml 中。该ListViewdelegate 是一行两个Text 项,对应于从MediaMetaData 项中抽象出来的键值对。

Popup 的另一侧是播放速率控制以及音频、视频和字幕的音轨选择。播放速率可从ComboBox 中选择,并通过属性playbackRate 进行设置。

settingsController.mediaPlayer.playbackRate = (currentIndex + 1) * 0.25

TracksInfo.qml 中定义的TracksInfo 类型包含音轨数据。更具体地说,ListModel 包含音轨的标题,或字幕的语言。这些信息通过调用TracksInfo 类型中定义的read(MediaMetadata mediaMetadata) 函数填充到Main.qml 中。

onTracksChanged: {
    audioTracksInfo.read(mediaPlayer.audioTracks)
    videoTracksInfo.read(mediaPlayer.videoTracks)
    subtitleTracksInfo.read(mediaPlayer.subtitleTracks, 6) /* QMediaMetaData::Language = 6 */
    updateMetadata()
    mediaPlayer.play()
}

然后在SettingsPopup 中的ComboBoxes 中查询TracksInfo 中定义的model ,以选择当前音轨。

settingsController.mediaPlayer.pause()
tracksInfo.selectedTrack = currentIndex
settingsController.mediaPlayer.play()

示例项目 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.