• 图解系列 图解直播推拉流流程


    常用开源流媒体服务器为SRS和MTX

    流程

    涉及到的组件

    • 主播(推流端)
    • 观众(播放器)
    • 业务服务【持有一些私有Key,如rtmpKey等】
    • 流媒体服务器【SRS/MTX】
    • CDN【持有公钥】

    推流流程

    1.主播登录系统

    2.主播点击发起直播,业务系统返回一个可用的推流地址,其携带认证token(token直接使用JWT也行)。

    • token = now time + random + ttl + signature md5(now time + random + ttl + rtmpKey) 【自己验自己只用一个key即可】

    • 示例:

      • signature = md5(now time + random + ttl + rtmpKey) = 88195f8943e5c944066725df2b1706f8
      • rtmp://192.168.1.10/live?time=1402307089&expire=3600&signature =88195f8943e5c944066725df2b1706f8

      加签是为了放篡改,把防止篡改的信息都参与加签

    3.主播用上一步返回的可用推流地址进行推流。

    4.根据地址会连接到SRS/MTX。

    后面都以SRS举例,在SRS上提前配置http回调,回调到我们的业务系统

    • on_connect http://127.0.0.1:8085/api/v1/on_connect;

    当客户端连接到指定的vhost和app时会触发这个callback。

    5.我们在业务系统拿到token去校验, 按同样的算法验证,如果md5变了就返回错误,srs就会拒绝连接。如果返回0就会接受连接。

    6.流媒体服务器就可以根据我们的配置在内存中生成flv或者在文件系统生成ts文件

    扩展

    1.ts文件移动,移动到OSS或其他位置

    on_hls:当SRS获取HLS的ts文件时触发 POST请求

    当切片生成时,回调这个url,使用POST回调。用来和自己的系统集成,譬如实现切片移动等。

    {
    "action": "on_hls",
    "client_id": 1985,
    "ip": "192.168.1.10", 
    "vhost": "video.test.com", 
    "app": "live",
    "stream": "livestream", 
    "param":"?token=xxx&salt=yyy",
    "duration": 9.36, // in seconds
    "cwd": "/usr/local/srs",
    "file": "./objs/nginx/html/live/livestream/2015-04-23/01/476584165.ts",
    "url": "live/livestream/2015-04-23/01/476584165.ts",
    "m3u8": "./objs/nginx/html/live/livestream/live.m3u8",
    "m3u8_url": "live/livestream/live.m3u8",
    "seq_no": 100, "server_id": "vid-werty"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.触发CDN上ts文件的缓存预热

    on_hls_notify:当SRS获取HLS的ts文件时触发,用于将文件推送到CDN网络,通过从CDN网络获取ts文件。该请求是一个GET请求,请求地址为格式:

    当切片生成时,回调这个url,使用GET回调。用来和系统集成,可以使用[ts_url]变量,实现预分发(即下载一次ts片,预热)。

    • https://127.0.0.1:8085/api/v1/hls/[app]/[stream]/[ts_url]?[param]

    [server_id]服务器ID
    [app]应用名称
    [stream]流名称
    [ts_url]url
    [param]参数

    拉流流程

    1.观众根据需要可登录也可不登录到系统。

    2.业务系统返回一个可用的播放地址,这个播放地址是CDN的临时的(10分钟过期)

    • 播放地址可以是Http-flv地址,也可以是hls的m3u8地址。
    • 每次请求都会返回一个不一样的CDN临时URL。
      • 如果是涉密的流,管理好这个临时URL即可,例如只有登录的人才返回这个URL。
    • 例如:http://cdn.com/stream.m3u8?timestamp=1456213&ttl=600&random&signature=md5hash(timestamp,ttl,random+CDNKey)
      • 跟推流时候的临时签名一样。
      • 防篡改 + 临时有效性10分钟。
    • 注意这个地址也是业务系统加签但是验签是CDN回源的时候业务系统自己也会验
      • 这里因为是2个系统加签,验签流程,所以可以采用私钥加签,公钥验签逻辑,业务系统用私钥加签CDN用共钥验签。(可以用多套密钥对,参数传递密钥对ID)
      • 也可以用对称算法加签验签。
      • 无论什么算法,都要去CDN上传你的key。

    3.当用户拿着加了CDN的临时url访问时,CDN会鉴权,会验证是否过期是否篡改

    • CDN节点对鉴权URL中的鉴权信息(包括鉴权字符串、时间戳等)进行验证,判断请求的合法性。

    • 鉴权失败,拒绝访问请求。

    • 鉴权通过,正常响应合法请求。

    4.如果CDN有cache则直接返回,否则CDN请求源站,即回源操作。

    5.回源服务器鉴权保护,我们可以将源站设置为仅允许 CDN访问,而拒绝客户端的直接回源。

    • 同样鉴权URL中的鉴权信息(包括鉴权字符串、时间戳等)进行验证,判断请求的合法性,是否过期是否篡改

    • 在 CDN Origin 设置时,添加自定义 Header 字段及值,源站对请求中的字段检查,若不含有该 Header 字段及值,则返回错误码。

    • 验证请求IP白名单,只运行CDN的IP放行请求。

    • 源站为OSS存储桶

      在OSS存储桶策略中设置,仅允许CDN从存储桶中获取内容。

    文件加密

    背景信息

    HLS(HTTP Live Streaming的缩写)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。HLS协议基于HTTP协议,客户端按照顺序使用HTTP协议下载存储在服务器上的文件。HLS协议规定,视频的封装格式是TS(Transport Stream),除了TS视频文件本身,还定义了用来控制播放的M3U8文件(文本文件)。HLS协议的工作原理是把整个视频流分割成一个个小的TS格式视频文件来传输,在开始一个流媒体会话时,客户端会先下载一个包含TS文件URL地址的M3U8文件(相当于一个播放列表),给客户端用于下载TS文件。

    HLS基本字段

    • #EXTM3U:M3U8文件头,必须放在第一行。
    • EXT-X-MEDIA-SEQUENCE :第一个TS分片的序列号,一般情况下是0,但是在直播场景下,这个序列号标识直播段的起始位置; #EXT-X-MEDIA-SEQUENCE:0
    • #EXT-X-TARGETDURATION:每个分片TS的最大的时长; #EXT-X-TARGETDURATION:10 ,表示每个分片的最大时长是10秒。
    • #EXT-X-ALLOW-CACHE:是否允许cache,#EXT-X-ALLOW-CACHE:YES#EXT-X-ALLOW-CACHE:NO,默认情况下是YES。
    • #EXT-X-ENDLIST:M3U8文件结束符。
    • #EXTINF:extra info,分片TS的信息,如时长,带宽等;一般情况下是 #EXTINF:,[] </code>后面可以跟其他的信息,逗号之前是当前分片的TS时长。分片时长要小于 <code>#EXT-X-TARGETDURATION</code> 定义的值。</li><li><code>#EXT-X-VERSION</code>:M3U8版本号。</li><li><code>#EXT-X-DISCONTINUITY</code>:该标签表明其前一个切片与下一个切片之间存在中断。</li><li><code>#EXT-X-PLAYLIST-TYPE </code>:表明流媒体类型。</li><li><code>#EXT-X-KEY</code>:是否加密解析。例如:<code>#EXT-X-KEY:METHOD=AES-128,URI="https://example.com/video.key?token=xxx"</code> 加密算法是AES-128,密钥通过请求 <code>https://example.com/video.key?token=xxx</code> 来获取,密钥请求回来以后存储在本地,并用于解密后续下载的TS视频文件。</li></ul> <p><strong>示例</strong></p> <pre data-index="1" class="set-code-hide prettyprint"><code class="prism language-ini has-numbering" onclick="mdcp.signin(event)" style="position: unset;">#EXT-X-VERSION:3 #EXT-X-ALLOW-CACHE:YES #EXT-X-MEDIA-SEQUENCE:13 // 在这里 全部 #EXT-X-KEY:METHOD=AES-128,URI="https://example.com/keyfile.key",IV=0x1234567890ABCDEF1234567890ABCDEF #EXT-X-TARGETDURATION:15 #EXTINF:10.147, no desc livestream-13.ts #EXTINF:10.007, no desc livestream-14.ts // 或者在这里 局部 #EXT-X-KEY:METHOD=AES-128,URI="livestream-15.key",IV=0x175D2375FEBAE7ED8E92A7E6A64F5113 #EXTINF:10.216, no desc livestream-15.ts #EXTINF:10.170, no desc livestream-16.ts #EXTINF:11.378, no desc livestream-17.ts #EXTINF:9.668, no desc livestream-18.ts <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{"spm":"1001.2101.3001.7365"}"><img class="look-more-preCode contentImg-no-view" src="https://1000bd.com/contentImg/2022/06/27/191644837.png" alt="" title=""></span></div><ul class="pre-numbering" style="opacity: 0.129874;"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li></ul></pre> <h4><a name="t5"></a><a id="_174"></a>流程</h4> <p><strong>切片加密</strong></p> <p>1.流媒体服务器在推流端连接上时,从<strong>业务服务端获取key和IV</strong>。</p> <p>2.流媒体服务器在生成ts文件时,<strong>使用Key和IV加密TS文件</strong>。</p> <p><strong>切片解密</strong></p> <p>1.索引m3u8文件含有获取解密匙URI,大致如下:</p> <blockquote> <p>#EXT-X-KEY:METHOD=AES-128,URI=“https://example.com/keyfile.key”</p> </blockquote> <p>2.URI部分就是去获取解密匙的http请求,进行边解密边播放。<br> 3.KeyURI可以加token或者Cookie进行权限控制.</p> </div> </div> </li> <li class="list-group-item ul-li"> <b>相关阅读:</b><br> <nobr> <a href="/Article/Index/1024350">YOLOv5实战之输电线路绝缘子缺陷检测识别</a> <br /> <a href="/Article/Index/778329">程序员面试金典 - 面试题 17.18. 最短超串</a> <br /> <a href="/Article/Index/802404">firewall-cmd修改ssh接口转发</a> <br /> <a href="/Article/Index/1382924">【Qt控件之QButtonGroup】概述及使用</a> <br /> <a href="/Article/Index/1031911">第十九章 Nacos统一配置中心详解</a> <br /> <a href="/Article/Index/1344525">adb详细教程(四)-使用adb启动应用、关闭应用、清空应用数据、获取设备已安装应用列表</a> <br /> <a href="/Article/Index/878143">猿创征文|基于物联网的门禁与考勤系统_阿里云_2022</a> <br /> <a href="/Article/Index/1556391">Go语言第二篇-基本数据类型与转义字符</a> <br /> <a href="/Article/Index/1653025">C#WPF数字大屏项目实战08--生产量/良品统计</a> <br /> <a href="/Article/Index/982096">PHP:对象继承</a> <br /> </nobr> </li> <li class="list-group-item from-a mb-2"> 原文地址:https://blog.csdn.net/abu935009066/article/details/132760720 </li> </ul> </div> <div class="col-lg-4 col-sm-12"> <ul class="list-group" style="word-break:break-all;"> <li class="list-group-item ul-li-bg" aria-current="true"> 最新文章 </li> <li class="list-group-item ul-li"> <nobr> <a href="/Article/Index/2039499">花了一晚上AI Coding, 在不熟悉的领域,使用AI帮同事解决了跳槽的小问题</a> <br /> <a href="/Article/Index/2039500">一首《谦比希铜矿之歌》厂歌火爆全网,背后是AI的数学本质</a> <br /> <a href="/Article/Index/2039501">园友特惠| 1Panel 企业版 & AI 一体机限量放售,最高直降 5100!</a> <br /> <a href="/Article/Index/2039502">C# 内存安全性的重大演进:重新定义 unsafe 关键字</a> <br /> <a href="/Article/Index/2039503">为了随时随地控制 AI Agent,我做了一个 Web Terminal</a> <br /> <a href="/Article/Index/2039504">AAVE V3 v3.7 版本更新:Isolation Mode 被移除,清算流程精度修复</a> <br /> <a href="/Article/Index/2039505">Agent 架构设计与能力构建</a> <br /> <a href="/Article/Index/2039506">从 Responses API 到 Chat Completions:一个模型网关的设计复盘</a> <br /> <a href="/Article/Index/2039507">上位机程序发布打包成安装包---Inno Setup</a> <br /> <a href="/Article/Index/2039508">【EF Core】继承策略——TPT</a> <br /> </nobr> </li> </ul> <ul class="list-group pt-2" style="word-break:break-all;"> <li class="list-group-item ul-li-bg" aria-current="true"> 热门文章 </li> <li class="list-group-item ul-li"> <nobr> <a href="/Article/Index/888177">十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!</a> <br /> <a href="/Article/Index/797680">奉劝各位学弟学妹们,该打造你的技术影响力了!</a> <br /> <a href="/Article/Index/888183">五年了,我在 CSDN 的两个一百万。</a> <br /> <a href="/Article/Index/888179">Java俄罗斯方块,老程序员花了一个周末,连接中学年代!</a> <br /> <a href="/Article/Index/797730">面试官都震惊,你这网络基础可以啊!</a> <br /> <a href="/Article/Index/797725">你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法</a> <br /> <a href="/Article/Index/797702">心情不好的时候,用 Python 画棵樱花树送给自己吧</a> <br /> <a href="/Article/Index/797709">通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!</a> <br /> <a href="/Article/Index/797716">13 万字 C 语言从入门到精通保姆级教程2021 年版</a> <br /> <a href="/Article/Index/888192">10行代码集2000张美女图,Python爬虫120例,再上征途</a> <br /> </nobr> </li> </ul> </div> </div> </div> <!-- 主体 --> <!--body结束--> <!--这里是footer模板--> <!--footer--> <nav class="navbar navbar-inverse navbar-fixed-bottom"> <div class="container"> <div class="row"> <div class="col-md-12 text-center"> <div style="padding:0px 5px;"> <a href="/tools">小工具</a> <a href="https://games.1000bd.com">小游戏</a> </div> <div class="text-muted center foot-height"> Copyright © 2022 侵权请联系<a href="mailto:2656653265@qq.com">2656653265@qq.com</a>    <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2022015340号-1</a> </div> <div style=" padding:5px 0;"> <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502049817" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;"> <img src="" style="float:left;" /><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">京公网安备 11010502049817号</p></a> </div> </div> </div> </div> </nav> <!--footer--> <!--footer模板结束--> <script src="/js/plugins/jquery/jquery.js"></script> <script src="/js/bootstrap.min.js"></script> <!--这里是scripts模板--> <!--scripts模板结束--> </body> </html>