一、前言

用mpv来读取文件的信息,以及设置当前播放进度,音量、静音等,和当时vlc封装的功能一样,只不过vlc是通过调用函数接口去处理,而mpv是通过读取和设置属性来处理,vlc支持定时器或者线程中函数方法去读取状态,也支持事件回调去拿到对应的状态改变,mpv当然也支持,而且还更方便,主要的工作量或者花费的时间在如何知道有哪些属性、分别是什么功能含义,这个在官方都列出来了(http://mpv.io/manual/master/#options、http://mpv.io/manual/master/#list-of-input-commands、http://mpv.io/manual/master/#properties),不过都是英文就是,大部分程序员应该是没有什么难度的,大不了鼠标右键翻译成中文即可,哈哈,相信不少人都这么干过,很多浏览器默认就支持鼠标右键菜单翻译的,实在是很方便的,本人在查阅很多英文文档的时候,用的也是蛮多的,包括Qt官方的文档和BUG报告页面,但是建议在搜索问题的时候还是建议尽量用英文的描述去搜索,这样才能搜索的更精确。

常用的一些属性:

  1. 视频原始宽度高度 width height
  2. 视频缩放后宽度高度 dwidth dheight
  3. 保存视频文件 stream-record 为空则表示停止录像
  4. 视频宽高比 video-aspect
  5. 暂停播放 pause yes表示暂停no表示继续
  6. 视频文件时长 duration
  7. 静音 mute yes表示静音no表示非静音
  8. 音量 volume int值0-100
  9. 获取播放进度 time-pos
  10. 设置播放进度 seek
  11. 当前音轨 aid
  12. 音轨数量 track-list/count
  13. 截图 screenshot-to-file

二、功能特点

  1. 多线程实时播放视频流+本地视频等。
  2. 支持windows+linux+mac。
  3. 多线程显示图像,不卡主界面。
  4. 自动重连网络摄像头。
  5. 可设置是否保存到文件以及文件名。
  6. 可直接拖曳文件到mpvwidget控件播放。
  7. 支持h265视频流+rtmp等常见视频流。
  8. 可暂停播放和继续播放。
  9. 支持存储单个视频文件和定时存储视频文件。
  10. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。
  11. 可设置画面拉伸填充或者等比例填充。
  12. 可对视频进行截图(原始图片)和截屏。
  13. 录像文件存储MP4文件。
  14. 支持qsv、dxva2、d3d11va等硬解码。

三、效果图

四、相关站点

  1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  5. 体验地址:https://blog.csdn.net/feiyangqingyun/article/details/97565652

五、核心代码

void MpvThread::readMediaInfo()
{
if (mpvPlayer != NULL) {
QVariant width = getValue("width");
QVariant height = getValue("height");
videoWidth = width.toInt();
videoHeight = height.toInt();
qDebug() << TIMEMS << url << "videoWidth:" << videoWidth << "videoHeight:" << videoHeight;
}
} void MpvThread::readPlayInfo()
{
//定义长度变量用于存储文件时长
uint length = getLength();
//定义变量存储声音大小,默认值1
int volume = getVolume();
//定义变量存储是否静音
bool mute = getMute(); //发送文件时长信号
emit fileLengthReceive(length);
//发送当前音量值信号
emit fileVolumeReceive(volume, mute); //改变标志位启动读取播放进度
if (!callbackevent) {
isReadPosition = true;
}
} void MpvThread::readPosition()
{
//获取播放进度位置
int position = getPosition();
//获取是否播放结束
bool isPlay = (position != 0);
if (position > 0 && !isRtsp) {
emit filePositionReceive(position, isPlay);
} //本地文件播放结束
if (!isPlay && !isRtsp && suffix != "dshow") {
this->stop();
}
} void MpvThread::setSize()
{
if (mpvPlayer != NULL) {
double width = playWidget->width();
double height = playWidget->height();
setValue("video-aspect", width / height);
}
} bool MpvThread::getIsPlaying()
{
//在视频流模式下,不是暂停状态,当前的位置和上一次的位置一致则表示断了
//进度为0表示没有播放成功也需要重新加载
bool isPlay = this->isRunning();
if (isPlay && isRtsp && !getValue("pause").toBool()) {
int position = getPosition();
if (position == 0 || this->position == position) {
isPlay = false;
} this->position = position;
} return isPlay;
} uint MpvThread::getLength()
{
uint length = 0;
if (mpvPlayer != NULL) {
QVariant value = getValue("duration");
length = value.toDouble() * 1000;
} return length;
} uint MpvThread::getPosition()
{
uint positon = 0;
if (mpvPlayer != NULL) {
QVariant value = getValue("time-pos");
positon = value.toDouble() * 1000;
} return positon;
} void MpvThread::setPosition(int position)
{
if (mpvPlayer != NULL && !isRtsp) {
command(QVariantList() << "seek" << position / 1000 << "absolute");
}
} bool MpvThread::getMute()
{
bool ok = false;
if (mpvPlayer != NULL) {
QVariant value = getValue("mute");
ok = !value.toBool();
} return ok;
} void MpvThread::setMute(bool mute)
{
if (mpvPlayer != NULL) {
setValue("mute", mute ? "yes" : "no");
}
} int MpvThread::getVolume()
{
int volume = 0;
if (mpvPlayer != NULL) {
QVariant value = getValue("volume");
volume = value.toInt();
} return volume;
} void MpvThread::setVolume(int volume)
{
if (mpvPlayer != NULL) {
setValue("volume", volume);
}
} int MpvThread::getTrack()
{
int track = 0;
if (mpvPlayer != NULL) {
QVariant value = getValue("aid");
track = value.toInt();
} return track;
} int MpvThread::getTrackCount()
{
int trackCount = 0;
if (mpvPlayer != NULL) {
QVariant value = getValue("track-list/count");
trackCount = value.toInt();
} return trackCount;
} void MpvThread::setTrack(int track)
{
if (mpvPlayer != NULL) {
setValue("aid", track);
}
}

Qt音视频开发14-mpv读取和控制的更多相关文章

  1. Moviepy音视频开发:视频转gif动画或jpg图片exe图形化工具开发案例

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 老猿之所以学习和研究Moviepy的使用,是因为需要一个将视频转成动画的工具,当时在网上到处搜索查找免费使用工具,结果找了很多自称免费的工具,但转完 ...

  2. 【秒懂音视频开发】02_Windows开发环境搭建

    音视频开发库的选择 每个主流平台基本都有自己的音视频开发库(API),用以处理音视频数据,比如: iOS:AVFoundation.AudioUnit等 Android:MediaPlayer.Med ...

  3. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

  4. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  5. Android开发 音视频开发需要了解的专业术语知识

    前言 在摸索一段时间的音视频开发后,越来越发现这个坑的深度真是特别的深. 除了了解Android自带的音视频处理API以外,还得了解一些视频与音频方面的知识.这篇博客就是主要讲解这方面的专业术语.内容 ...

  6. 音视频开发-FFmpeg

    音视频开发是个非常复杂的,庞大的开发话题,初涉其中,先看一下结合 OEIP(开源项目) 新增例子. 可以打开flv,mp4类型文件,以及rtmp协议音视频数据,声音的播放使用SDL. 把采集的麦/声卡 ...

  7. Python音视频开发:消除抖音短视频Logo的图形化工具实现

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...

  8. Python音视频开发:消除抖音短视频Logo和去电视台标

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...

  9. moviepy音视频开发:使用credits1给视频加片头片尾字幕

    ☞ ░ 前往老猿Python博文目录 ░ 一.概述 在<moviepy音视频剪辑:视频基类VideoClip子类DataVideoClip.UpdatedVideoClip.ImageClip. ...

  10. moviepy音视频开发:音频剪辑基类AudioClip

    ☞ ░ 前往老猿Python博文目录 ░ 一.背景知识介绍 1.1.声音三要素: 音调:人耳对声音高低的感觉称为音调(也叫音频).音调主要与声波的频率有关.声波的频率高,则音调也高. 音量:也就是响度 ...

随机推荐

  1. nodejs redis 小试牛刀

    一.环境安装 书接上文,浅学Redis之后,服务器已经安装Redis了,用 nodejs 链接 redis 之前,先安装 nodejs 环境. 1.安装fnm (1)压缩包fnm-linux.zip搞 ...

  2. python项目实战——人生重开模拟器

    文章目录 1.菜单栏的编写 2.玩家确定颜值.体质.智力.家境 3.生成性别 4.设定角色出生点 5.各个年龄段的变化 5.1 幼年阶段 5.2 青年阶段 5.3中年阶段 5.4 晚年阶段 6.整体代 ...

  3. LeetCode题目练习记录 _栈、队列01 _20211012

    LeetCode题目练习记录 _栈.队列01 _20211012 84. 柱状图中最大的矩形 难度困难1581 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . ...

  4. SQL Server 安装图解

    此安装步骤适用于首次安装 一.SQL Server 安装 1.双击SQL Server 光盘映像文件,会出现如图所示界面 选择如下图所示的选项 2.输入产品密钥(这里演示密钥进行) 3.配置更新项,检 ...

  5. 如何在Spark键值对数据中,对指定的Key进行输出/筛选/模式匹配

    在用键值对RDD进行操作时,经常会遇到不知道如何筛选出想要数据的情况,这里提供了一些解决方法 目录 1.对固定的Key数据进行查询 2.对不固定的Key数据进行模糊查询 1.对固定的Key数据进行查询 ...

  6. visual studio当中动态库和静态库的联系

    一.为什么要写这篇博客 公司需要调用MNN框架编译之后的动态库和静态库文件来在另外一台没有编译过MNN框架上的机器运行对应的程序,比如说人体关键点检测之类的程序,这个时候了解静态库和动态库的关系就很有 ...

  7. 源码开放:WebSocket应用示例

    1 WebSocket概述 WebSocket是HTML5下一种新的协议(本质上是一个基于TCP的协议),它实现了浏览器与服务器之间的全双工通信,能够节省服务器资源和带宽,达到实时通讯的目的.WebS ...

  8. 2023NOIP A层联测9 风信子+P2048 【NOI2010】 超级钢琴 2023

    P2048 [NOI2010] 超级钢琴 2023NOIP A层联测9 风信子 一年 OI 一场空,一道原题见祖宗-- Ps:超级钢琴是风信子的前置题. 超级钢琴 题意 在一段序列上,选择长度为 \( ...

  9. TreeMap源码分析——深入分析(基于JDK1.6)

    TreeMap有Values.EntrySet.KeySet.PrivateEntryIterator.EntryIterator.ValueIterator.KeyIterator.Descendi ...

  10. js之模块导入与导出:export、export default、module.exports、exports

    前两者export.export default可为一组,是es6的规范,和import匹配,import是es6中的语法标准:后两者module.exports.exports可为一组,是commo ...