如何使用Qt Multimedia模块实现桌面录制?
Qt Multimedia实现桌面屏幕录制的方案
核心结论
Qt Multimedia在Qt 6.5及之后版本提供了官方的桌面捕获支持,低版本则需要通过自定义视频源结合框架实现,两种方式都能满足你用QVideoWidget实时预览、QMediaRecorder录制的需求。
一、Qt 6.5+ 官方方案(推荐)
Qt 6.5新增了QScreenCapture类,专门用于桌面/窗口捕获,可直接集成到QMediaCaptureSession中,无需自行处理平台原生API:
- 基本使用示例
#include <QGuiApplication> #include <QScreenCapture> #include <QMediaCaptureSession> #include <QVideoWidget> #include <QMediaRecorder> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 初始化屏幕捕获对象(指定要捕获的屏幕,这里选主屏幕) QScreenCapture screenCapture(QGuiApplication::primaryScreen()); // 可选:捕获指定窗口,需要窗口的WId // screenCapture.setWindowId(someWindowId); // 配置捕获会话 QMediaCaptureSession captureSession; captureSession.setScreenCapture(&screenCapture); // 绑定实时预览窗口 QVideoWidget videoWidget; captureSession.setVideoOutput(&videoWidget); videoWidget.show(); // 配置录制器 QMediaRecorder recorder; captureSession.setRecorder(&recorder); recorder.setOutputLocation(QUrl::fromLocalFile("./desktop_record.mp4")); // 可选:设置视频编码、分辨率等参数 // QMediaFormat format; // format.setFileFormat(QMediaFormat::MP4); // format.setVideoCodec(QMediaFormat::VideoCodec::H264); // recorder.setMediaFormat(format); // 开始录制 recorder.record(); return app.exec(); }
- 补充说明
- 该方案同时支持屏幕和指定窗口捕获,无需自行处理跨平台兼容问题
- 可直接搭配
QAudioInput实现麦克风+桌面的同步录制 - 实时预览和录制效率远高于FFmpeg截图合成的方式
二、Qt 6.5以下版本:自定义视频源方案
低版本Qt没有内置桌面捕获类,需通过自定义视频帧推送结合QMediaCaptureSession实现:
1. 桌面捕获逻辑(跨平台)
需要针对不同平台调用原生API实现高效屏幕捕获:
- Windows:使用DirectX Desktop Duplication API(比GDI截图效率高)
- Linux:使用X11的XShm或XRandR扩展
- macOS:使用Quartz Display Services的CGDisplayStream
也可以先用Qt的QScreen::grabWindow做快速原型(注意:该方法是同步截图,高帧率场景下效率较低,仅适合测试):
QImage captureDesktop() { QScreen* screen = QGuiApplication::primaryScreen(); return screen->grabWindow(0).toImage(); // 0代表整个屏幕 }
2. 将捕获的图像转换为QVideoFrame
需要把QImage转换成符合QVideoSink要求的QVideoFrame:
QVideoFrame imageToVideoFrame(const QImage& image) { QVideoFrame frame(image.size(), QVideoFrame::Format_RGB32); frame.map(QVideoFrame::WriteOnly); memcpy(frame.bits(), image.bits(), image.sizeInBytes()); frame.unmap(); return frame; }
3. 集成到QMediaCaptureSession
创建自定义类推送视频帧到QMediaCaptureSession的QVideoSink:
#include <QObject> #include <QTimer> #include <QVideoSink> #include <QImage> class DesktopVideoSource : public QObject { Q_OBJECT public: explicit DesktopVideoSource(QObject *parent = nullptr) : QObject(parent) { // 定时捕获桌面(这里设为30帧/秒) m_captureTimer = new QTimer(this); connect(m_captureTimer, &QTimer::timeout, this, &DesktopVideoSource::captureAndPushFrame); m_captureTimer->start(1000/30); } void setVideoSink(QVideoSink* sink) { m_videoSink = sink; } private slots: void captureAndPushFrame() { if (!m_videoSink) return; QImage desktopImage = captureDesktop(); QVideoFrame frame = imageToVideoFrame(desktopImage); m_videoSink->setVideoFrame(frame); } private: QTimer* m_captureTimer; QVideoSink* m_videoSink; };
然后在主逻辑中绑定到QMediaCaptureSession:
int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); DesktopVideoSource videoSource; QMediaCaptureSession captureSession; videoSource.setVideoSink(captureSession.videoSink()); QVideoWidget videoWidget; captureSession.setVideoOutput(&videoWidget); videoWidget.show(); QMediaRecorder recorder; captureSession.setRecorder(&recorder); recorder.setOutputLocation(QUrl::fromLocalFile("./desktop_record.mp4")); recorder.record(); return app.exec(); }
三、关于你表述的纠正
你提到“QMediaCaptureSession、QMediaRecorder仅支持摄像头设备”,这个表述在Qt 6.5及之后版本并不准确:Qt 6.5新增的QScreenCapture可以直接接入这两个组件,实现桌面录制;而在Qt 6.5之前,确实没有内置的桌面捕获源,需要自定义视频输入。
内容的提问来源于stack exchange,提问作者Abdurahmon
相关产品推荐
相关产品推荐

