Qt6+QML实现Windows屏幕录制功能

 更新时间:2025年04月18日 09:37:54   作者:luoyayun361  
Qt6提供了很多丰富的多媒体支持类,本文将为大家详细介绍一下Qt6如何结合QML实现Windows屏幕录制功能,文中的示例代码简洁易懂,有需要的小伙伴可以参考一下

前言

Qt6提供了更丰富的多媒体支持类,使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder,来实现一个屏幕录制的demo,其中QScreenCapture 最低版本 Qt6.5。支持录制的清晰度设置,选择视频保存位置,UI使用QML来实现。

Qt6还有一个比较好用的类 QWindowCapture, 可以针对窗口录屏。使用静态函数 QList<QCapturableWindow> capturableWindows()

可以获取当前可用的录制窗口,选择窗口进行录制。可以在本demo的基础上进行扩展。

效果图

本demo使用Qt6.8 MinGW进行编译,注意QScreenCapture最低支持Qt6.5,所以版本不能低于6.5.

完整代码

主要使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder这三个关键的多媒体类来实现。

关键代码:

开始录制和结束录制:

void ScreenRecorder::startRecording()
{
    if (m_isRecording) {
        qDebug() << __FUNCTION__ << "Already recording, ignoring request";
        return;
    }
    
    qDebug() << __FUNCTION__ << "Starting recording process...";
    
    // 选择保存文件
    QString defaultPath = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss");
    QString defaultFileName = QString("%1/ScreenRecording_%2.mp4").arg(defaultPath).arg(timestamp);
    
    qDebug() << __FUNCTION__ << "Default save path:" << defaultFileName;
    
    QString filePath = QFileDialog::getSaveFileName(
        nullptr,
        tr("Save Recording"),
        defaultFileName,
        tr("Video Files (*.mp4)"));
    
    if (filePath.isEmpty()) {
        qDebug() << __FUNCTION__ << "User cancelled file selection";
        m_statusMessage = tr("Recording cancelled");
        emit statusMessageChanged();
        return;
    }

    qDebug() << __FUNCTION__ << "Selected file path:" << filePath;
    
    // 确保目录存在
    QFileInfo fileInfo(filePath);
    QDir dir = fileInfo.dir();
    if (!dir.exists()) {
        qDebug() << __FUNCTION__ << "Creating directory:" << dir.path();
        if (!dir.mkpath(".")) {
            qDebug() << __FUNCTION__ << "Failed to create directory";
            m_statusMessage = tr("Error: Could not create directory");
            emit statusMessageChanged();
            return;
        }
    }
    
    // 设置输出位置
    QUrl fileUrl = QUrl::fromLocalFile(filePath);
    qDebug() << __FUNCTION__ << "Setting output location:" << fileUrl.toString();
    m_recorder.setOutputLocation(fileUrl);
    
    // 更新质量设置
    updateQualitySettings();
    
    // 开始录制
    qDebug() << __FUNCTION__ << "Starting recorder...";
    m_recorder.record();
    
    // 启动计时器
    m_elapsedTimer.start();
    m_timer.start(1000); // 每秒更新一次
    
    m_isRecording = true;
    m_statusMessage = tr("Recording started");
    emit isRecordingChanged();
    emit statusMessageChanged();
    
    qDebug() << __FUNCTION__ << "Recording started successfully";
}

void ScreenRecorder::stopRecording()
{
    if (!m_isRecording) {
        return;
    }
    
    qDebug() << __FUNCTION__ << "Stopping recording...";
    
    // 获取当前输出位置,用于验证
    QUrl outputLocation = m_recorder.outputLocation();
    qDebug() << __FUNCTION__ << "Output location:" << outputLocation.toLocalFile();
    
    // 停止录制
    m_recorder.stop();
    
    // 停止计时器
    m_timer.stop();
    
    // 检查文件是否存在
    QString filePath = outputLocation.toLocalFile();
    QFileInfo fileInfo(filePath);
    if (fileInfo.exists()) {
        qDebug() << __FUNCTION__ << "File saved successfully at:" << filePath;
        qDebug() << __FUNCTION__ << "File size:" << fileInfo.size() << "bytes";
        m_statusMessage = tr("Recording saved to %1").arg(filePath);
    } else {
        qDebug() << __FUNCTION__ << "Error: File not created at:" << filePath;
        m_statusMessage = tr("Error: Recording file not created");
    }
    
    m_isRecording = false;
    emit isRecordingChanged();
    emit statusMessageChanged();
}

设置录制器:

void ScreenRecorder::setupRecorder()
{
    qDebug() << __FUNCTION__ << "Setting up recorder...";
    
    // 设置捕获会话
    m_captureSession.setScreenCapture(&m_screenCapture);
    m_captureSession.setRecorder(&m_recorder);
    
    // 设置屏幕捕获
    m_screenCapture.setScreen(QGuiApplication::primaryScreen());
    m_screenCapture.setActive(true); // 激活屏幕捕获
    qDebug() << __FUNCTION__ << "Screen set to:" << QGuiApplication::primaryScreen()->name();
    qDebug() << __FUNCTION__ << "Screen capture active:" << m_screenCapture.isActive();
    
    // 设置录制器
    QMediaFormat format;
    format.setFileFormat(QMediaFormat::FileFormat::MPEG4);
    format.setVideoCodec(QMediaFormat::VideoCodec::H264);
    
    // 检查编解码器是否支持
    QList<QMediaFormat::VideoCodec> supportedCodecs = format.supportedVideoCodecs(QMediaFormat::Encode);
    qDebug() << __FUNCTION__ << "Supported video codecs:" << supportedCodecs;
    
    if (!supportedCodecs.contains(QMediaFormat::VideoCodec::H264)) {
        qDebug() << __FUNCTION__ << "Warning: H264 codec may not be supported";
        // 尝试使用第一个可用的编解码器
        if (!supportedCodecs.isEmpty()) {
            format.setVideoCodec(supportedCodecs.first());
            qDebug() << __FUNCTION__ << "Using alternative codec:" << supportedCodecs.first();
        }
    }
    
    m_recorder.setMediaFormat(format);
    qDebug() << __FUNCTION__ << "Media format set:" << format.fileFormat() << format.videoCodec();
    
    // 应用当前质量设置
    updateQualitySettings();
    
    // 连接信号
    connect(&m_recorder, &QMediaRecorder::recorderStateChanged,
            this, &ScreenRecorder::handleRecorderStateChanged);
    connect(&m_recorder, &QMediaRecorder::errorOccurred,
            this, &ScreenRecorder::handleError);
            
    qDebug() << __FUNCTION__ << "Recorder setup complete";
}

该功能是Qt结合ffmpeg来实现的,运行时会输出相关信息:qt.multimedia.ffmpeg: Using Qt multimedia with FFmpeg version 7.1 LGPL version 2.1 or later
Qt6还提供了很多非常好用的多媒体类,可以实现很多丰富的功能。

到此这篇关于Qt6+QML实现Windows屏幕录制功能的文章就介绍到这了,更多相关Qt6屏幕录制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言猜凶手的代码实现

    C语言猜凶手的代码实现

    本文主要介绍了C语言猜凶手的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • C++基类指针和派生类指针之间的转换方法讲解

    C++基类指针和派生类指针之间的转换方法讲解

    今天小编就为大家分享一篇关于C++基类指针和派生类指针之间的转换方法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • c语言操作文本的基本使用方法

    c语言操作文本的基本使用方法

    这篇文章主要介绍了c语言操作文本的基本使用方法,需要的朋友可以参考下
    2014-04-04
  • C语言中#pragma pack(1)的用法与注意点

    C语言中#pragma pack(1)的用法与注意点

    #pragma用于指示编译器完成一些特定的动作,下面这篇文章主要给大家介绍了关于C语言中#pragma pack(1)的用法与注意点的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • C++ Boost Thread线程使用示例详解

    C++ Boost Thread线程使用示例详解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • 一文解密C++中的多态机制

    一文解密C++中的多态机制

    众所周知C++语言的三大特性:封装、多态、继承,其中多态就是去完成某个行为,但是会根据不同的对象产生不同的状态,下面小编就来带大家深入了解一下C++的多态机制吧
    2023-07-07
  • C++实现堆排序实例介绍

    C++实现堆排序实例介绍

    大家好,本篇文章主要讲的是C++实现堆排序实例介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • 使用C++实现一个高效的线程池

    使用C++实现一个高效的线程池

    在多线程编程中,线程池是一种常见且高效的设计模式,本文将详细介绍如何使用C++实现一个线程池,并解析相关代码实现细节,需要的小伙伴可以参考下
    2024-12-12
  • C/C++ for 语句的要点与注意事项小结

    C/C++ for 语句的要点与注意事项小结

    C/C++ 中的 for 语句是一种常用的循环结构,用于重复执行一段代码,直到满足某个条件为止,这篇文章主要介绍了C/C++ for 语句的要点与注意事项,需要的朋友可以参考下
    2024-06-06
  • C++实现扫雷游戏(控制台不闪屏版)

    C++实现扫雷游戏(控制台不闪屏版)

    这篇文章主要为大家详细介绍了C++实现扫雷游戏,控制台不闪屏版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03

最新评论