导入一个视频文件并截取某一帧
简单介绍
Qt 6的Qt Multimedia模块替换了Qt 5.x的Qt Multimedia模块。使用Qt 5的Qt Multimedia的现有代码可以通过有限的努力进行移植。
也就是可以用QVideoSink来获取视频单帧了
准备工作
引入Multimedia
CMake示例:
1 2
| find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Multimedia) target_link_libraries(QtTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt6::Multimedia)
|
需要引用的头文件
1 2 3
| #include <QMediaPlayer> #include <QVideoSink> #include <QVideoFrame>
|
使用教程
获取单帧
.h private添加
1
| QMediaPlayer* m_player = nullptr;
|
.cpp使用样例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #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)); connect(videoSink, &QVideoSink::videoFrameChanged, [&](const QVideoFrame &frame) { m_player->setPosition(5000); QImage image = frame.toImage(); image.save("screenshot_at_5_seconds.png"); m_player->stop(); } }); m_player->play(); }
|
获取多帧
.h中添加loop
如果需要循环获取,可以使用loop进行局部循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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; QImage image = frame.toImage(); ui->label->setPixmap(QPixmap::fromImage(image)); if (!image.isNull()) { image.save(QString::number(i) + ".jpg", "JPG"); } disconnect(videoSink, &QVideoSink::videoFrameChanged, this, nullptr); } }); loop.exec(); }
|