Qt6+QML實(shí)現(xiàn)Windows屏幕錄制功能
前言
Qt6提供了更豐富的多媒體支持類(lèi),使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder,來(lái)實(shí)現(xiàn)一個(gè)屏幕錄制的demo,其中QScreenCapture 最低版本 Qt6.5。支持錄制的清晰度設(shè)置,選擇視頻保存位置,UI使用QML來(lái)實(shí)現(xiàn)。
Qt6還有一個(gè)比較好用的類(lèi) QWindowCapture, 可以針對(duì)窗口錄屏。使用靜態(tài)函數(shù) QList<QCapturableWindow> capturableWindows()
可以獲取當(dāng)前可用的錄制窗口,選擇窗口進(jìn)行錄制??梢栽诒綿emo的基礎(chǔ)上進(jìn)行擴(kuò)展。
效果圖
本demo使用Qt6.8 MinGW進(jìn)行編譯,注意QScreenCapture最低支持Qt6.5,所以版本不能低于6.5.


完整代碼
主要使用Qt6 QMediaCaptureSession、QScreenCapture、QMediaRecorder這三個(gè)關(guān)鍵的多媒體類(lèi)來(lái)實(shí)現(xiàn)。
關(guān)鍵代碼:
開(kāi)始錄制和結(jié)束錄制:
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;
}
}
// 設(shè)置輸出位置
QUrl fileUrl = QUrl::fromLocalFile(filePath);
qDebug() << __FUNCTION__ << "Setting output location:" << fileUrl.toString();
m_recorder.setOutputLocation(fileUrl);
// 更新質(zhì)量設(shè)置
updateQualitySettings();
// 開(kāi)始錄制
qDebug() << __FUNCTION__ << "Starting recorder...";
m_recorder.record();
// 啟動(dòng)計(jì)時(shí)器
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...";
// 獲取當(dāng)前輸出位置,用于驗(yàn)證
QUrl outputLocation = m_recorder.outputLocation();
qDebug() << __FUNCTION__ << "Output location:" << outputLocation.toLocalFile();
// 停止錄制
m_recorder.stop();
// 停止計(jì)時(shí)器
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();
}設(shè)置錄制器:
void ScreenRecorder::setupRecorder()
{
qDebug() << __FUNCTION__ << "Setting up recorder...";
// 設(shè)置捕獲會(huì)話(huà)
m_captureSession.setScreenCapture(&m_screenCapture);
m_captureSession.setRecorder(&m_recorder);
// 設(shè)置屏幕捕獲
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();
// 設(shè)置錄制器
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";
// 嘗試使用第一個(gè)可用的編解碼器
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();
// 應(yīng)用當(dāng)前質(zhì)量設(shè)置
updateQualitySettings();
// 連接信號(hào)
connect(&m_recorder, &QMediaRecorder::recorderStateChanged,
this, &ScreenRecorder::handleRecorderStateChanged);
connect(&m_recorder, &QMediaRecorder::errorOccurred,
this, &ScreenRecorder::handleError);
qDebug() << __FUNCTION__ << "Recorder setup complete";
}該功能是Qt結(jié)合ffmpeg來(lái)實(shí)現(xiàn)的,運(yùn)行時(shí)會(huì)輸出相關(guān)信息:qt.multimedia.ffmpeg: Using Qt multimedia with FFmpeg version 7.1 LGPL version 2.1 or later
Qt6還提供了很多非常好用的多媒體類(lèi),可以實(shí)現(xiàn)很多豐富的功能。
到此這篇關(guān)于Qt6+QML實(shí)現(xiàn)Windows屏幕錄制功能的文章就介紹到這了,更多相關(guān)Qt6屏幕錄制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Qt6 QML實(shí)現(xiàn)DateTimePicker組件的示例代碼
- Qt?QML實(shí)現(xiàn)無(wú)邊框窗口的實(shí)例代碼
- QML與C++交互之創(chuàng)建自定義對(duì)象的實(shí)現(xiàn)
- Qt?Qml實(shí)現(xiàn)毛玻璃效果
- Qt qml實(shí)現(xiàn)動(dòng)態(tài)輪播圖效果
- 基于Qml實(shí)現(xiàn)水印工具
- QML與C++幾種交互方式
- Qt QML使用虛擬鍵盤(pán)的示例代碼
- C++與QML進(jìn)行數(shù)據(jù)交互的常見(jiàn)方法總結(jié)
- C++與QML交互的項(xiàng)目實(shí)踐
- Qt6 QML Flickable控件詳解
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)經(jīng)典24點(diǎn)紙牌益智游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)經(jīng)典24點(diǎn)紙牌益智游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
C++入門(mén)之實(shí)現(xiàn)十步萬(wàn)度游戲
這篇文章主要介紹了C++入門(mén)實(shí)現(xiàn)十步萬(wàn)度游戲,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
C++生成隨機(jī)浮點(diǎn)數(shù)的示例代碼
在C++11之前,我們通常采用rand函數(shù)來(lái)生成隨機(jī)數(shù),但rand函數(shù)對(duì)一些情況顯得難以處理。本文將介紹如何利用C++生成隨機(jī)浮點(diǎn)數(shù),需要的可以參考一下2022-04-04
C語(yǔ)言中二維數(shù)組作為函數(shù)參數(shù)來(lái)傳遞的三種方法
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中二維數(shù)組作為函數(shù)參數(shù)來(lái)傳遞的三種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C語(yǔ)言有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
C++ std::unique_lock 用法實(shí)例詳解
std::unique_lock 是 C++11 提供的一個(gè)用于管理互斥鎖的類(lèi),它提供了更靈活的鎖管理功能,適用于各種多線(xiàn)程場(chǎng)景,這篇文章給大家介紹了C++ std::unique_lock 用法,感興趣的朋友跟隨小編一起看看吧2023-09-09
C語(yǔ)言順序表的基本操作(初始化,插入,刪除,查詢(xún),擴(kuò)容,打印,清空等)
這篇文章主要介紹了C語(yǔ)言順序表的基本操作(初始化,插入,刪除,查詢(xún),擴(kuò)容,打印,清空等),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-02-02
基于Qt實(shí)現(xiàn)離線(xiàn)瓦片地圖下載器
這篇文章主要介紹了如何通過(guò)Qt實(shí)現(xiàn)離線(xiàn)瓦片地圖下載器,文中的示例代碼對(duì)我們學(xué)習(xí)或工作有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-01-01
jQuery移動(dòng)頁(yè)面開(kāi)發(fā)中主題按鈕的設(shè)計(jì)示例
這篇文章主要介紹了jQuery移動(dòng)頁(yè)面開(kāi)發(fā)中主題按鈕的設(shè)計(jì)示例,jQuery是當(dāng)今最具人氣的JavaScript開(kāi)發(fā)類(lèi)庫(kù),需要的朋友可以參考下2015-12-12

