QML开发:媒体播放

一、媒体播放(Playing Media)

1. 元素 MediaPlayer

1.1 概述
  MediaPlayer 是 Qt Multimedia 模块里最核心的媒体控制元素,用来加载、解码并播放 音频或视频文件。它本身不显示视频画面(只负责解码),需要配合 VideoOutput 元素来显示视频。

  • 如果只是播放音频,可以单独使用 MediaPlayer 或 Audio 元素。
  • 如果要播放视频,需要 MediaPlayer + VideoOutput。

1.2 导入模块
使用 MediaPlayer 需要引入 QtMultimedia:

import QtMultimedia 5.12   // Qt5
// Qt6 则用: import QtMultimedia

1.3 常用属性
在这里插入图片描述
1.4 常用方法
在这里插入图片描述
1.5 常用信号
在这里插入图片描述
1.6 使用示例
播放音频:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.15

Rectangle {
    width: 400; height: 200

    MediaPlayer {
        id: music
        source: "qrc:/sounds/music.mp3"
        autoPlay: true
        volume: 0.8
        onError: console.log("播放错误:", errorString)
    }

    Row {
        anchors.centerIn: parent
        spacing: 10

        Button { text: "播放"; onClicked: music.play() }
        Button { text: "暂停"; onClicked: music.pause() }
        Button { text: "停止"; onClicked: music.stop() }
    }
}

播放视频:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.12

Rectangle {
    width: 800; height: 600

    MediaPlayer {
        id: video
        source: "file:///C:/Videos/test.mp4"
        autoPlay: true
    }

    VideoOutput {
        anchors.fill: parent
        source: video
    }

    Slider {
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        from: 0
        to: video.duration
        value: video.position
        onMoved: video.seek(value)
    }
}

2. 元素 VideoOutput

2.1 概述

  • VideoOutput 负责 显示 视频画面,但不负责播放。
  • 播放功能由 MediaPlayer 提供,VideoOutput.source 绑定到 MediaPlayer,才能看到画面。
  • 可以当成一个“视频显示区域”,和 Image 类似,但显示的内容是视频流。

2.2 导入模块

import QtMultimedia 5.12   // Qt5
// Qt6 则用: import QtMultimedia

2.3 常用属性
在这里插入图片描述
fillMode 取值:

  • VideoOutput.Stretch → 拉伸填充整个区域(可能变形)
  • VideoOutput.PreserveAspectFit → 保持比例缩放,完整显示(常用)
  • VideoOutput.PreserveAspectCrop → 保持比例缩放并裁剪,铺满显示

2.4 常用信号
在这里插入图片描述
2.5 基本用法
播放视频示例:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.12

Rectangle {
    width: 800; height: 600
    color: "black"

    MediaPlayer {
        id: player
        source: "file:///C:/Videos/sample.mp4"
        autoPlay: true
    }

    VideoOutput {
        anchors.fill: parent
        source: player
        fillMode: VideoOutput.PreserveAspectFit
    }

    Row {
        spacing: 10
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        padding: 10

        Button { text: "播放"; onClicked: player.play() }
        Button { text: "暂停"; onClicked: player.pause() }
        Button { text: "停止"; onClicked: player.stop() }
    }
}

显示摄像头画面:VideoOutput 也能显示摄像头(和 Camera 元素配合)

import QtQuick 2.12
import QtMultimedia 5.12

Rectangle {
    width: 640; height: 480

    Camera { id: cam }

    VideoOutput {
        anchors.fill: parent
        source: cam
        fillMode: VideoOutput.PreserveAspectFit
    }
}

二、声音效果(Sounds Effects)

2.1 概述
在 QML / Qt Multimedia 里,除了 MediaPlayer、Audio 用于播放音乐或长音频之外,还提供了专门的 SoundEffect 元素 用来播放短音效(比如按钮点击声、提示音、游戏里的爆炸声)。

  • SoundEffect 适合 短小、重复的音效,因为它会把音频加载到内存里,播放延迟非常低。
  • 不适合播放长音频(比如背景音乐),那应该用 Audio 或 MediaPlayer。

