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还提供了很多非常好用的多媒体类,可以实现很多丰富的功能。本文仅演示基础使用,在此demo上可进行更多的扩展。
本文demo下载