目录
( 1 ) void setCamera(QCamera *camera);
( 2 ) void setRecorder(QMediaRecorder *recorder);
( 3 ) void setVideoOutput(QObject *output);
( 4 ) void setImageCapture(QImageCapture *imageCapture);
( 5 ) void setVideoSink(QVideoSink *sink);
1·多媒体管理中心类
QT6 使用的是 QMediaCaptureSession 多媒体管理中心类来实现操作处理
下面,我们假设存在以下声明
头文件:
#include <QApplication>
#include <QLabel>
#include <QCamera>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QMediaRecorder>
#include <QImageCapture>
#include <QVideoWidget>
#include <QVideoSink>
代码:
// 媒体会话
QMediaCaptureSession captureSession;
QMediaCaptureSession 重要函数
( 1 ) void setCamera(QCamera *camera);
该功能允许设置一个主要摄像机。
设置以后,通常媒体都会以该摄像机为主要的视频设备输入。
一般情况可以使用以下代码实现。
// 默认的视频输入设备
QCameraDevice defaultVideoInput = QMediaDevices::defaultVideoInput();
// 设置摄像机
QCamera camera(defaultVideoInput);
// 设置到媒体内容中心
captureSession.setCamera(&camera);
( 2 ) void setRecorder(QMediaRecorder *recorder);
该功能允许设置一个主要录制对象。
设置以后,通常媒体都会以该对象为主要的录制输出。
注:录制输出并非设备输出,也并非是主要的截图实现途径
一般情况可以使用以下代码实现。
// 媒体录制
QMediaRecorder recorder;
captureSession.setRecorder(&recorder);
( 3 ) void setVideoOutput(QObject *output);
该功能允许设置一个主要输出对象。
output 需要实现一个 QVideoSink *videoSink() 函数,否则只能祝您好运
使用 QMediaCaptureSession 时,也必须存在 QVideoSink 设备,否则 QMediaCaptureSession 对象将会无法正常工作
设置以后,通常媒体都会以该对象为主要的视频输出。
一般情况可以使用以下代码实现。
// 显示窗口
QVideoWidget showVieo;
captureSession.setVideoOutput(&showVieo);
当需要显示内容的时候,可以使用一下代码。
showVieo.show();
但是若是使用了 摄像头,则需要使用加以下代码
// 假设存在摄像头 QCamera camera( QMediaDevices::defaultVideoInput());
camera.start();
( 4 ) void setImageCapture(QImageCapture *imageCapture);
设置一个图片对象,但该对象并非被动调用,而是使用主动调用,否则它仅仅是一个驻留!
使用一下方式可以实现每次播放一帧的时候就会发生截图效果
// 截图显示
QLabel captureImageLabel;
captureImageLabel.show();
// 获取视频输出设备槽
QVideoSink *videoSink = captureSession.videoSink();
// 信号
QObject::connect(videoSink, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) {
captureImage.capture();
});
QObject::connect(&captureImage, &QImageCapture::imageCaptured, [&]( int id, const QImage &preview ) {
captureImageLabel.setPixmap(QPixmap::fromImage(preview));
qDebug() << "id : " << id;
});
( 5 ) void setVideoSink(QVideoSink *sink);
当没有调用 void setVideoOutput(QObject *output); 来设置他的 QVideoSink 设备时,可以使用该函数来设置一个简单的 QVideoSink 设备。
// 设备
QVideoSink videoSink ;
captureSession.setVideoSink(&videoSink);
// 拍摄显示
QLabel captureImageLabel;
// 信号
QObject::connect(&videoSink, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) {
QPixmap pixmap = QPixmap::fromImage(frame.toImage());
pixmap = pixmap.scaled(captureImageLabel.width(), captureImageLabel.height(), Qt::KeepAspectRatio, Qt::FastTransformation);
captureImageLabel.setPixmap(pixmap);
});
这种方式明显更加简单,但同样的,失去了它应有的窗口显示功能
案例
#include <QApplication>
#include <QMessageBox>
#include <QDir>
#include <QLabel>
#include <QCamera>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QMediaRecorder>
#include <QImageCapture>
#include <QVideoWidget>
#include <QVideoSink>
int main( int argc, char *argv[] ) {
QApplication a(argc, argv);
if( QMediaDevices::videoInputs().count() == 0 ) {
QMessageBox::information(nullptr, QObject::tr("错误"), QObject::tr("没有找到输入设备"));
return -1;
}
// 默认的视频输入设备
QCameraDevice defaultVideoInput = QMediaDevices::defaultVideoInput();
// 设置摄像机
QCamera camera(defaultVideoInput);
// 媒体会话
QMediaCaptureSession captureSession;
// 静态拍摄
QImageCapture captureImage;
// 媒体录制
QMediaRecorder recorder;
// 显示窗口
QVideoWidget showVieo;
// 拍摄显示
QLabel captureImageLabel;
captureSession.setCamera(&camera);
captureSession.setRecorder(&recorder);
captureSession.setVideoOutput(&showVieo);
captureSession.setImageCapture(&captureImage);
QVideoSink *videoSink = captureSession.videoSink();
// 信号
QObject::connect(videoSink, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) {
// 每帧都拍摄
captureImage.capture();
});
recorder.setQuality(QMediaRecorder::HighQuality);
// 使用 / 代替 \\,否则有时候会出现一些 bug
QString localfile = QDir::currentPath().append(QDir::separator()).append("recorder.mp4").replace("\\", "/");
recorder.setOutputLocation(QUrl::fromLocalFile(localfile));
QObject::connect(&recorder, &QMediaRecorder::recorderStateChanged, [&]( QMediaRecorder::RecorderState state ) {
qDebug() << "state : " << state;
});
QObject::connect(&captureImage, &QImageCapture::imageCaptured, [&]( int id, const QImage &preview ) {
// 不安全返回
if( preview.isNull() )
return;
// 截图缩放
QPixmap pixmap = QPixmap::fromImage(preview);
size_t height = captureImageLabel.height(),
width = captureImageLabel.width();
pixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::FastTransformation);
// 不安全返回
if( pixmap.isNull() )
return;
// 拍摄完成之后实现更新窗口
captureImageLabel.setPixmap(pixmap);
// 输出帧数 id
int mod = id % 200;
qDebug() << "id : " << id << ", mod = " << mod;
if( id > 0 )
if( mod == 0 )
recorder.stop();
});
camera.start();
recorder.record();
showVieo.show();
showVieo.setWindowTitle(QObject::tr("视频播放窗口"));
QSize size = showVieo.size() / 2;
const auto &mapFromGlobal = showVieo.mapToGlobal(QPoint(size.width(), size.height()));
QRect geometry = showVieo.geometry();
captureImageLabel.setGeometry(mapFromGlobal.x(), mapFromGlobal.y(), size.width(), size.height());
captureImageLabel.setWindowTitle(QObject::tr("拍摄截图预览"));
captureImageLabel.show();
return a.exec();
}
若正常运行,应该可以出现以上的2个窗口,并且在该编译结果的路径当中会出现一个 “recorder.mp4” 的文件
结束
在结尾处并没有实现音频的输入,但没有问题的话,可以按照摄像头输入一般来实现
QAudioInput audioInput(QMediaDevices::defaultAudioInput());
captureSession.setAudioInput(&input);
recorder.setQuality(QMediaRecorder::HighQuality);
QString localfile = QDir::currentPath().append(QDir::separator()).append("recorder.mp4");
recorder.setOutputLocation(QUrl::fromLocalFile(localfile));
recorder.record();