QT6 与输入输出设备(实现 QT 6 录制 或 QT 6 截图)

目录

1·多媒体管理中心类

  头文件:

  代码:

  QMediaCaptureSession     重要函数

 ( 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();

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值