一、前言

最近将推流程序完善了很多功能,尤其是增加了对多种流媒体服务程序的支持,目前支持mediamtx、LiveQing、EasyDarwin、nginx-rtmp、ZLMediaKit、srs、ABLMediaServer等,其中经过大量的对比测试,个人比较建议使用mediamtx和ZLMediaKit,因为这两者支持的格式众多,不仅同时支持rtsp/rtmp推流,还支持各种格式rtsp/rtmp/hls/flv/ws-flv/webrtc等拉流,涵盖面非常全,而且拉流的画面非常流畅,在局域网没有出现花屏的现象,对视频文件、视频流支持都非常友好。

为了增强程序的拓展性,以便适应后期增加其他流媒体服务器程序,特意将流媒体服务程序的信息用配置文件存取来,可以自行增删改,推流和拉流对应的端口都可以自行修改,这样非常适用于一台电脑多种流媒体服务,通过配置不同的端口来保证同时推流到多个流媒体服务程序,比如windows系统554端口很可能被系统的进程占用,所以需要更改为其他端口,在流媒体服务程序对应的配置文件更改后,还需要在推流程序对应的配置文件中修改,这样后期如果增加了其他的流媒体服务程序,只需要在配置文件增加即可,程序会自动读取并加载到下拉框。

二、效果图















三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_push。

四、功能特点

  1. 支持各种本地视频文件和网络视频文件。
  2. 支持各种网络视频流,网络摄像头,协议包括rtsp、rtmp、http。
  3. 支持将本地摄像头设备推流,可指定分辨率和帧率等。
  4. 支持将本地桌面推流,可指定屏幕区域和帧率等。
  5. 自动启动流媒体服务程序,默认mediamtx(原rtsp-simple-server),可选用srs、EasyDarwin、LiveQing、ZLMediaKit等。
  6. 可实时切换预览视频文件,可切换视频文件播放进度,切换到哪里就推流到哪里。
  7. 推流的清晰度和质量可调。
  8. 可动态添加文件、目录、地址。
  9. 视频文件自动循环推流,如果视频源是视频流,在掉线后会自动重连。
  10. 网络视频流自动重连,重连成功自动继续推流。
  11. 网络视频流实时性极高,延迟极低,延迟时间大概在100ms左右。
  12. 极低CPU占用,4路主码流推流只需要占用0.2%CPU。理论上常规普通PC机器推100路毫无压力,主要性能瓶颈在网络。
  13. 推流可选推流到rtsp/rtmp两种,推流后的数据支持直接rtsp/rtmp/hls/webrtc四种方式访问,可以直接浏览器打开看实时画面。
  14. 可以推流到外网服务器,然后通过手机、电脑、平板等设备播放对应的视频流。
  15. 每个推流都可以手动指定唯一标识符(方便拉流/用户无需记忆复杂的地址),没有指定则按照策略随机生成hash值。
  16. 自动生成测试网页直接打开播放,可以看到实时效果,自动按照数量对应宫格显示。
  17. 推流过程中可以在表格中切换对应推流项,实时预览正在推流的视频,并可以切换视频文件的播放进度。
  18. 音视频同步推流,符合264/265/aac格式的自动原数据推流,不符合的自动转码再推流(会占用一定CPU)。
  19. 转码策略支持三种,自动处理(符合要求的原数据/不符合的转码),仅限文件(文件类型的转码视频),所有转码。
  20. 表格中实时显示每一路推流的分辨率和音视频数据状态,灰色表示没有输入流,黑色表示没有输出流,绿色表示原数据推流,红色表示转码后的数据推流。
  21. 自动重连视频源,自动重连流媒体服务器,保证启动后,推流地址和打开地址都实时重连,只要恢复后立即连上继续采集和推流。
  22. 提供循环推流示例,一个视频源同时推流到多个流媒体服务器,比如打开一个视频同时推流到抖音/快手/B站等,可以作为录播推流,列表循环,非常方便实用。
  23. 根据不同的流媒体服务器类型,自动生成对应的rtsp/rtmp/hls/flv/ws-flv/webrtc地址,用户可以直接复制该地址到播放器或者网页中预览查看。
  24. 编码视频格式可以选择自动处理(源头是264就264/源头是265就265),转H264(强制转264),转H265(强制转265)。
  25. 支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。

