RTMP低延迟推流

人总是需要压力才能进步, 最近有个项目, 需要我在RK3568上, 推流到公网, 最大程度的降低延迟.
废话不多说, 先直接看效果:
在这里插入图片描述
数据经过WiFi发送到Inenter的SRS服务器, 再通过网页拉流的.

因为是打金任务, 所以逼了自己一把, 把RTMP推流好好捋一遍.
先说说任务目标, 首先是MPP编码, 把mpp的github库下载下来, 研究mpi_enc_test这个例程, 基本就能实现, 从摄像头/dev/video0获取yuv数据, 编码为h264, 保存为文件.

最终值得注意是两点:

  1. log看不到, mpp的log都保存到了/var/log/messages中.

在这里插入图片描述

  1. 输入参数, 因为人家的test demo, 包装得非常好, 编码的参数需要用参数输入, 而你必须设置一些编码参数, 我想到一个非常偷懒的做法:

在这里插入图片描述
伪装, 哈哈
这里面几个比较重要的参数,
-w -h分辨率之类,
-n 表示连续获取数据帧, 不显示数量
-t 就是h264比那吗
-g 是关键帧间隔
-rc 是码流控制, 1代表固定码流, 可根据需要修改, 在固定码流模式下, 可以设置码率

下图的bps就是码率, 直接写死, 要提高码率, 可以修改这里
在这里插入图片描述
3. 在整个编码一开始, 会有一个生成SPS/PPS帧的过程, 原本的代码是直接写入到h264裸文件中. 我看了下面雷神的做法, 先缓存了下来, 跟第一个I帧一起发送.

接下来就是RTMP推流国过程了.

整个过程的前提是, 我之前在腾讯, 花5分钟(开通)+30分钟(折腾防火墙发现是梯子的问题), 搞了个SRS的服务器, 这个服务能接收N种推流方式:
在这里插入图片描述
这里面我最熟悉的就是RTMP了.
其实我最迷信的就是直接TCP转发…但是播放端没有研究, 而我之前试过, 先在板子这端用RTSP, 然后用ZLMedia的pusher, 或者叫Muxer, 把RTSP转到RTMP上去:

https://blog.csdn.net/zunly/article/details/138510170?spm=1001.2014.3001.5502

我偶然发现, 通过网页看到的流, 延迟非常小, 说明这个路应该是ok的, 但是经过RTSP, 再转推, 实在太2, 于是乎经过了几天的折腾, 下面是一点发现:

先说说目前的目标, 就是把mpp编码完的h264数据帧, 一帧一帧的通过RTMP推到Internet上的SRS上去.

首先我能想到的, 就是这么普及的应用, 应该是有库的吧, 搜了一圈, 发现有几个选择:
传说的librtmp, 如果直接在github搜索, librtmp, 过滤掉iOS, 安卓平台, 就会看到雷神(致敬RIP)之前的仓库:

https://github.com/leixiaohua1020/simplest_librtmp_example.git

他的做法是使用一个叫librtmp的库, 但是这个库没有源码, 只有编译好的lib文件跟dll文件, 这没法移植啊…

github上, SRS librtmp的仓库, 留了一个留言:

在这里插入图片描述
两个连接都已经失效.

我又研究了ZLMedia的RTMP部分, 发现一时之间很难看懂…

接下来是ffmpeg, ffmpeg最早进入视野是因为我一开始就想研究webRTC的推流, 据说那玩意儿贼快, 于是看到了一个国内的现状, 很多开发者, 开发出一个框架, 像变现, 方法成了, 什么知识星球, 什么CSDN收费下载…唉…当然作为一个自由主义知识分子, 信仰的是Milton Friedman, Ronald H. Coase, 我举双手赞同知识付费…
最后因为没有钱, 我放弃了WHIP就是webRTC推流的方法…默默留下了贫穷的眼泪.

偶然的机会, 我发现了另一个雷神的仓库:
https://github.com/leixiaohua1020/simplest_ffmpeg_streamer

差点跟前面那个搞混了, 这个仓库就是一个既可以推mp4也可以推flv, 也可以推裸流的宝藏代码, 也是雷神在8年前遗珠…
这个方案用的是ffmpeg的库, ffmpeg老早就集成了这些了…ffmpeg牛逼!!!
我先是在Unbantu上面, 把代码在x86/x64环境跑起来(居然真的能跑通, 推流也是能看到画面的).
然后通过WireShark抓包, 看看到底除了了裸流的数据, ffmpeg 还发了些啥:

在wireshark中, 我发现了几个问题, 一个是对应代码的, RTMP的初始化连接过程, 是非常必要的, 这个过程相当于告诉RTMP的服务器, 你要推流的视频的一些信息, 例如宽高, 帧率之类.
在这里插入图片描述
而这些信息, 其实是ffmpeg通过读取你要发送的h264/flv文件来获取的, 就是这个write_head的过程
在这里插入图片描述

实际的每一个数据帧的发送, 根据打印结果发现, 如下图, 如果我推流的是一个h264的文件, 每次发送的packet, 其实就是通过ffmpeg的 av_read_frame方法, 跟NAL的分割字符(00 00 00 01或者00 00 01), 读取的一帧数据

在这里插入图片描述
read之后, 打印pkt, 长度跟数据内容, 用winhex打开比较

在这里插入图片描述
发现, 每个包, 就是一帧
在这里插入图片描述
那么思路就这样串起来了.

首先, 通过编码, 把摄像头数据, 保存为一个h264的文件, 这个文件当中, 最少有1个SPS, PPS, 跟一个关键帧, 作为一个初始化ffmepg AVPacket对象的工具, 同时也供RTMP的连接初始化使用, 接下来, 再使用实时编码出来的h264帧, 不断填充AVPacket对象的data 跟len这两个参数, 再通过ffmpeg的av_interleaved_write_frame 方法, 就可以把数据源源不断的推到RTMP上去了.

代码暂时不开源, 因为是个打金的项目, 如果上面的文章您还有任何疑问, 欢迎发私信讨论, 感谢大家.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/13276.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Altium】AD-检查原理图中元器件未连接的Passive Pin

1、 文档目标 如何让原理图编译时找出元器件上未连接的Passive Pin 2、 问题场景 当引脚属性(Pin type)为passive时,原理图编译的默认规则是不会去检查它们是否有连接的。在实际设计过程中,经常会有导线虚连,漏连的事…

医疗传感器种类不断增多 市场规模逐渐扩大

医疗传感器种类不断增多 市场规模逐渐扩大 医疗传感器是将人体的生理信息转换为电信息的变换装置。医疗传感器具有高灵敏度、高精度、实时监测等优点,可以检测佩戴者的心率、呼吸频率、活动量等,从而更加准确地了解身体情况。   经过多年发展&#…

【极简】docker常用操作

镜像images是静态的 容器container是动态的,是基于镜像的,类似于一个进程。 查看docker images: docker images 或者docker image ls 查看docker container情况:docker ps -a,-a意思是--all 运行一个container: doc…

数字水印 | 奇异值分解 SVD 的 Python 代码实现

🥑原理:数字水印 | 奇异值分解 SVD 的定义、原理及性质 🥑参考:Python 机器学习笔记:奇异值分解(SVD)算法 正文 对于一个图像矩阵,我们总可以将其分解为以下形式: 通过…

使用API有效率地管理Dynadot域名,默认将域名隐形转发至其他界面

关于Dynadot Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮…

【大模型微调】一文掌握7种大模型微调的方法

本篇文章深入分析了大型模型微调的基本理念和多样化技术,细致介绍了LoRA、适配器调整(Adapter Tuning)、前缀调整(Prefix Tuning)等多个微调方法。详细讨论了每一种策略的基本原则、主要优点以及适宜应用场景,使得读者可以依据特定的应用要求和计算资源限…

openGauss一主两备集群异常断电后不能正常启动的解决过程简记

背景 因异常断电后opengauss 5.0.0版本,一主两备集群启动失败。 报错不是主机,由于当时没有截图,查看日志后发现报错是: 定位过程 Day1 1. 尝试用另外两台机器启动每台机器 发现都报错自己不是主机,像极了唐僧被妖…

哪款桌面便签app能帮助我提升工作效率

作为上班族,我们每天都要处理大量的工作事项,从策划方案到处理邮件,每一个环节都需高效且有条不紊。在这样的工作环境下,提升效率显得尤为重要。而选择一款优秀的桌面便签app,无疑是提高工作效率的关键。 桌面便签app…

