第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 多媒体模块架构 Qt Multimedia 核心 音频播放 QMediaPlayer+QAudioOutput 视频播放 QMediaPlayer+QVideoWidget 摄像头采集 QCamera+QVideoSink 音频录制 QMediaRecorder 底层后端:Windows (DirectShow) / Linux (GStreamer) / macOS (AVFoundation) 格式支持:MP3 / WAV / MP4 / AVI / OGG / FLAC / MKV 你的应用程序:播放器 / 录像机 / 视频会议

从这张图你能看出来,Qt Multimedia的核心模块统一管理音频、视频、摄像头和录制功能。底层依赖不同的系统后端,上层则提供统一的API。你写代码时,不用关心底层是DirectShow还是GStreamer,Qt帮你封装好了。

嗯,这一章的内容就这些。多媒体这块其实不难,关键是理解各个类之间的协作关系。你动手写几个小例子,比如一个简单的音乐播放器、一个视频播放器,很快就能上手。


公众号:蓝海资料掘金营,微信deep3321