Qt 音频和视频开发 4-vlc 读取和控制
最编程
2024-05-05 11:44:23
...
一、前言
vlc本身是个全功能的很牛逼的播放器,你能够想到的播放的功能他都有,比如获取视频文件的长度、唱片的封面、当前播放进度、设置播放进度、声音控制、静音控制等,这些vlc都给你封装好了,你直接调用对应的api函数即可。
看vlc的官方对vlc的更新频率也是蛮高的,所以在各种新的视频标准和格式出来以后,他也是在不断的更新完善,比如H265,8K视频等,都能正常的播放,查阅vlc的动态库目录可以看见,vlc的部分解码用的就是ffmpeg,所以知道了为啥他这么强大了吧,原来是依赖ffmpeg这个超级牛逼的全功能解码库呢。
用vlc做控制这块有两种处理方式,一种是在线程中来定时读取,比如读取播放进度、当前各种状态、当前音量、静音等,还有一种方式是采用事件回调的形式,默认建议事件回调的机制,能够拿到很多事件消息,效率也更高。你只需要在打开视频以前调用libvlc_event_attach订阅自己感兴趣的事件,在不需要的时候比如关闭的时候调用libvlc_event_detach注销订阅的事件即可。
二、功能特点
- 多线程实时播放视频流和本地视频。
- 支持windows+linux+mac,支持vlc2和vlc3。
- 多线程显示图像,不卡主界面。
- 自动重连网络摄像头。
- 可设置边框大小即偏移量和边框颜色。
- 可设置是否绘制OSD标签即标签文本或图片和标签位置。
- 可设置两种OSD位置和风格。
- 可设置是否保存到文件以及文件名。
- 可直接拖曳文件到vlcwidget控件播放。
- 支持h265视频流+rtmp等常见视频流。
- 可暂停播放和继续播放。
- 支持回调模式和句柄两种模式。
- 支持线程读取进度等信息和事件回调两种处理模式。
- 自动将当前播放位置和音量大小是否静音以信号发出去。
- 提供接口设置播放位置和音量及设置静音。
- 支持存储单个视频文件和定时存储视频文件。
- 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。
三、效果图
四、相关站点
- 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
- 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
- 个人主页:https://blog.****.net/feiyangqingyun
- 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
- 体验地址:https://blog.****.net/feiyangqingyun/article/details/97565652
五、核心代码
void VlcThread::setSize(int width, int height)
{
if (vlcPlayer != NULL) {
QString option = QString("%1:%2").arg(width).arg(height);
QByteArray data = option.toUtf8();
const char *arg = data.constData();
//一旦打开视频以后要动态更改宽高比,值只能是vlc认识的比如 16:9 1:1 之类的
//const char *arg = "4:3";
libvlc_video_set_aspect_ratio(vlcPlayer, arg);
}
}
bool VlcThread::getIsPlaying()
{
bool isPlaying = false;
if (vlcPlayer != NULL) {
int result = libvlc_media_player_is_playing(vlcPlayer);
isPlaying = (result != 0);
}
return isPlaying;
}
VlcThread::VlcState VlcThread::getState()
{
VlcState state = VlcThread::VlcState_NothingSpecial;
if (vlcPlayer != NULL) {
state = (VlcState)libvlc_media_player_get_state(vlcPlayer);
}
return state;
}
uint VlcThread::getLength()
{
uint length = 0;
if (vlcPlayer != NULL) {
length = libvlc_media_player_get_length(vlcPlayer);
}
return length;
}
uint VlcThread::getPosition()
{
uint positon = 0;
if (vlcPlayer != NULL) {
positon = libvlc_media_player_get_time(vlcPlayer);
}
return positon;
}
void VlcThread::setPosition(int position)
{
if (vlcPlayer != NULL && !isRtsp) {
libvlc_media_player_set_time(vlcPlayer, position);
}
}
bool VlcThread::getMute()
{
bool ok = false;
if (vlcPlayer != NULL) {
int result = libvlc_audio_get_mute(vlcPlayer);
ok = (result == 0);
}
return ok;
}
void VlcThread::setMute(bool mute)
{
if (vlcPlayer != NULL) {
libvlc_audio_set_mute(vlcPlayer, mute ? 1 : 0);
}
}
int VlcThread::getVolume()
{
int volume = 0;
if (vlcPlayer != NULL) {
volume = libvlc_audio_get_volume(vlcPlayer);
}
return volume;
}
void VlcThread::setVolume(int volume)
{
if (vlcPlayer != NULL) {
libvlc_audio_set_volume(vlcPlayer, volume);
}
}
int VlcThread::getTrack()
{
int track = 0;
if (vlcPlayer != NULL) {
track = libvlc_audio_get_track(vlcPlayer);
}
return track;
}
int VlcThread::getTrackCount()
{
int trackCount = 0;
if (vlcPlayer != NULL) {
trackCount = libvlc_audio_get_track_count(vlcPlayer);
}
return trackCount;
}
void VlcThread::setTrack(int track)
{
if (vlcPlayer != NULL) {
track = libvlc_audio_set_track(vlcPlayer, track);
}
}
推荐阅读
-
Qt 音频和视频开发 4-vlc 读取和控制
-
[物联网部分 ] 12 - 联发科 MTK8516 开发环境设置 - MT8516 还支持多达 8 个 TDM 通道和 2 个 PDM 输入,以支持远场(Far-field)麦克风语音控制和智能音频设备的多源音频输入。
-
PHP Websocket 开发教程:构建实时音频和视频通话功能
-
音频和视频开发之旅--音频基础概念、交叉编译原理与实践(LAME 交叉编译)(iOS)
-
实时音频和视频技术的发展与应用-1.1 双重音频和视频 从架构上看,双人音视频系统相对简单明了。红点代表房间信令服务,房间信令服务的主要功能是管理房间信息,实现容量协商和上下行链路的质量调节,例如当下行信道发生拥塞时,上行线路的码率和分辨率会降低。 在传输信道层面,我们的策略是优先直连,在跨区域、跨运营商的情况下,我们会选择单中转或双中转信道,在策略上尽量保持直连和中转信道同时存在,当其中一个信道的质量不好时,系统会自动切断到另一个信道的流量。 1.2 多人音视频 多人视频通话的产品形态是整个房间不超过 50 人,大盘平均房间规模约为 4.x 人,房间内部最多满足一个大视频和三个小视频(四屏)。根据这一条件,我们在架构中采用了典型的 SFU 小房间设计。 上图中的红点代表房间信令服务,主要用于房间管理和状态信息同步。房间管理主要包括用户列表的管理,例如哪些用户打开了视频/音频,我看了谁,谁看了我,这些都是基于房间管理的信息,然后房间信令服务会将这些信息同步到媒体传输服务进行数据分发。 房间服务的另一个作用是房间级容量协商和质量控制,例如,房间里的每个人一开始都支持 H.265 编码,当某个时刻进来一个只支持 H.264 编码的用户时,房间里所有的上游主播就必须把 H.265 切成 H.264。还有一种情况是,房间里有一定比例的人下行链路信道质量较差,这会导致上行链路房间质量下降。 在传输层面,我们采用的是单层分布式媒体传输网络,大家都选择中转方式,不区分双人和多人,采用 Full-Mesh 传输机制将所有数据推送过去,比如一个节点上的人并不都看另外两个人的视频,但还是会将视频推送给他们。
-
音频/视频开发必备技能:市场上最常用工具和软件详解
-
腾讯视频直播 02-推流-美颜滤镜 同样,腾讯云提供了 setBeautyFilter 方法来设置美颜风格、磨皮程度、美白程度和泛红程度 //style 磨皮风格:0:平滑 1:自然 2:朦胧 //美容级别:0-9。值为 0 时关闭美颜效果。默认值:0,关闭美颜效果。 //美白级别:取值 0-9。值为 0 时,将关闭美白效果。默认值:0,关闭美白效果。 //ruddyLevel:取值范围为 0-9。值为 0 时关闭美白效果。默认值:0,关闭美白效果。 public boolean setBeautyFilter(int style, int beautyLevel, int whiteningLevel, int ruddyLevel);; public boolean setBeautyFilter(int style, int beautyLevel, int whiteningLevel, int ruddyLevel) 滤镜 setFilter 方法可以设置滤镜效果,滤镜本身是一个直方图文件。setSpecialRatio 方法可以设置滤镜的程度,从 0 到 1,越大滤镜效果越明显,默认值为 0.5。 Bitmap bitmap = BitmapUtils.decodeResource(getResources, R.drawable.langman); if (mLivePusher) if (mLivePusher ! = null) { mLivePusher.setFilter(bmp); } 控制摄像头 腾讯云 sdk 默认为前置摄像头(可以通过修改 TXLivePushConfig 的配置函数 setFrontCamera 来修改默认值),调用一次 switchCamera 就切换一次,注意切换摄像头前要确保 TXLivePushConfig 和 TXLivePusher 对象已经初始化。 mLivePushConfig.setFrontCamera(true); // 默认前置摄像头。 mLivePusher.switchCamera; //切换摄像头。 ⑦ 设置徽标水印 腾讯视频云目前支持两种设置水印的方式:一种是在流媒体 SDK 中设置水印,原理是在 SDK 中对视频进行编码前在画面中设置水印。另一种方式是在云端设置水印,即由云端解析视频并添加水印标识。 建议使用 SDK 添加水印,因为在云端添加水印会有问题。下面是添加水印的 SDK 介绍: //设置视频水印 mLivePushConfig.setWatermark(BitmapFactory.decodeResource(getResources,R.drawable.watermark), 10, 10); // 最后两个参数是视频的水印。 //最后两个参数是水印位置的 X 轴和 Y 轴坐标。 mLivePusher.setConfig(mLivePushConfig); 如果需要对水印图像的位置进行模型适配,则需要调用水印规范化接口。 /设置视频水印 mLivePushConfig.setWatermark(mBitmap, 0.02f, 0.05f, 0.2f); //参数为水印图像。 //参数包括水印图像的位图、水印位置的 X 轴坐标、水印位置的 Y 轴坐标和水印宽度。后三个参数的范围是 [0,1]。 // 最后两个参数是水印位置的 X 轴坐标和 Y 轴坐标。 mLivePusher.setConfig(mLivePushConfig); TXLivePushConfig 中的 setHardwareAcceleration 方法可以启用或禁用硬件编码。 if (mHWVideoEncode){ if (mLivePushConfig ! = null) { if (Build.VERSION.SDK_INT < 18){ Toast.makeText(getApplicationContext, "Hardware acceleration failed, current phone API level is too low (min 18)"、 Toast.LENGTH_SHORT).show; mHWVideoEncode = false; } } } } mLivePushConfig.setHardwareAcceleration(mHWVideoEncode ? TXLiveConstants.ENCODE_VIDEO_HARDWARE : TXLiveConstants.ENCODE_VIDEO_SOFTWARE); mLivePusher.setConfig(mLivePushConfig); // 如果您不确定何时启用硬件加速,建议将其设置为 ENCODE_VIDEO_AUTO。 // 默认情况下启用软件编码,但如果手机的 CPU 使用率超过 80% 或帧速率为 10,SDK 将自动切换到硬件编码。 ⑨ 后台推流 在常规模式下,一旦应用程序进入后台,摄像头捕捉数据的能力就会被 Android 禁用,这意味着 SDK 无法继续捕捉和编码音频和视频数据。如果我们什么都不做,故事就会按照下面的脚本发展: 阶段 1(背景剪切后 10 秒 ->)- CDN 无法将视频流传输给观众,因为没有数据,观众看到的是主帧。 阶段 2(10 秒-> 70 秒)--观众一方的播放器因无法接收到直播流而退出,房间里空无一人。 第 3 阶段(70 秒后)--服务器直接断开了推送流媒体的 RTMP 链接,主播需要重新打开直播才能继续。 主播可能只是短暂地接了一个紧急电话,但各云提供商的安全措施会迫使主播的直播提前结束。 1) 设置 setPauseFlag 在开始推流之前,使用 TXLivePushConfig 的 setPauseImg 接口设置一个等待图像,其含义建议为 "主播将暂时离开,稍后再回来"。
-
使用 FFmpeg 开发音频和视频流 (III) - 将视频 YUV 格式编码为 H264
-
使用QT进行软件开发:创建一个完整的视频播放器和多媒体播放器(MDK SDK)教程