五、相关代码

QList<QString> VideoPushUrl::listPushType = QList<QString>();
QList<QString> VideoPushUrl::listPullType = QList<QString>();
QList<int> VideoPushUrl::listPullPort = QList<int>(); void VideoPushUrl::initServerInfo()
{
listPushType.clear();
listPullType.clear();
listPullPort.clear(); listPushType << "mediamtx" << "mediamtx" << "mediamtx" << "mediamtx";
listPullType << "rtsp" << "rtmp" << "hls" << "webrtc";
listPullPort << 8554 << 1935 << 8888 << 8889; listPushType << "LiveQing" << "LiveQing" << "LiveQing" << "LiveQing" << "LiveQing";
listPullType << "rtmp" << "hls" << "flv" << "ws-flv" << "webrtc";
listPullPort << 10085 << 18000 << 18000 << 18000 << 18000; listPushType << "EasyDarwin";
listPullType << "rtsp";
listPullPort << 5541; listPushType << "nginx-rtmp";
listPullType << "rtmp";
listPullPort << 1935; listPushType << "ZLMediaKit" << "ZLMediaKit" << "ZLMediaKit" << "ZLMediaKit" << "ZLMediaKit" << "ZLMediaKit";
listPullType << "rtsp" << "rtmp" << "hls" << "flv" << "ws-flv" << "webrtc";
listPullPort << 554 << 1935 << 80 << 80 << 80 << 80; listPushType << "srs" << "srs" << "srs" << "srs";
listPullType << "rtmp" << "hls" << "flv" << "webrtc";
listPullPort << 1935 << 8080 << 8080 << 8080; listPushType << "ABLMediaServer" << "ABLMediaServer" << "ABLMediaServer" << "ABLMediaServer" << "ABLMediaServer";
listPullType << "rtsp" << "rtmp" << "hls" << "flv" << "ws-flv";
listPullPort << 554 << 1935 << 9088 << 8088 << 6088;
} void VideoPushUrl::initServerInfo(const QString &fileName)
{
listPushType.clear();
listPullType.clear();
listPullPort.clear(); QFile file(fileName);
if (file.open(QFile::ReadOnly | QFile::Text)) {
while (!file.atEnd()) {
QString content = file.readLine();
content.replace("\r", "");
content.replace("\n", "");
if (content.isEmpty()) {
continue;
} QStringList list = content.split(",");
if (list.count() == 3) {
listPushType << list.at(0);
listPullType << list.at(1);
listPullPort << list.at(2).toInt();
}
}
}
} QStringList VideoPushUrl::getPushType()
{
QStringList types;
foreach (QString type, listPushType) {
if (!types.contains(type)) {
types << type;
}
}
return types;
} QString VideoPushUrl::getPushPath(const QString &pushUrl)
{
//("rtsp:", "", "127.0.0.1:5541") ("rtsp:", "", "127.0.0.1:5541", "live") ("rtsp:", "", "127.0.0.1:5541", "live/test")
QString path = "/";
QStringList list = pushUrl.split("/");
int count = list.count();
//从第三位开始后面所有的都是资源目录
for (int i = 3; i < count; ++i) {
path = path + list.at(i) + "/";
} //末尾的斜杠去掉
return path.mid(0, path.length() - 1);
} int VideoPushUrl::getPullPort(const QString &pushType, const QString &pullType)
{
int port = 80;
int count = listPushType.count();
for (int i = 0; i < count; ++i) {
if (listPushType.at(i) == pushType && listPullType.at(i) == pullType) {
port = listPullPort.at(i);
break;
}
}
return port;
} //各种拉流协议分析 https://www.cnblogs.com/xi-jie/p/14031604.html
QString VideoPushUrl::getPullUrl(const QString &pushUrl, const QString &pushType, const QString &pullType, const QString &ip, const QString &flag)
{
//找到对应服务器类型和拉流类型的端口
int port = getPullPort(pushType, pullType);
//资源目录(可以为空)
QString path = getPushPath(pushUrl);
//去掉特殊字符比如?
QString name = flag.split("?").first(); //根据服务器类型获取对应的地址
QString url = QString("://%1:%2%3/%4").arg(ip).arg(port).arg(path).arg(name);
if (pushType == "mediamtx") {
//同时支持rtsp/rtmp推拉流(非常棒)
if (pullType == "rtsp") {
url = "rtsp" + url;
} else if (pullType == "rtmp") {
url = "rtmp" + url;
} else if (pullType == "hls") {
url = "http" + url;
} else if (pullType == "webrtc") {
url = "http" + url;
}
} else if (pushType == "LiveQing") {
//只支持rtmp推流
if (pullType == "rtmp") {
url = QString("rtmp://%1:%2/hls/%3").arg(ip).arg(port).arg(name);
} else if (pullType == "hls") {
url = QString("http://%1:%2/hls/%3/%3_live.m3u8").arg(ip).arg(port).arg(name);
} else if (pullType == "flv") {
url = QString("http://%1:%2/flv/hls/%3.flv").arg(ip).arg(port).arg(name);
} else if (pullType == "ws-flv") {
url = QString("ws://%1:%2/ws-flv/hls/%3.flv").arg(ip).arg(port).arg(name);
} else if (pullType == "webrtc") {
url = QString("webrtc://%1:%2/rtc/hls/%3").arg(ip).arg(port).arg(name);
}
} else if (pushType == "EasyDarwin") {
//只支持rtsp推流拉流
if (pullType == "rtsp") {
url = "rtsp" + url;
}
} else if (pushType == "nginx-rtmp") {
//只支持rtmp推流拉流
if (pullType == "rtmp") {
url = "rtmp" + url;
}
} else if (pushType == "ZLMediaKit") {
//同时支持rtsp/rtmp推拉流(名气最大/用户最多)
if (pullType == "rtsp") {
url = "rtsp" + url;
} else if (pullType == "rtmp") {
url = "rtmp" + url;
} else if (pullType == "hls") {
url = "http" + url + "/hls.m3u8";
} else if (pullType == "flv") {
url = "http" + url + ".live.flv";
} else if (pullType == "ws-flv") {
url = "ws" + url + ".live.flv";
} else if (pullType == "webrtc") { }
} else if (pushType == "srs") {
//不支持rtsp推流拉流(以前支持/后面都移除了)
if (pullType == "rtmp") {
url = "rtmp" + url;
} else if (pullType == "hls") {
url = "http" + url + ".m3u8";
} else if (pullType == "flv") {
url = "http" + url + ".flv";
} else if (pullType == "webrtc") {
url = "webrtc" + url;
}
} else if (pushType == "ABLMediaServer") {
//支持rtsp/rtmp推流拉流(目前还不稳定/兼容性不够好)
if (pullType == "rtsp") {
url = "rtsp" + url;
} else if (pullType == "rtmp") {
url = "rtmp" + url;
} else if (pullType == "hls") {
url = "http" + url + ".m3u8";
} else if (pullType == "flv") {
url = "http" + url + ".flv";
} else if (pullType == "ws-flv") {
url = "ws" + url + ".flv";
}
} else if (pushType == "Monibuca") {
//支持rtsp/rtmp推流拉流(拉流格式众多/各种插件/性能很强劲/具体有待验证)
if (pullType == "rtsp") {
url = "rtsp" + url;
} else if (pullType == "rtmp") {
url = "rtmp" + url;
} else if (pullType == "hls") {
url = QString("http://%1:%2/hls%3/%4.m3u8").arg(ip).arg(port).arg(path).arg(name);
} else if (pullType == "flv") {
url = QString("http://%1:%2/hdl%3/%4.flv").arg(ip).arg(port).arg(path).arg(name);
} else if (pullType == "ws-flv") {
url = QString("ws://%1:%2/jessica%3/%4.flv").arg(ip).arg(port).arg(path).arg(name);
} else if (pullType == "webrtc") {
url = QString("webrtc://%1:%2/webrtc/play%3/%4").arg(ip).arg(port).arg(path).arg(name);
}
} return url;
}

