You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Qt Multimedia模块实现桌面录制?

Qt Multimedia实现桌面屏幕录制的方案

核心结论

Qt Multimedia在Qt 6.5及之后版本提供了官方的桌面捕获支持,低版本则需要通过自定义视频源结合框架实现,两种方式都能满足你用QVideoWidget实时预览、QMediaRecorder录制的需求。


一、Qt 6.5+ 官方方案(推荐)

Qt 6.5新增了QScreenCapture类,专门用于桌面/窗口捕获,可直接集成到QMediaCaptureSession中,无需自行处理平台原生API:

  1. 基本使用示例
#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();
}
  1. 补充说明
  • 该方案同时支持屏幕和指定窗口捕获,无需自行处理跨平台兼容问题
  • 可直接搭配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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:11:08