第26章 Qt Multimedia多媒体:音频播放、视频播放、摄像头采集、音频录制、多媒体格式支持
说到Qt的多媒体模块,我其实挺感慨的。早些年做项目时,多媒体这块一直是Qt的软肋,动不动就依赖第三方库,配置起来让人头疼。但自从Qt 5引入Qt Multimedia模块后,情况好多了。说白了,现在你只需要几行代码,就能搞定音频播放、视频播放、甚至摄像头采集这些功能。
我个人习惯把多媒体模块分成四个核心方向:音频播放与录制、视频播放、摄像头采集、以及格式支持。咱们一个一个来聊。
26.1 音频播放:QMediaPlayer + QAudioOutput
音频播放是最基础的需求。Qt里用QMediaPlayer配合QAudioOutput就能搞定。嗯,这里要注意:Qt 6之后,音频输出从QAudioOutput变成了独立类,不再是QMediaPlayer的一部分。
核心思路:QMediaPlayer负责解码和播放控制,QAudioOutput负责音频输出设备管理。
// 音频播放示例
QMediaPlayer *player = new QMediaPlayer;
QAudioOutput *audioOutput = new QAudioOutput;
player->setAudioOutput(audioOutput);
// 设置音频源
player->setSource(QUrl::fromLocalFile("music.mp3"));
player->play();
我在项目中遇到过一个问题:播放某些MP3文件时,声音断断续续。后来发现是音频输出设备没设置好。你想想看,默认输出设备可能被其他应用占用了。所以我建议你每次播放前,检查一下audioOutput->isAvailable()。
小技巧:用player->positionChanged信号可以实时更新进度条。配合setPosition()实现拖拽播放。
26.2 视频播放:QVideoWidget + QMediaPlayer
视频播放其实就是在音频播放的基础上,加一个视频输出窗口。Qt提供了QVideoWidget,直接把它嵌入到你的UI里就行。
// 视频播放示例
QMediaPlayer *player = new QMediaPlayer;
QVideoWidget *videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
// 设置视频源
player->setSource(QUrl::fromLocalFile("video.mp4"));
player->play();
我曾经踩过一个坑:视频播放时画面黑屏,但音频正常。查了半天,发现是QVideoWidget没有设置合适的尺寸策略。说白了,视频窗口太小或者被其他控件遮挡了。解决办法很简单:给videoWidget设置一个最小尺寸,或者用布局管理器让它自适应。
注意事项:Qt Multimedia在Windows上默认使用DirectShow,在Linux上使用GStreamer。不同后端对视频格式的支持不一样。比如某些Linux发行版没装GStreamer的MPEG解码插件,播放MP4就会失败。
26.3 摄像头采集:QCamera + QVideoSink
摄像头采集这块,Qt做得挺优雅的。用QCamera打开设备,然后用QVideoSink接收视频帧。我记得第一次做摄像头项目时,还担心会不会很复杂,结果发现核心代码也就十几行。
// 摄像头采集示例
QCamera *camera = new QCamera;
QVideoSink *videoSink = new QVideoSink;
camera->setVideoSink(videoSink);
// 连接信号获取帧数据
connect(videoSink, &QVideoSink::videoFrameChanged,
[](const QVideoFrame &frame) {
// 处理每一帧
qDebug() << "帧尺寸:" << frame.size();
});
camera->start();
这里有个细节:QVideoFrame的数据格式可能是YUV、NV12或者RGB。如果你要做图像处理,最好先转换成QImage。我一般用frame.toImage(),但要注意这个操作比较耗时,别在主线程里频繁调用。
实用技巧:用QCameraDevice::availableCameras()可以列出所有摄像头。如果你有多个摄像头,可以用camera->setCameraDevice()切换。
26.4 音频录制:QMediaRecorder
音频录制用QMediaRecorder。它和QMediaPlayer配合使用,一个负责录,一个负责播。嗯,这里要注意:录制前要指定编码格式和输出文件。
// 音频录制示例
QMediaRecorder *recorder = new QMediaRecorder;
recorder->setSource(camera); // 也可以设置音频输入源
recorder->setOutputLocation(QUrl::fromLocalFile("record.wav"));
// 设置编码格式
QMediaFormat format;
format.setAudioCodec(QMediaFormat::AudioCodec::PCM);
format.setFileFormat(QMediaFormat::FileFormat::WAV);
recorder->setMediaFormat(format);
recorder->record();
我曾经在项目里遇到录制出来的音频文件是空的。排查后发现,是因为没有设置音频输入源。说白了,QMediaRecorder默认不知道从哪个设备录。你需要用setSource()指定一个QMediaCaptureSession或者QCamera(如果摄像头带麦克风)。
核心要点:录制前一定要检查recorder->isAvailable()和recorder->error()。很多录制失败是因为权限问题或者设备被占用。
26.5 多媒体格式支持
格式支持这块,说白了就是Qt Multimedia能播什么、不能播什么。这取决于底层后端和系统安装的解码器。
| 格式类型 | 常见格式 | 支持情况 |
|---|---|---|
| 音频 | MP3, WAV, OGG, FLAC | 基本都支持,但MP3需要解码器 |
| 视频 | MP4, AVI, MKV, MOV | 取决于后端,GStreamer支持较好 |
| 图像 | JPEG, PNG, BMP | Qt GUI模块自带支持 |
我建议你在项目里用QMediaFormat::supportedFileFormats()和QMediaFormat::supportedAudioCodecs()来动态检测。这样你的程序在不同平台上都能自适应。
避坑指南:我曾经在Linux上部署项目,结果用户反馈播不了MP4。后来发现是系统没装gstreamer1-plugins-bad-free。所以,如果你要分发应用,最好把依赖的解码器一起打包,或者在文档里写清楚。
26.6 知识体系总览
为了让你更直观地理解Qt Multimedia的整体结构,我画了一张图。你看完应该就明白各个模块之间的关系了。
从这张图你能看出来,Qt Multimedia的核心模块统一管理音频、视频、摄像头和录制功能。底层依赖不同的系统后端,上层则提供统一的API。你写代码时,不用关心底层是DirectShow还是GStreamer,Qt帮你封装好了。
嗯,这一章的内容就这些。多媒体这块其实不难,关键是理解各个类之间的协作关系。你动手写几个小例子,比如一个简单的音乐播放器、一个视频播放器,很快就能上手。
公众号:蓝海资料掘金营,微信deep3321