本页内容

QML 媒体播放器示例

使用 QML 的 `MediaPlayer ` 类型播放音频和视频。

显示播放控制按钮和视频预览区域的视频播放器

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

运行示例

您可以通过以下方式运行该示例:

实例化 MediaPlayer

本示例中 QML 代码的入口点是Main.qml 。在此处创建了一个ApplicationWindow ,并设置了id 、title 、width 和height 等属性。

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
        }
    }
}

当MediaPlayer 的mediaStatus 属性大于0时,VideoOutput 类型的visible 属性将设置为true 。mediaStatus 属于枚举类型,当未设置媒体时其值为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()
}

在该面板上创建了三个按钮并将其居中显示,分别用于播放、暂停以及向前或向后快进/快退十秒。通过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()
}

若要向前或向后跳转十秒,需将类型为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 类型定义了一个静音按钮,以及一个来自QtQuick Controls 的Slider ,用于设置播放器的音量。这两个属性通过定义mute 和volume 属性对外暴露,并可通过Main.qml 中AudioOutput 的定义进行访问。

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

PlaybackSeekControl 使用一个RowLayout ,其中包含一个Slider ,其两侧各有一个Text 项。这两个Text 项分别显示正在播放媒体的当前时间和剩余时间。这两者均通过两个MediaPlayer 类型的属性进行计算:position 提供当前播放位置(以毫秒为单位),duration 提供媒体的时长(以毫秒为单位)。

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

Slider 仅在媒体播放器支持快进/快退(而非直播媒体等)时才启用。MediaPlayer 类型为此提供了一个名为seekable 的属性。Slider 的value 是通过MediaPlayer 的position 和duration 属性计算得出的。

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

元数据和轨道信息

PlaybackControl 类型实例化了一个SettingsPopup ,其中包含当前加载的媒体和所选曲目的元数据信息,并具备更新播放速率的能力。该Popup 在SettingsPopup.qml 中定义。

用户可自定义的播放设置和元数据信息

元数据包含在其独立的组件文件MetadataInfo.qml 中。该文件包含一个ListModel 对象、一个用于清空该对象的函数clear() ,以及一个用于填充该对象的函数read(MediaMetadata metadata) 。read(MediaMetadata metadata) 函数接受一个类型为MediaMetaData 的对象作为参数,并遍历其键值结构,将数据提取到ListView 的model 中。用于实现此操作的方法包括keys() (返回MediaMetaData 中的所有键)和{stringValue(Key key)}(针对给定的key 返回value )。

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
}

随后,数据将通过SettingsPopup.qml 以ListView 类型显示。该ListView 的delegate 由两项Text 组成,分别对应从MediaMetaData 项中抽象出的键值对。

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

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

名为TracksInfo 的类型(定义于TracksInfo.qml )包含有关音轨的数据。更具体地说,它包含一个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 中ComboBox文件中的model (定义于TracksInfo ),以选定当前音轨。

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

示例项目 @ code.qt.io

© 2026 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.