Qt/C++音视频开发49-推流到各种流媒体服务程序的更多相关文章

  1. WebRTC 音视频开发

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

  2. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

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

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

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

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

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

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

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

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

  7. Android音视频开发(1):H264 基本原理

    前言 H264 视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的.随着 x264/openh264 以及 ffmpeg 等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大 ...

  8. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  9. Android IOS WebRTC 音视频开发总结(八十三)-- 使用WebRTC广播网络摄像头视频(上)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  10. Android IOS WebRTC 音视频开发总结(四六)-- 从另一个角度看国内首届WebRTC大会

    文章主要从开发者角度谈国内首届WebRTC大会,支持原创,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,更多详见www.rtc.help. -------------------- ...

随机推荐

  1. element输入天数,获取当前时间加上天数 【时间获取】

    handleInput (val) { // console.log(this.formModel.ITEM_PM) if (!(/[^\d]/g).test(val)) { // console.l ...

  2. 激活windows教程

    新建bat文件 [批处理文件:后缀是 bat ] 输入代码: slmgr/skms kms.03k.org slmgr/ato 然后以管理员运行 :

  3. 37 .vue2数组和对象的区别 ?

    vue2中的数组不能使用索引实现响应式 ,因为vue没有给数组元素添加get和set函数  : 追加对象的属性的时候不是响应式,要使用 $set 追加响应式  :

  4. Python入门:A+B问题

    1. A + B 问题I 前言 本篇作为课程第一篇,主要是对Python基础语法进行扫盲,本节课会学习到下面知识: 输入 本道题目的工作任务很简单,只是计算两个数的和,但是在计算之前,我们首先要明确的 ...

  5. CF1187E 题解

    Title translation 给定一棵 \(n\) 个点的树,初始全是白点. 要做 \(n\) 步操作,每一次选定一个与一个黑点相隔一条边的白点,将它染成黑点,然后获得该白点被染色前所在的白色联 ...

  6. VS2019插件更新慢的解决办法

    VS2019更新巨慢,可以尝试通过以下几个方法解决: 1. 关闭IPV6 关闭IPV6:Win10怎么样禁用IPV6 如何关闭IPV6协议-百度经验 (baidu.com) 2. 选择最快的DNS 百 ...

  7. Windows 非服务器版本永久关闭命令行“快速编辑模式”

    使用管理员权限运行cmd.exe 运行如下命令: reg add HKEY_CURRENT_USER\Console /v QuickEdit /t REG_DWORD /d 00000000 /f

  8. Vue2.x 常用功能和方法

    Vue 生命周期 beforeCreate (组件实例刚被创建,组件属性计算之前,如 data 属性等) created (组件实例创建完成, 属性已绑定,但 DOM 还未生成, $el 属性不存在) ...

  9. Nginx增加网页认证功能

    Nginx增加网页认证功能 增加认证功能模块 ngx_http_auth_basic_module 模块实现让访问者,只有输入正确的用户密码才允许访问web内容.web上的一些内容不想被其他人知道,但 ...

  10. 适合才最美:Shiro安全框架使用心得

    大家好,我是 V 哥.Apache Shiro 是一个强大且灵活的 Java 安全框架,专注于提供认证.授权.会话管理和加密功能.它常用于保护 Java 应用的访问控制,特别是在 Web 应用中.相比 ...