导入一个视频文件并截取某一帧
简单介绍
Qt 6的Qt Multimedia模块替换了Qt 5.x的Qt Multimedia模块。使用Qt 5的Qt Multimedia的现有代码可以通过有限的努力进行移植。
也就是可以用QVideoSink来获取视频单帧了
准备工作
引入Multimedia
CMake示例:
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Multimedia)
target_link_libraries(QtTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt6::Multimedia)需要引用的头文件
#include <QMediaPlayer>
#include <QVideoSink>
#include <QVideoFrame>使用教程
获取单帧
.h private添加
QMediaPlayer* m_player = nullptr;.cpp使用样例
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_player = new QMediaPlayer(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QVideoSink* videoSink = new QVideoSink(this);
m_player->setVideoOutput(videoSink);
//加载视频文件
QString str = QFileDialog::getOpenFileName();
m_player->setSource(QUrl(str));
//连接 QVideoSink 的 videoFrameChanged 信号
connect(videoSink, &QVideoSink::videoFrameChanged, [&](const QVideoFrame &frame) {
//获取帧时间戳
m_player->setPosition(5000);
QImage image = frame.toImage(); //将 QVideoFrame 转换为 QImage
image.save("screenshot_at_5_seconds.png"); //保存图片
m_player->stop(); // 停止播放
}
});
// 开始播放视频
m_player->play();
}获取多帧
.h中添加loop
QEventLoop loop;如果需要循环获取,可以使用loop进行局部循环
//循环七秒
for (int i = 0; i <= m_player->duration(); i += 7000)
{
m_player->setPosition(i);
//使用局部事件循环等待帧捕获
bool frameCaptured = false;
//连接视频帧捕获的信号
connect(videoSink, &QVideoSink::videoFrameChanged, this, [&](const QVideoFrame &frame) mutable {
if (!frameCaptured && frame.isValid()) {
frameCaptured = true; //第一次捕获后设置为 true
QImage image = frame.toImage();
ui->label->setPixmap(QPixmap::fromImage(image));
if (!image.isNull()) {
//保存图像为 jpg
image.save(QString::number(i) + ".jpg", "JPG");
}
//断开信号,停止等待
disconnect(videoSink, &QVideoSink::videoFrameChanged, this, nullptr);
}
});
//开启局部事件循环,等待帧捕获完成
loop.exec();
}
还没有评论
欢迎留下你的观点,保持交流的清晰和友好。
写下评论
请先使用 GitHub 登录,之后就可以评论。