2.2 导入模块

import QtMultimedia 5.12   // Qt5
// Qt6 则用: import QtMultimedia

2.3 常用属性
在这里插入图片描述
2.4 常用方法
在这里插入图片描述

2.4使用示例
播放按钮点击音效:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.12

Rectangle {
    width: 400; height: 200

    SoundEffect {
        id: clickSound
        source: "qrc:/sounds/click.wav"
        volume: 0.8
    }

    Button {
        anchors.centerIn: parent
        text: "点我"
        onClicked: clickSound.play()
    }
}

循环播放音效:

SoundEffect {
    id: alarmSound
    source: "qrc:/sounds/alarm.wav"
    loops: SoundEffect.Infinite
}

// 开始循环
alarmSound.play()

// 停止
alarmSound.stop()

注意事项:

  • 适合短音效(< 1MB 左右),因为它会一次性加载到内存。
  • 文件格式:最稳定的是 WAV,压缩格式(mp3/ogg)支持依赖平台。
  • 低延迟:和 MediaPlayer 不同,SoundEffect 播放时几乎没有延迟,很适合游戏或交互反馈。
  • 多实例播放:同一个 SoundEffect 不能同时重叠播放,如果需要多个声音叠加,最好创建多个 SoundEffect 实例。

三、捕捉图像(Capturing Images)

3.1 概述

  • Camera 元素用于控制和访问设备摄像头。
  • 它本身 不显示画面,需要配合 VideoOutput 来预览视频。
  • 可以用来:拍照(静态图片)、录像(结合 MediaRecorder)、实时视频预览

3.2 导入模块

import QtMultimedia 5.12   // Qt5
// Qt6: import QtMultimedia

3.3 常用属性
在这里插入图片描述
3.4 常用方法

  • start() :启动摄像头(相当于 active = true)
  • stop() :关闭摄像头

3.5 常用信号
在这里插入图片描述
3.6 基本使用
摄像头预览:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.12
Rectangle {
    width: 640
    height: 480

    Camera {
        id: cam
        captureMode: Camera.CaptureStillImage
    }

    VideoOutput {
        anchors.fill: parent
        source: cam
        focus: visible // 点击对焦
    }

    Button {
        text: cam.active ? "关闭" : "打开"
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: cam.active = !cam.active
    }
}

拍照并保存:

import QtQuick 2.12
import QtMultimedia 5.12
import QtQuick.Controls 2.12

Rectangle {
    width: 640
    height: 480

    Camera {
        id: cam
        captureMode: Camera.CaptureStillImage

        imageCapture {
            onImageCaptured: (id, preview) => {
                console.log("拍照完成,预览图已生成")
            }
            onImageSaved: (id, fileName) => {
                console.log("照片已保存:", fileName)
            }
        }
    }

    VideoOutput {
        anchors.fill: parent
        source: cam
    }

    Button {
        text: "拍照"
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: cam.imageCapture.captureToFile("photo.jpg")
    }
}

录像示例(配合 MediaRecorder):

Camera {
    id: cam
    captureMode: Camera.CaptureVideo
}

MediaRecorder {
    id: recorder
    mediaObject: cam
    outputLocation: "file:///C:/Videos/test.mp4"
}

// 开始录像
recorder.record()

// 停止录像
recorder.stop()

Camera 中常见的捕获模式:

Camera.CaptureStillImage   // 捕获静态图像(拍照)
Camera.CaptureVideo        // 捕获视频(录像)

完整的拍照和录像切换示例:

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtMultimedia 5.12

