libVLC 捕获鼠标、键盘事件

在实现播放器的时候,我们需要捕获键盘、鼠标事件进行视频快进、快退,或者双击全屏/退出全屏窗口、鼠标右键弹出菜单栏。默认情况下,在使用libVLC库的时候,我们无法捕获这些事件,因为我们将Qt的视频窗口传递给了libVLC。

cpp 复制代码
libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());

但是libVLC提供了两个接口,使得忽略了对鼠标键盘事件的处理,让事件返回到原始Qt的widget上。

cpp 复制代码
	libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);
	libvlc_video_set_key_input(vlc_mediaPlayer, 0);

好了,知道了如何操作了之后,下面开始实现代码。

首先打开文件的时候禁用鼠标、键盘事件,并且设置视频窗口为Qt的Widget控件,libvlc_media_player_set_hwnd。

cpp 复制代码
void showWidget::slotOpenFile()
{
	/*选择文件*/
	QString filename = QFileDialog::getOpenFileName(this, "选择打开的文件", "D:/", tr("*.*"));
	std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));
	vlc_base = libvlc_new(0, NULL);
	vlc_media = libvlc_media_new_path(vlc_base, filename.toUtf8().data());
	if (!vlc_media) {
		return;
	}

	// 创建libvlc实例和媒体播放器
	vlc_mediaPlayer = libvlc_media_player_new_from_media(vlc_media);
	if (!vlc_mediaPlayer) {
		return;
	}
	
	// 等待元数据加载完成
	libvlc_media_parse(vlc_media);

	m_defalutRate = libvlc_video_get_aspect_ratio(vlc_mediaPlayer);
	m_defalutCrop = libvlc_video_get_crop_geometry(vlc_mediaPlayer);

	libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);
	libvlc_video_set_key_input(vlc_mediaPlayer, 0);

	// 获取各种元数据
	const char *title = libvlc_media_get_meta(vlc_media, libvlc_meta_Title);
	const char *artist = libvlc_media_get_meta(vlc_media, libvlc_meta_Artist);
	const char *album = libvlc_media_get_meta(vlc_media, libvlc_meta_Album);
	const char *url = libvlc_media_get_meta(vlc_media, libvlc_meta_URL);
	const char *date = libvlc_media_get_meta(vlc_media, libvlc_meta_Date);
	const char *lang = libvlc_media_get_meta(vlc_media, libvlc_meta_Language);
	int duration = libvlc_media_get_duration(vlc_media);  // 获取时长(单位:毫秒)

	qDebug("Title: %s", title ? title : "N/A");
	qDebug("Artist: %s", artist ? artist : "N/A");
	qDebug("Album: %s", album ? album : "N/A");
	qDebug("Duration: %d ms", duration);
	qDebug("url: %s", url ? url : "N/A");
	qDebug("date: %s", date ? date : "N/A");
	qDebug("lang: %s", lang ? lang : "N/A");
	
	libvlc_media_track_t **tracks;
	int track_count = libvlc_media_tracks_get(vlc_media,&tracks);
	for (unsigned i = 0; i < track_count; i++) 
	{
		libvlc_media_track_t* track = tracks[i];

		// 显示轨道信息
		printf("Track #%u: %s\n", i, track->psz_description);

		// 这里可以获取到每一个轨道的信息,比如轨道类型 track->i_type
		// 可能是 libvlc_track_video, libvlc_track_audio 或者 libvlc_track_text (字幕)

		if (track->i_type == libvlc_track_video) {
			// 处理视频轨道信息
			qDebug("width = %d",track->video->i_width);
			qDebug("height = %d", track->video->i_height);
			qDebug("rate_num = %d", track->video->i_frame_rate_num);
			qDebug("rate_den = %d", track->video->i_frame_rate_den);
		}
		else if (track->i_type == libvlc_track_audio) {
			// 处理音频轨道信息
			qDebug("channels = %d", track->audio->i_channels);
			qDebug("rate = %d", track->audio->i_rate);
		}
		else if (track->i_type == libvlc_track_text) {
			// 处理字幕轨道信息
		}
	}

	//获取事件管理器
	libvlc_event_manager_t *em = libvlc_media_player_event_manager(vlc_mediaPlayer);

	// 注册事件监听器
	libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);
	libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);
	libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);
	libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);
	libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);

	libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());

	QTimer::singleShot(1000, this, &showWidget::slotPlay);
}

