如何在QML中为VideoSink添加MediaRecorder实现视频录制?
解决方案
Qt6的MediaRecorder确实无法直接在QML中绑定VideoSink作为录制源,因为它依赖QMediaCaptureSession来关联媒体输入。你需要在C++层的Producer类中集成录制逻辑,通过QMediaCaptureSession对接VideoSink的视频流,具体步骤如下:
1. 修改C++ Producer类,添加录制功能
扩展你的Producer类,加入QMediaCaptureSession、QMediaRecorder以及自定义视频源,用来传递VideoSink收到的帧:
头文件(Producer.h)
#ifndef PRODUCER_H #define PRODUCER_H #include <QObject> #include <QVideoSink> #include <QMediaCaptureSession> #include <QMediaRecorder> #include <QUrl> class Producer : public QObject { Q_OBJECT Q_PROPERTY(QVideoSink* videoSink READ videoSink WRITE setVideoSink NOTIFY videoSinkChanged) Q_PROPERTY(QUrl outputLocation READ outputLocation WRITE setOutputLocation NOTIFY outputLocationChanged) public: explicit Producer(QObject *parent = nullptr); QVideoSink* videoSink() const; void setVideoSink(QVideoSink* sink); QUrl outputLocation() const; void setOutputLocation(const QUrl& location); public slots: void startRecording(); void stopRecording(); bool isRecording() const; signals: void videoSinkChanged(); void outputLocationChanged(); void recordingStateChanged(bool isRecording); private slots: void onFrameReceived(const QVideoFrame& frame); private: class VideoFrameSource : public QObject { Q_OBJECT Q_PROPERTY(QVideoFrame currentFrame READ currentFrame NOTIFY currentFrameChanged) public: explicit VideoFrameSource(QObject* parent = nullptr) : QObject(parent) {} QVideoFrame currentFrame() const { return m_frame; } public slots: void setFrame(const QVideoFrame& frame) { m_frame = frame; emit currentFrameChanged(); } signals: void currentFrameChanged(); private: QVideoFrame m_frame; }; QVideoSink* m_videoSink = nullptr; QMediaCaptureSession m_captureSession; QMediaRecorder m_recorder; QUrl m_outputLocation; VideoFrameSource* m_videoSource = nullptr; }; #endif // PRODUCER_H
实现文件(Producer.cpp)
#include "Producer.h" #include <QMediaFormat> Producer::Producer(QObject *parent) : QObject{parent} { m_videoSource = new VideoFrameSource(this); m_captureSession.setVideoInput(m_videoSource); m_captureSession.setRecorder(&m_recorder); // 配置MP4录制格式,使用H264视频编码 QMediaFormat format; format.setFileFormat(QMediaFormat::MP4); format.setVideoCodec(QMediaFormat::VideoCodec::H264); m_recorder.setMediaFormat(format); } QVideoSink* Producer::videoSink() const { return m_videoSink; } void Producer::setVideoSink(QVideoSink* sink) { if (m_videoSink == sink) return; if (m_videoSink) { disconnect(m_videoSink, &QVideoSink::frameReceived, this, &Producer::onFrameReceived); } m_videoSink = sink; if (m_videoSink) { connect(m_videoSink, &QVideoSink::frameReceived, this, &Producer::onFrameReceived); } emit videoSinkChanged(); } QUrl Producer::outputLocation() const { return m_outputLocation; } void Producer::setOutputLocation(const QUrl& location) { if (m_outputLocation == location) return; m_outputLocation = location; m_recorder.setOutputLocation(location); emit outputLocationChanged(); } void Producer::startRecording() { if (!m_outputLocation.isValid()) return; m_recorder.record(); emit recordingStateChanged(true); } void Producer::stopRecording() { m_recorder.stop(); emit recordingStateChanged(false); } bool Producer::isRecording() const { return m_recorder.status() == QMediaRecorder::RecordingStatus; } void Producer::onFrameReceived(const QVideoFrame& frame) { if (m_videoSource && isRecording()) { m_videoSource->setFrame(frame); } }
2. 修改QML代码,调用Producer的录制接口
移除原有的独立MediaRecorder,直接通过Producer的方法控制录制:
VideoOutput { id: cameraDisplay anchors.fill: parent } Producer { id:producer objectName: "producer" videoSink: cameraDisplay.videoSink // 设置MP4输出路径,确保程序有写入权限 outputLocation: "file:///home/user/recorded_video.mp4" } Button{ text: "" Image { id: recordImage source: producer.isRecording() ? "Images/StopRecord.png" : "Images/Record.png" width: parent.width height: parent.height } onClicked: { if (producer.isRecording()) { producer.stopRecording() } else { producer.startRecording() } } }
关键说明
QMediaCaptureSession是Qt6中媒体捕获的核心组件,负责关联视频输入和录制器;- 自定义的
VideoFrameSource用来将VideoSink收到的帧传递给QMediaCaptureSession,作为录制的视频源; - 确保项目文件中已添加多媒体模块:
QT += multimedia; - 输出路径需使用
file://前缀,且程序拥有对应目录的写入权限; - 视频编码格式需根据系统支持情况调整,H264是MP4容器的通用选择。
内容的提问来源于stack exchange,提问作者asdfasdf
相关产品推荐
相关产品推荐

