QML 媒体播放器示例
使用 QML MediaPlayer
类型播放音频和视频。
此示例演示了一个简单的多媒体播放器,可以使用各种编解码器播放音频和视频文件。
运行示例
要从 Qt Creator 运行示例,请打开 欢迎模式 并从 示例 中选择示例。有关更多信息,请访问 构建和运行示例。
实例化 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
属性设置为名为 errorString
的 MediaPlayer
属性。
onErrorOccurred: { mediaError.open() mediaError.text = mediaPlayer.errorString }
播放控制
为了有一个可用的媒体播放器,需要有一个用于控制播放的接口。这在一个单独的组件文件 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
自定义组件
实例化的。
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`使用一个包含一个`Slider`和一个位于其两侧的`Text`项的`RowLayout`。这两个`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 }
当媒体播放器可搜索且不是如直播媒体时,才启用`Slider`。`MediaPlayer`类型有一个名为`seekable`的属性来表示这一点。使用`position`和`duration`属性计算`Slider`的`value`。
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`的值。
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
,或对于特定于字幕的语言。此信息通过在 Main.qml
中调用在 TracksInfo
类型中定义的 read(MediaMetadata mediaMetadata)
函数来填充。
onTracksChanged: { audioTracksInfo.read(mediaPlayer.audioTracks) videoTracksInfo.read(mediaPlayer.videoTracks) subtitleTracksInfo.read(mediaPlayer.subtitleTracks, 6) /* QMediaMetaData::Language = 6 */ updateMetadata() mediaPlayer.play() }
在 TracksInfo
中定义的 model
然后将在 SettingsPopup
中的 ComboBox
中查询以选择当前轨道。
settingsController.mediaPlayer.pause() tracksInfo.selectedTrack = currentIndex settingsController.mediaPlayer.play()
© 2024 The Qt Company Ltd. 本文档中的文档贡献享有各自所有者的版权。本文档根据自由软件基金会(Free Software Foundation)发布的 GNU 自由文档许可证版本 1.3 的条款提供。Qt 和相应的徽标是 The Qt Company Ltd. 在芬兰和/或世界上其他国家的商标。所有其他商标均为其所有者财产。