【数据结构】数据结构大汇总 {数据结构的分类总结:定义和特性、实现方式、操作与复杂度、适用场景、相关算法、应用实例}

一、线性结构 1.1 顺序表 定义和特性:顺序表是一种线性表的存储结构,它采用一段地址连续的存储单元依次存储线性表中的元素。顺序表具有随机访问的特性,即可以通过元素的下标直接访问元素。 实现方式:顺序表可以通过数组来实现&…

基于51单片机的非接触式无线红外测温

基于51单片机的无线红外测温 (程序+原理图+设计报告) 功能介绍 具体功能: 1.采用红外温度传感器测温并用LCD1602显示; 2.按键为启动按键、保存按键、显示数据按键,可以实现对温度数值的控制…

【制作100个unity游戏之26】unity2d横版卷轴动作类游戏6(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言敌人动画配置撞墙判断敌人基本AI逻辑实现 野猪受伤死亡死亡敌人死亡时,还是会对人物产生伤害有限状态机&抽象类多态 定义不同状态的敌人行为防止野猪在悬崖掉下去野猪的追击状态的转换敌人主动查找玩家 追击状态…

基于微信小程序+JAVA Springboot 实现的【智慧乡村旅游服务平台】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称: 基于微信小程序的智慧乡村旅游服务平台的设计与实现 项目技术栈 该项目采用了以下核心技术栈: 后端框架/库: Java SSM框架数据库: MySQL前端技术: 微信开发者工具、uni-app其他技术&#xff1a…

8B10B编码(高速收发器五)

1、8B10B解决的问题 8B10B编码是1983年IBM公司提出的传输编码标准,通常用于高速收发器中,常见的JESD204B、SATA等接口协议,使用查表就可以实现编码和解码。 在这些高速收发器的接收端需要通过CDR技术去恢复时钟与数据的相位关系,在…

Linux day6 yum下载,systemctl,

yum命令 yum [-y] install wget 通过yum下载wget小工具 -y的意思是,如果有询问,自动确认(总是允许)。 yum remove wget 也可以通过这种方式卸载wget

PyQt5 中的 List View

文章目录 1. 基础概念2. 创建 List View2.1 PyQt5 中一个简单的 List View 实例2.2 代码解释2.3 运行结果 3. 数据模型3.1 标准模型3.2 自定义模型 4. 自定义 List View4.1 使用样式表 (QSS)4.2 设置项委托 (Item Delegate) 5.事件处理6. 与数据交互6.1 添加数据6.2 删除数据6.…

echers配置项:数据过多时,折叠数据缩放查看

当数据过多时,如上图所示的时间点,会自动折叠,此时鼠标缩放还不起作用,我们配置如下代码 let option {dataZoom: [{startValue: 05:00}, // 这个值需要跟 第一条 时间数据对应上{type: inside}], }配置后,就可以进行…

echers配置项:折线图,折现的颜色修改

如上图所示:红框内的折现颜色修改,并隐藏默认的点 series: [{data: [1, 230, 224, 218, 135, 147, 760,1500,1200,2500,2000],type: line,lineStyle: {color: #00DBFE // 折现颜色},symbol:none, // 不显示点smooth: true, // 折现角度:圆滑…

5W 3KVAC隔离 宽电压输入 AC/DC 电源模块——TP05AL系列

TP05AL系列产品是一款经济型开板式开关电源,输出功率为5W,具有可靠性高、小体积、性价比高等特点,广泛用于工控和电力仪器、仪表、智能家居等相关行业。

通过 Apple Vision Pro 释放创造力:深入研究空间计算

Apple 最新进军空间计算领域的 Apple Vision Pro,标志着重新定义我们与技术交互方式的重大飞跃。空间计算超越了传统界限,允许用户以无缝集成到物理世界的方式参与 2D 和 3D 内容。 我们可以关注两种类型的体验: 在空间中渲染 2D 内容。这涉及将现有设备窗口投影到空间领域…

通过C++和libcurl下载网易云音乐音频文件的5个简单步骤

概述 在网络编程中,使用C和libcurl库下载文件是一项常见的任务。网易云音乐作为中国领先的在线音乐服务平台之一,以其丰富的音乐资源、优质的音质和智能推荐系统而广受欢迎。由于其平台提供了大量的正版音乐资源,用户在下载音频文件时可能会…