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

如何在QT C++中将QImage序列保存为视频?

解决QMediaRecorder无法直接录制带叠加层视频的问题

QMediaRecorder确实只能直接录制摄像头的原始流,没法中途插入帧处理。要实现“抓帧→加叠加层→存视频”的需求,得绕开QMediaRecorder的直接录制逻辑,改用自定义帧捕获+处理+写入的流程,下面是两种可行的实现方式:

方法一:Qt原生模块实现(推荐)

用QCamera捕获帧,自定义QAbstractVideoSurface处理叠加层,最后用QVideoWriter写入视频文件。

步骤1:实现自定义视频表面

继承QAbstractVideoSurface来接收摄像头的每一帧,在present方法里完成叠加层绘制:

#include <QAbstractVideoSurface>
#include <QVideoFrame>
#include <QPainter>

class OverlayVideoSurface : public QAbstractVideoSurface
{
    Q_OBJECT
public:
    explicit OverlayVideoSurface(QObject *parent = nullptr) : QAbstractVideoSurface(parent) {}

    // 声明支持的像素格式
    QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const override
    {
        Q_UNUSED(handleType);
        return {QVideoFrame::Format_RGB32, QVideoFrame::Format_ARGB32};
    }

    // 处理每一帧
    bool present(const QVideoFrame &frame) override
    {
        if (!frame.isValid()) return false;

        // 复制帧并映射到内存
        QVideoFrame cloneFrame(frame);
        if (!cloneFrame.map(QAbstractVideoBuffer::ReadOnly)) return false;
        QImage image(cloneFrame.bits(), cloneFrame.width(), cloneFrame.height(), 
                     QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()));
        cloneFrame.unmap();

        // 添加叠加层(示例:居中红色文字)
        QPainter painter(&image);
        painter.setPen(Qt::red);
        painter.setFont(QFont("Arial", 20));
        painter.drawText(image.rect(), Qt::AlignCenter, "实时叠加内容");
        painter.end();

        // 发送处理后的帧
        emit frameProcessed(QVideoFrame(image));
        return true;
    }

signals:
    void frameProcessed(const QVideoFrame &frame);
};

步骤2:整合摄像头与视频写入器

在主逻辑里连接摄像头、自定义表面和QVideoWriter:

#include <QCamera>
#include <QVideoWriter>
#include <QVideoEncoderSettings>

// 初始化摄像头
QCamera *camera = new QCamera(this);
camera->setCaptureMode(QCamera::CaptureVideo);

// 实例化自定义表面
OverlayVideoSurface *surface = new OverlayVideoSurface(this);
camera->setViewfinderSurface(surface);

// 配置视频写入器
QVideoWriter writer;
QString outputPath = "./record_with_overlay.mp4";
QVideoEncoderSettings encodeSettings;
encodeSettings.setCodec("video/mp4"); // 根据系统支持调整,可通过QVideoWriter::supportedCodecs()查看
encodeSettings.setResolution(640, 480); // 匹配摄像头分辨率
encodeSettings.setFrameRate(30.0);

writer.setFileName(outputPath);
writer.setSettings(encodeSettings);

// 绑定处理后的帧到写入器
connect(surface, &OverlayVideoSurface::frameProcessed, this, [&](const QVideoFrame &frame){
    if (writer.isOpen()) {
        writer.write(frame);
    }
});

// 启动录制
if (writer.open()) {
    camera->start();
}

// 停止录制时记得调用
// camera->stop();
// writer.close();

方法二:结合FFmpeg实现(适合复杂编码需求)

如果Qt原生的QVideoWriter满足不了编码格式要求,可以调用FFmpeg库来完成视频编码。核心逻辑是:

  • 用QCamera抓帧转成RGB/YUV格式
  • 把帧数据传给FFmpeg的编码器
  • 写入封装好的视频文件

这种方式需要自己处理FFmpeg的编码上下文、流配置等,灵活性更高但代码量更大。

注意事项

  1. 确保QVideoWriter的编码格式是系统支持的,Windows、macOS、Linux的支持列表可能不同
  2. 帧格式转换时要注意像素格式匹配,避免出现花屏、颜色失真
  3. 录制结束必须调用writer.close(),否则视频文件可能损坏

内容的提问来源于stack exchange,提问作者lilsoujaaa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:25:31