然后鼠标右键显示菜单:

代码实现:

cpp 复制代码
	//.h
    QMenu *m_menu = nullptr;
	QAction *m_video = nullptr;

	QAction *m_scaleAction = nullptr;	//缩放
	QAction *m_aspectRatioAction = nullptr;	//宽高比
	QAction *m_cropAction = nullptr;	//裁剪

	QMenu *m_videoMenu = nullptr;
    
    //.cpp
    //总菜单
	m_menu = new QMenu(this);
	m_video = m_menu->addAction("视频");

	//视频菜单
	m_videoMenu = new QMenu(this);
	m_scaleAction = m_videoMenu->addAction("缩放");
	m_aspectRatioAction = m_videoMenu->addAction("宽高比");
	m_cropAction = m_videoMenu->addAction("裁剪");

	m_video->setMenu(m_videoMenu);

	//宽高比菜单
	m_aspectRatioMenu = new QMenu(this);
	m_aspectRatioAction->setMenu(m_aspectRatioMenu);



    

重写鼠标和键盘事件。

cpp 复制代码
protected:
	virtual void mousePressEvent(QMouseEvent *event);
	virtual void mouseDoubleClickEvent(QMouseEvent *event);
	virtual void keyPressEvent(QKeyEvent *event);

鼠标双击全屏。

cpp 复制代码
void showWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
	if (this->isFullScreen())
	{
		this->showNormal();
	}
	else
	{
		this->showFullScreen();
	}
}

键盘事件:调节W、S键音量大小和space键暂停和播放。

cpp 复制代码
void showWidget::keyPressEvent(QKeyEvent *event)
{
	if (!vlc_mediaPlayer)
		return;

	int value = ui.hSliderVolumn->value();
	if (event->key() == Qt::Key_W)	//添加音量
	{
		qDebug() << "up";
		slotValueChanged(value+10);
	}
	else if (event->key() == Qt::Key_S)	//减小音量
	{
		slotValueChanged(value - 10);
	}
	else if (event->key() == Qt::Key_Space)
	{
		if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Playing)
		{
			libvlc_media_player_pause(vlc_mediaPlayer);
		}
		else if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Paused)
		{
			libvlc_media_player_play(vlc_mediaPlayer);
		}
	}
}


void showWidget::slotValueChanged(int value)
{
	if (vlc_mediaPlayer)
		libvlc_audio_set_volume(vlc_mediaPlayer, value);
}

鼠标点击弹出菜单。

cpp 复制代码
void showWidget::mousePressEvent(QMouseEvent *event)
{
	switch (event->button())
	{
	case Qt::RightButton:
		//this->setWindowState(Qt::WindowMinimized);
		m_menu->exec(event->globalPos());
		break;
	default:
		QWidget::mousePressEvent(event);
	}
}

更多参考:

libVLC 事件机制-CSDN博客

libVLC windows开发环境搭建-CSDN博客

https://sunnnnnn666.blog.csdn.net/article/details/136854500

libVLC 元数据-CSDN博客

libVLC 添加图片和文本水印-CSDN博客

https://sunnnnnn666.blog.csdn.net/article/details/136920169

https://sunnnnnn666.blog.csdn.net/article/details/137023036

相关推荐
安步当歌1 小时前
【WebRTC】视频编码链路中各个类的简单分析——VideoStreamEncoder
音视频·webrtc·视频编解码·video-codec
顾北川_野1 小时前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
顶呱呱程序1 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
苏三有春2 小时前
PyQt5实战——UTF-8编码器功能的实现(六)
开发语言·qt
EasyCVR2 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频
runing_an_min2 小时前
ffmpeg 视频滤镜:屏蔽边框杂色- fillborders
ffmpeg·音视频·fillborders
Vanranrr2 小时前
C++ QT
java·c++·qt
兆。2 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
徒步僧13 小时前
ThingsBoard规则链节点:RPC Call Reply节点详解
qt·microsoft·rpc
可峰科技15 小时前
斗破QT编程入门系列之一:认识Qt:初步使用(四星斗师)
开发语言·qt