ApplicationWindow {
    visible: true
    width: 800
    height: 600
    title: "拍照 & 录像 示例"

    // 相机
    Camera {
        id: camera
        captureMode: Camera.CaptureStillImage  // 默认拍照模式

        // 拍照功能
        imageCapture {
            onImageCaptured: {
                console.log("图片捕获成功:", preview)
            }
            onImageSaved: {
                console.log("图片保存路径:", path)
            }
        }

        // 录像功能
        videoRecorder {
            onRecordingStarted: {
                console.log("录像开始")
            }
            onRecordingStopped: {
                console.log("录像停止,文件路径:", actualLocation)
            }
        }
    }

    // 视频预览窗口
    VideoOutput {
        source: camera
        anchors.fill: parent
        focus : visible
    }

    // 控制栏
    Row {
        spacing: 10
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        padding: 10

        // 模式切换按钮
        Button {
            text: camera.captureMode === Camera.CaptureStillImage ? "切换到录像" : "切换到拍照"
            onClicked: {
                if (camera.captureMode === Camera.CaptureStillImage) {
                    camera.captureMode = Camera.CaptureVideo
                } else {
                    camera.captureMode = Camera.CaptureStillImage
                }
            }
        }

        // 拍照按钮
        Button {
            text: "拍照"
            enabled: camera.captureMode === Camera.CaptureStillImage
            onClicked: {
                camera.imageCapture.captureToLocation("photo_" + Date.now() + ".jpg")
            }
        }

        // 开始录像按钮
        Button {
            text: "开始录像"
            enabled: camera.captureMode === Camera.CaptureVideo
            onClicked: {
                camera.videoRecorder.recordToLocation("video_" + Date.now() + ".mp4")
                camera.videoRecorder.record()
            }
        }

        // 停止录像按钮
        Button {
            text: "停止录像"
            enabled: camera.captureMode === Camera.CaptureVideo
            onClicked: camera.videoRecorder.stop()
        }
    }
}

完整的相机应用示例(支持预览、拍照、保存、录像):

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtMultimedia 5.12

ApplicationWindow {
    width: 800
    height: 600
    visible: true
    title: "QML 相机应用"

    Camera {
        id: cam
        captureMode: Camera.CaptureVideo  // 默认支持拍照和录像
        active: true

        // 拍照
        imageCapture {
            onImageCaptured: (id, preview) => {
                console.log("拍照完成,生成预览图")
            }
            onImageSaved: (id, fileName) => {
                console.log("照片已保存到:", fileName)
            }
        }
    }

    // 录像功能
    MediaRecorder {
        id: recorder
        mediaObject: cam
        outputLocation: "file:///C:/Videos/test.mp4"
        onRecordingStarted: console.log("开始录像...")
        onRecordingStopped: console.log("录像已保存:", actualLocation)
    }

    // 显示视频预览
    VideoOutput {
        anchors.fill: parent
        source: cam
        focus: visible
        fillMode: VideoOutput.PreserveAspectFit
    }

    // 控制面板
    Row {
        spacing: 10
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        padding: 10

        Button {
            text: "拍照"
            onClicked: cam.imageCapture.captureToFile("photo.jpg")
        }

        Button {
            text: recorder.recorderState === MediaRecorder.RecordingState ? "停止录像" : "开始录像"
            onClicked: {
                if (recorder.recorderState === MediaRecorder.RecordingState) {
                    recorder.stop()
                } else {
                    recorder.record()
                }
            }
        }

        Button {
            text: cam.active ? "关闭相机" : "打开相机"
            onClicked: cam.active = !cam.active
        }
    }
}

四、播放列表(Implementing a Playlist)

4.1 基本概念

  • MediaPlayer:负责播放媒体文件(音频或视频)。
  • MediaPlaylist:管理一组媒体文件,可以顺序播放、循环播放、随机播放等。

MediaPlayer 的 playlist 属性可以绑定一个 MediaPlaylist 实例。

4.2 导入模块

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtMultimedia 5.12

4.3 MediaPlaylist 常用属性
在这里插入图片描述
播放模式(playbackMode):

  • MediaPlaylist.CurrentItemOnce → 播放当前媒体一次
  • MediaPlaylist.CurrentItemInLoop → 当前媒体循环播放
  • MediaPlaylist.Sequential → 顺序播放列表
  • MediaPlaylist.Loop → 播放列表循环
  • MediaPlaylist.Random → 随机播放

4.3 MediaPlaylist 常用方法
在这里插入图片描述

4.4 基本示例
音频播放列表示例:

ApplicationWindow {
    visible: true
    width: 400
    height: 200

    MediaPlayer {
        id: player
        autoPlay: true
    }

    MediaPlaylist {
        id: playlist
        currentIndex: 0
        playbackMode: MediaPlaylist.Sequential

        MediaContent { source: "qrc:/sounds/song1.mp3" }
        MediaContent { source: "qrc:/sounds/song2.mp3" }
        MediaContent { source: "qrc:/sounds/song3.mp3" }
    }

    Component.onCompleted: player.playlist = playlist

    Column {
        spacing: 10
        anchors.centerIn: parent

        Button { text: "上一首"; onClicked: playlist.previous() }
        Button { text: player.playbackState === MediaPlayer.PlayingState ? "暂停" : "播放"; 
                 onClicked: {
                     if(player.playbackState === MediaPlayer.PlayingState) player.pause()
                     else player.play()
                 }
        }
        Button { text: "下一首"; onClicked: playlist.next() }
    }
}

视频播放列表示例:

MediaPlayer {
    id: videoPlayer
    autoPlay: true
}

MediaPlaylist {
    id: videoPlaylist
    currentIndex: 0
    playbackMode: MediaPlaylist.Loop

    MediaContent { source: "file:///C:/Videos/video1.mp4" }
    MediaContent { source: "file:///C:/Videos/video2.mp4" }
}

Component.onCompleted: videoPlayer.playlist = videoPlaylist

VideoOutput {
    anchors.fill: parent
    source: videoPlayer
}

完整的 QML 播放器带播放列表,支持:

  • 播放列表显示
  • 播放 / 暂停
  • 上一首 / 下一首
  • 播放模式切换(顺序 / 循环 / 随机)
  • 播放状态显示
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtMultimedia 5.12

ApplicationWindow {
    visible: true
    width: 500
    height: 400
    title: "QML 播放器示例"

    MediaPlayer {
        id: player
        autoPlay: false
        volume: 0.8
    }

    MediaPlaylist {
        id: playlist
        currentIndex: 0
        playbackMode: MediaPlaylist.Sequential

        MediaContent { source: "qrc:/sounds/song1.mp3" }
        MediaContent { source: "qrc:/sounds/song2.mp3" }
        MediaContent { source: "qrc:/sounds/song3.mp3" }
    }

    Component.onCompleted: player.playlist = playlist

    Column {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 10

        // 播放列表显示
        ListView {
            id: listView
            height: 200
            model: playlist.mediaCount
            delegate: Rectangle {
                width: listView.width
                height: 40
                color: index === playlist.currentIndex ? "#a0c4ff" : "#ffffff"
                border.color: "#888888"

                Text {
                    anchors.centerIn: parent
                    text: playlist.mediaAt(index).source
                    font.pointSize: 12
                    elide: Text.ElideRight
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: playlist.currentIndex = index
                }
            }
        }

        // 控制按钮
        Row {
            spacing: 10
            Button {
                text: "上一首"
                onClicked: playlist.previous()
            }
            Button {
                text: player.playbackState === MediaPlayer.PlayingState ? "暂停" : "播放"
                onClicked: {
                    if(player.playbackState === MediaPlayer.PlayingState)
                        player.pause()
                    else
                        player.play()
                }
            }
            Button {
                text: "下一首"
                onClicked: playlist.next()
            }
        }

        // 播放模式切换
        Row {
            spacing: 10
            Text { text: "播放模式:" }
            ComboBox {
                model: ["顺序", "循环", "随机"]
                currentIndex: 0
                onCurrentIndexChanged: {
                    switch(currentIndex) {
                        case 0: playlist.playbackMode = MediaPlaylist.Sequential; break;
                        case 1: playlist.playbackMode = MediaPlaylist.Loop; break;
                        case 2: playlist.playbackMode = MediaPlaylist.Random; break;
                    }
                }
            }
        }

        // 播放状态显示
        Text {
            text: "当前播放: " + playlist.currentMedia.source
            font.bold: true
            color: "#333333"
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值