技术研究之RTMP
1.前言
早期的视频直播用的技术都是 声网 的直播平台,总是遇到费用的问题,于是就准备研究下rtmp的技术路线,看看能不能走通。基于NGINX的媒体流服务器: nginx 和 nginx-rtmp-module 功能:
- RTMP、HLS、MPEG-DASH 直播
- RTMP视频点播FLV/MP4,本地文件或HTTP播放
- 支持分布式串流:推流拉流 (可多推多拉)
- 支持H264/AAC
- 支持FFmpeg在线转码
- 在某些事件上运行外部程序(exec),主要用来使用FFmpeg转码推流到其他平台,可推多平台
- HTTP控制模块,用于录制音频/视频和投放客户端
- HTTP回调(发布/播放/记录/更新等)
- 将统计数据存储在方便机器和人类可读的XML/XSL中
- 先进的缓冲技术,将内存分配保持在最低水平,以实现更快的流媒体和低内存占用
- 支持 Linux/FreeBSD/MacOS/Windows 系统
2.nginx配置rtmp
因为我原先安装了nginx,现在只能是重新安装,但是如何增加,这个我倒是没有尝试过。
(1) 下载
下载 nginx-rtmp-module 模块,直接源码下载就好了。
(2) 安装
将下载的模块上传到服务器 /homo/soft 目录并解压
1 | ## 进入源码目录,可能是nginx-1.24.0 |
(3) 配置
在nginx.conf的配置文件中,增加rtmp模块配置
1 | rtmp { |
如果需要hls模块,可以添加hls,这样配置 http 就可以直接在浏览器端用 hls 播放器播放 m3u8 的视频了。
1 | rtmp { |
(4) 推流
打开 OBS Stadio 进行推流。打开 文件 -> 设置 -> 直播,选择自定义,填写服务器地址,rtmp://xxxx:10009/live
推流码也可以随便定义,如果定义了推流码,拉流的时候的地址就变成了:rtmp://xxxx:10009/live/推流码
(5) 播放
我这里用了 easyplay 进行了简单的测试,使用了上面的直播,然后定义了自己的直播地址,发现可以直播了。
【1】.在已经安装Nginx的基础上增加 Nginx-rtmp-module 模块 这个是在已有的nginx的软件上增加了 nginx-module-rtmp 方法
【2】.搭建自己的直播服务器(nginx + RTMP) 1.下载 nginx 和 nginx-rtmp-module;2.配置nginx服务器;3.配置hls。最后还用了
【3】.搭建nginx的RTMP服务器的步骤
【4】.What are the pros and cons of RTMP vs HLS for live streaming?
【5】.配置Nginx以支持RTMP直播及HLS流播放 在RTMP URL中通过添加特定路径或标识(即推流密钥),用以区分不同的推流源。这在Nginx配置文件中不直接定义,而是通过推流软件(如OBS)在推流时指定。推流URL格式通常为:rtmp://your_server_ip/live/STREAM_KEY,其中STREAM_KEY为自定义的推流密钥。
3.鉴权
搭建了rtmp地址之后,就可以直接使用服务器地址进行直播推流和拉流了,如何鉴权还需要额外的操作。我经过资料查找,在rtmp模块的配置中,可以配置一个 on_play 参数,在 on_play处添加Java验证服务的地址,Nginx-rtmp会在发送直播流前,访问这个地址进行验证,若验证成功该地址返回200,失败则返回401等异常状态码。参数key也会被转发给这个地址。
1 | rtmp { |
【1】.基于Nginx-rtmp+Java的直播拉流鉴权方案 用户在web端登陆成功后,Java服务端将用户的id、密码,当前时间等信息合并成一个字符串,使用RSA算法公钥加密该字符串,生成一个密文key。把这个密文key作为前端直播流地址的一个参数,发送给Nginx-rtmp服务器。Nginx-rtmp再将参数转发给Java后台的验证服务,验证通过则可正常播放。Nginx-rtmp的默认url长度值过小(默认256),故url过长时会被截断。而RSA加密后的密文又很长。这个问题需要通过修改Nginx-rtmp的源代码来解决,即修改url参数长度最大值。
【2】.推流的时候能加帐号密码吗? 目前是没有用户名密码这套验证机制的,不过可以采用推流与播放使用不同app_name的方式,并开启鉴权功能
刚刚我测试发现一个问题,等我修复一下
【3】.使用auth_request模块实现nginx端鉴权控制
【4】.NGINX如何实现rtmp推流服务–鉴权篇 推流的限制:on_publish;拉流的限制:on_play;
4.前端播放
【1】.H5视频之video.js播放rtmp直播源和hls直播源
【2】.Video.js播放RTMP流媒体
【3】.VUE–播放视频(RTMP、FLV、HLS、Webrtc)
【4】.请问有办法rtmp的推流转成webrtc吗?是不是利用webrtc技术三端就都可以播放了?
5.配置
常用的直播配置
1 | events { |
启用 hls 支持
1 | server { |
【1】.NGINX-RTMP 直播服务部署 1.推多路配置(多个应用程序或监听不同的端口) server{ } 块内配置多个 application 可以实现,由于都是监听一个端口,同一时间内只有一路有画面。2.重新编码(转码)可以在 application{ } 块内运行 exec 命令(注意不支持windows系统),可以将接收到的 RTMP 流传给视频处理器进行编码转码,如 ffmpeg,3.可以使用 push 语句将 application 接收的流推送到其他流接收平台,当然也可以使用 exec 运行 ffmpeg 将接收到的流推送至其他平台。
【2】.使用 Nginx-RTMP 搭建简单的流媒体服务器 该配置下,推流地址为 rtmp://IP_ OR_DOMAIN/live/,当使用 live 为推流码进行推流时,播放地址为 rtmp://IP_ OR_DOMAIN/live/live。这里还用了 ffmpeg 进行了转码, apt install ffmpeg -y
【3】.Nginx学习之配置RTMP模块搭建推流服务 PC 直播流程非常简单,主要步骤:1.通过RTMP自定义一个推流地址,解决往哪推流的问题;2.采用第三方的推流软件,设置推流音视频源以及编码参数,解决推什么内容的问题;3.观众就可以使用我们提供的 RTMP DEMO 通过设置播放地址即可进行观看,解决内容触达到观众那里的问题。这里还用了 TcPlayer 进行了播放
【4】.Nginx RTMP服务器配置 1.配置stat;2.配置转码,新建专门用于播放流的application vod,将原先的live设置为只接收推流, 再设置使用ffmpeg将源流进行转化,再推到对应的专门播放application vod中。3.记录原始流,nginx-rtmp-module提供了record模块,来保存接收到的流。4.ffmpeg调节横竖屏resize;5.访问allow和deny;6.HLS中生成的m3u8中ts数量。7.rtmp流为什么播放时也会有延迟,主要是客户端缓存导致的。为了避免网络抖动导致的播放卡顿,很多RTMP播放器都会在收到一段时间的RTMP流后才开始播放。这样就导致了播放的延迟。
6.SRS
之所以会有这个想法,将RTMP转为 webrtc,是因为大疆用的是 rtmp 进行的直播,但是最后我看示例代码中,播放的竟然是使用 jswebrtc.min.js 的 webrtc 进行播放的,不晓得到底是为什么,于是就尝试了一下这个技术。经过不断的查询,我发现其实他们用了一种叫 srs 的流媒体技术,而不是我刚开始用的 nginx-rtmp 服务器。SRS(Simple RTMP Server) 是国人写的一款非常优秀的开源流媒体服务器软件。
(1)下载
克隆源码到服务器
(2)安装
1 | cd srs/trunk |
(3)启动
1 | CANDIDATE="192.168.1.10" |
【1】.WebRTC 研究系列 二、打通webrtc与rtmp WebRTC先使用ICE技术连接STUN/TURN,得到自己的连接信息。再绑定音视频设备获取媒体信息,拼装为SDP信令。两个客户端通过任意方式交换信令,建立客户端直接的连接,再使用RTP发送和接收媒体数据。
【2】.尝鲜:如何搭建一个简单的webrtc服务器 基于 WebRTC 的 1v1 视频实时通话架构:1.WebRTC 终端,负责音视频采集、编解码、NAT 穿越、音视频数据传输;2. Signal 服务器,负责信令处理,如加入房间、离开房间、媒体协商消息的传递等;3. STUN/TURN 服务器,负责获取 WebRTC 终端在公网的 IP 地址,以及 NAT 穿越失败后的数据中转。
【3】.SRS中RTC和RTMP流互相转换 TCP在网络抖动时,延迟会变大。一般消息(弹幕)的延迟比较小,这时就会出现消息比画面更快的情况。同步:不同客户端的播放进度不同步,有些延迟大,有些延迟小。比如直播答题,或者直播拍卖,需要同步播放器的场景,就会造成问题。SRS+FFmpeg,SRS将WebRTC流转RTMP,FFmpeg将多路RTMP合流。优势:延迟小,音质好;缺点是命令行难度高。SRS+OBS,方案和SRS+FFmpeg一样,不过用OBS来实现合流。优势:图形化界面更友好,音质好;缺点是延迟大有不同步风险较大。
【4】.SRS学习笔记(2) - rtmp / http-flv / hls 协议配置 及跨域问题
【5】.SRS流媒体服务器与WebRTC推拉流技术深度解析
【6】.开源流媒体服务器 SRS 学习笔记 - 安装、推流、拉流
【7】.SRS4.0:环境搭建(推流、服务器配置、拉流测试) 我们这里先使用srs.conf,支持rtmp推流,支持rtmp、hls、http-flv拉流。测试了使用 obs 进行推流。 1935端口对应的是rtmp服务, 1985对应的是http api服务,8080对应的是http-flv、hls的服务器端口
【8】.本机搭建SRS服务器——–37 在这里需要注意不需要执行make install。
7.docker 启动 srs
使用 docker 启动 srs 流媒体服务,我也是经历了一番波折,开始的操作步骤都是错误的,然后我尝试了下面的几个步骤,终于弄出来了启动和测试。
(1)在阿里云打开端口 1935、1985、8080 还有udp 8000端口,使用下面的命令打开 srs服务器,xx.xx.xx.xx 为服务器外网地址。
1 | docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 \ |
(2)在 obs 中设置直播地址 rtmp://xx.xx.xx.xx:1935/live/livestream,推流码为空,开启直播
(3)打开 http://xx.xx.xx.xx:8080/players/srs_player.html
页面,在 LivePlayer 选项卡中,URL地址栏中中输入 :http://xx.xx.xx.xx:8080/live/livestream.flv
测试直播画面。
(4)使用 jswebrtc 进行测试的时候
1 | let url = 'webrtc://47.97.116.4/live/livestream'; |
(5)经过我的尝试,有下面几个点需要注意
- udp 端口必须开,默认的是 8000 端口,8080 可以不需要
(2) 进入
【1】.SRS视频媒体服务器-docker启动:更换默认端口时的错误 1.启动srs容器:宿主机端口和容器端口映射时,保持端口一致;2.配置srs配置文件:使用宿主机端口启动;
【2】. srs更改端口号导致webrtc播放异常 这里通过nginx,将 rtc 的播放端口改为了 41985
【3】.WebRTC服务搭建(使用SRS) 配置域名和HTTPS,HTTP在Chrome浏览器快捷方式中添加,本地推流:ffmpeg。流播放:RTMP流,FLV流
问题
Response to preflight request doesn’t pass access control check: Redirect is not allowed for a preflight request.
当我用 nginx 代理srs 1985 端口的时候,前端播放的时候,就出现了这个奇怪的问题。或者说,如果使用 ip 地址访问 webrtc 进行播放,没有问题,但是使用域名就无法用,其中 test.tech 指向 xx.xx.xx.xx.xx
1 | webrtc://xx.xx.xx.xx.xx/live/livestream |
【尝试方案】
我尝试了很多的方法,修改了多次 nginx 配置
(1)增加了 always 配置
(2)增加了 option 过滤配置
1 |
|
(3)我以为是nginx配置的问题,后来我还是先把原先的 1985 端口开开了,我直接用了 webrtc://xx.xx.xx.xx:1985 进行连接了,结果还是不行
(4)后来我无意间发现了一个问题,使用 webrtc 推流必须用 https。
(5)修改nginx配置,这样也不起作用,Access to XMLHttpRequest at ‘http://xx:10015/rtc/v1/play/' from origin ‘http://localhost:3100' has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: Redirect is not allowed for a preflight request.
1 | ## 配置webrtc播放地址 |
(6)修改nginx配置,增加了 live 的配置,结果也是不行
1 | http { |
(7)我还尝试了,直接使用 ip + 端口号的形式,也是可以的,10015为nginx的端口,用上面的方法进行了 rtc 的代理,也就是说,端口可以不是 1985,但是一定要是 ip 地址。
1 | webrtc://xx.xx.xx.xx:10015/live/livestream |
(8)问题的原因其实是因为 OPTIONS 总是返回 307,而不是 200,所以预检请求无法通过
(9)后来我放弃了,解决不了域名和ip地址的问题,我只能去解决这个http和https的问题了。后来我发现,解决了https之后,这个域名也就自然而然的解决了,使用https的时候,就可以使用域名了,而使用 http 的时候,就不能用域名。
后来我又想明白了,要是前端部署到含有域名的网站,或者是同域名的情况下,是不是也不会出现这个问题呢?我将https换成了http尝试了一下,确实也可以使用nginx进行代理,最后也能实现直播,也就是说在不同源的情况下,问题就会发生了。
【解决方案】
最后用了 HSTS 307重定向跨域问题 这里的解决方案:在浏览器中输入 chrome://net-internals/#hsts,将访问的域名从HSTS中删除
【1】.SRS跨域播放问题 这里直接改了源码了
【2】.关于跨域 Response to preflight request doesn‘t pass access control check 我注意到后面有一句Redirect is not allowed for a preflight request:重定向不允许preflight request请求。我寻思着我这也没重定向啊。
【3】.WebRTC基础面试题 在浏览器下使用WebRTC必须要使用HTTPS服务。这是因为WebRTC需要使用STUN/TURN服务器来进行网络地址转换和数据传输,而浏览器为了安全性限制了使用WebRTC的请求必须来自安全的上下文,即使用HTTPS协议的页面。如果没有使用HTTPS,浏览器会阻止WebRTC的功能。
【4】.SRS+Docker部署教程 可能会出现docker中http回调127.0.0.1或者localhost时无法访问鉴权服务器, 将鉴权服务器改成0.0.0.0运行
【5】.SRS服务器RTMP2WebRTC外网拉流配置 这里加了一个 live 配置,但是最后还是用的ip地址作为 webrtc 的地址,外网拉流地址:webrtc://10.172.59.42:33333/live/20240102
【6】.SRS解决WebRTC黑屏问题,包括内网、公网环境黑屏
【7】.HSTS 307重定向跨域问题 这个方案可以了
【8】.nginx options请求失败
【9】.nginx 配置跨域 status code 200,但是报错CORS error,实际还是跨域了
【10】.nginx 跨域踩坑及解决–OPTIONS请求处理
8.后台启动
1 | ## 后台启动 |
9.srs配置https访问
因为我的网站是 https 的,所以我使用 jswebrtc 进行播放的时候,总是出现 https 无法调用 http 的问题。
【尝试方案】
(8)我尝试把全部的 http 全部转成 https,结果无效,因为我发现了原来是 jswebrtc.min.js 中,将http写死了。
1 | <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> |
我的完整的 nginx https 配置如下,其实就是多加了一个 rtc 的访问,转移到了 1985 端口上。
1 | server { |
【1】.SRS4.0.85流媒体搭建及HTTPS代理 location ~ /.+/.*.(flv|m3u8|ts|aac|mp3)$ { proxy_pass http://127.0.0.1:8080$request_uri;}
10.在线测试
安装并配置好了 SRS ,可以进行在线测试,在测试网站中测试 flv。我在测试的时候,发现 flv 的延迟要十几秒的时间。
1 | https://xxx:10015/live/test.flv |
11.直播卡顿
在我使用 SRS 作为服务器的时候,直播画面在小窗口的时候还是可以接受的,但是在大窗口就变得模糊了。
【尝试方案】
(1)尝试扩大缓存,结果无效
1 | # vi /etc/sysctl.conf |
(2)重新配置了 webrtc 进行了转发,结果无效
【解决方案】
修改了配置文件,增加了低延时播放。经过测试,我发现 flv 播放,还是会有 1-3 秒到延迟时间。
1 | listen 1935; |
【1】.ffmpeg rtmp 不清晰_rtmp与srs初识
【2】.Oryx - 直播转码降低带宽并节约成本
【4】.简单易懂srs webrtc 部署优化方案 对srs的优化,因为webrtc是使用的udp缓存,因此linux的udp缓存参数得增大,不然会因为本地udp缓存不够大,连本地上传的缓存都不够,导致掉帧。
【5】.如何提高SRS服务器的RTMP视频传输效率 服务器配置优化,网络带宽优化,SRS服务器配置优化,使用硬件加速技术,优化视频编码参数,使用CDN进行加速。
【6】.低延时直播应用 这里是官方的一系列的文章描述
【7】.在线SRS播放器
【8】.在线体验及Demo源码
【9】.直播视频流需要多大的上传带宽?
【10】.新版本浏览器播放rtmp流媒体替代方案 1.更换流媒体服务器播放协议,如:HTTP-FLV、HLS等协议。2.安装支持flash插件的低版本浏览器。3.nginx-http-flv-module。4.webrtc。
【11】.排查SRS问题记录一(RTMP推流,RTC播放卡住)
【12】.[SRS流媒体]SRS rtmp http-flv流低延时设置、测试
【13】.SRS RTMP/HLS低延时模式 延时影响因素:1.GOP:SRS可以关闭GOP的cache来避免这个影响。2.服务器性能太低:服务器来不及发送数据。3.播放端:譬如flash客户端的NetStream.bufferTime设置为10秒,那么延迟至少10秒以上。4.推流端:GOP、Profile、Tune等编码参数。RTMP延时特点:RTMP延时特点、有累积延迟
【14】.SRS低延时配置分析 1.tcp_nodelay:tcp关闭 Nagle算法,不再缓存发送。2.min_latency:开启最小延迟模式。3.queue_length: 设置队列大小。4.gop_cache: 关闭两个IDR帧间的数据缓存。5.mw_latency: merge wirte混合写的延迟。6.mr off:merge read关闭混合度
【15】.基于srs的低延迟直播平台搭建 1.全平台直播,小荷才露尖尖角。只需要上图的Encoders(FFmpeg/OBS)推送RTMP到SRS;一台SRS Origin(不需要Cluster),转封装成HTTP-FLV流、转封装成HLS;Players根据平台的播放器可以选HTTP-FLV或HLS流播放。2.WebRTC通话业务,一对一通话,多人通话,会议室等。WebRTC是SRS4引入的关键和核心的能力,从1到3秒延迟,到100到300毫秒延迟,绝对不是数字的变化,而是本质的变化。3.监控和广电上云,各行业风起云涌。除了使用FFmpeg主动拉取流到SRS,还可以广电行业SRT协议推流,或监控行业GB28181协议推流,SRS转换成互联网的协议观看。4.直播低延迟和互动,聚变近在咫尺。RTMP转WebRTC播放降低播放延迟,还能做直播连麦,或者使用WebRTC推流,未来还会支持WebTransport直播等等。5.大规模业务,带你装逼带你飞。如果业务快速上涨,可以通过Edge Cluster支持海量Players,或者Origin Cluster支持海量Encoders,当然可以直接平滑迁移到视频云。未来还会支持RTC的级联和集群。
【17】.SRS导致WebRTC丢帧如何排查
12.开启m3u8
(1) 配置 hls 低延时
1 | listen 1935; |
(2) OBS直播参数调优
GOP = 1;Profile = baseline; Tune = zerolatency (主要是GOP编码参数),例如OBS的编码设置如下: 设置 -> 输出 -> 高级,CPU使用预设:fast,配置Profile:baseline,微调Tune:zerolatency。这样配置之后,m3u8 的延迟可以达到 3-5 秒
(3) 配置nginx
1 | location /live/ { |
【1】.《直播从零开始》SRS RTMP/HLS低延时模式 这里有参数调优,我就是用的这个方法