尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HLS与M3U8深度解析:视频切片、AES加密与多码流自适应实战

HLS与M3U8深度解析:视频切片、AES加密与多码流自适应实战 我最早被 M3U8 这个文件虐到是在一次排查网页视频播放问题的时候播放器明明在播开发者工具里却全是几百 KB 一个的 .ts 请求还有一个 index.m3u8 文本文件在不停刷新。当时的第一反应是“这不就是个歌单吗”直到我把 HLS、M3U8、视频切片、AES 加密、多码流自适应这一整条链路彻底捋顺才意识到这套技术栈几乎撑起了当下视频行业的半壁江山。这篇文章不打算给你背协议文档而是从实际项目视角把 HLS-M3U8 这套体系拆开讲透切片怎么切、加密怎么加、多码流怎么做以及那些你大概率也会踩的坑。不管你是刚接触流媒体协议的新手还是已经在业务里被 M3U8 折腾过的前端、后端、音视频开发下面这些内容都可以直接拿来当参考。我尽量用能落地的命令、配置和踩坑经验来说话。1. 为什么现在的直播点播都绕不开 HLS 和 M3U81.1 从一次抓包说起M3U8 到底是什么我第一次认真看 M3U8 内容时发现它长这样#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, https://cdn.example.com/segment_0000.ts #EXTINF:10.0, https://cdn.example.com/segment_0001.ts #EXTINF:8.5, https://cdn.example.com/segment_0002.ts #EXT-X-ENDLIST这个文件本身是个纯文本记录的是视频片段的下载地址、时长、排列顺序以及加密信息、码流信息等。HLS 全称 HTTP Live Streaming是苹果在 2009 年推出的协议本意是给 iOS 设备做流媒体传输后来因为实现简单、基于 HTTP、天然穿透性强成了整个行业的事实标准。说它是歌单不完全错因为 M3U8 确实是从音频播放列表格式 M3U 扩展来的。但从功能上看它做的事情远比歌单多它要告诉播放器“先放哪些数据、每个数据多长、遇到网络波动换哪个档位、要不要解密”。所以更准确的说法是M3U8 是播放器的施工图。1.2 HLS 凭什么取代了 Flash 时代的 RTMP早年做视频直播大部分人用的是 RTMP Flash。RTMP 基于 TCP延迟可以压到 1 到 3 秒配合 Flash 播放器在 PC 端确实能跑。但移动端不认 FlashiOS 连 RTMP 都很难直接用CDN 厂商对 RTMP 的缓存和分发支持也不够好。HLS 的优势在于它把流媒体拆成了普通文件一个 M3U8 索引文件加一堆 TS 切片。HTTP 协议能做的优化它全部可以继承CDN 边缘缓存、Range 请求、预加载、断点续传都不用专门为流媒体做定制。用户网络差播放器就切换低码率的子播放列表网络好就切回高码率整个过程用户无感。至于直播和点播的差异HLS 同样兼顾。点播场景里M3U8 最后一个切片后有#EXT-X-ENDLIST表示播到这儿就完了直播场景里没有这个标签播放器会每隔几秒重新拉取一次 M3U8获取新增的切片序号实现了“拉流式直播”。1.3 一个适合初学者的理解模型如果你刚接触这套东西可以把 HLS 想成“施工队砌墙”M3U8 是施工图画清楚了墙有多少块砖、每块砖在哪个仓库、取砖顺序是什么TS 切片是砖每一块都自带时间戳和编码信息可以独立运输、独立缓存播放器是施工队先读施工图再按图取砖一块一块砌起来如果取砖过程发现某块砖坏了施工队可以跳过或重试不影响整面墙。我见过不少人一上来就直接啃 RFC 8216 协议文档结果被各种标签绕晕。其实先把“索引 分片”这个模型建立起来后面再看标签就清晰很多。HLS 的核心哲学和网页缓存很像把视频切成小块让每块都可以被 HTTP 缓存、被 CDN 分发、被播放器单独重试这就保证了在弱网环境下还有机会流畅播放。2. 视频切片M3U8 的骨架是怎么搭起来的2.1 为什么偏偏是 TS 而不是 MP4HLS 最常见的切片容器是 MPEG-TS也就是运输流。很多人问过我MP4 不也挺好吗为什么非要用 TSTS 的设计目标就是对抗“不可靠信道”。它把数据切成 188 字节一包每一包都有固定的包结构包头里带有 PID 和连续性计数器。哪怕中途丢了几包播放器也能很快重新对齐从下一个完整的数据包继续解码不会整个文件报废。这是它作为流媒体容器的天然优势。MP4 不是不能流式播放但它把关键元数据集中在 moov 原子可以理解成文件头部的索引区里。如果 moov 没下载完整整个文件就没法定位而且一旦中间数据损坏拖动就会出现问题。虽然现代标准里 fMP4碎片化 MP4也叫 CMAF通过把 moov 切分成多个 moof 解决了 HLS 点播场景的很多问题但存量视频里 TS 仍然占绝对主力。顺便说一句很多教程里直接ffmpeg -i input.mp4 -c copy output.m3u8就完事了其实 ffmpeg 默认就是用 TS 做切片它内部已经帮你处理好了格式转换。大部分业务场景下你不需要关心 TS 的底层包结构但理解它“分块抗损”的特性能帮你判断切片环节里哪些问题值得排查。2.2 用 ffmpeg 把一个 MP4 切成 TS 流手头有一个 MP4 文件想生成一份最基础的点播 M3U8命令非常简短ffmpeg -i input.mp4 -c copy -hls_time 10 -hls_list_size 0 -hls_segment_filename output_%03d.ts -f hls output.m3u8逐个参数说-i input.mp4输入文件。-c copy直接复制视频流和音频流不重新编码。速度最快但切片的关键帧位置不一定精准。-hls_time 10每个切片的目标时长是 10 秒。注意是“目标”不是“精确”时长ffmpeg 会尽量在接近这个长度的地方找关键帧切。-hls_list_size 0生成的 M3U8 里保留所有切片。如果不加这个参数默认只保留最近 5 个切片适合直播场景不适合点播。-hls_segment_filename output_%03d.ts切片文件的命名模板这里会生成 output_000.ts、output_001.ts……-f hls输出格式是 HLS。执行完之后目录里会出现一个 M3U8 加一堆 TS 切片。把这个目录放到任意 HTTP 服务器上播放器直接访问 M3U8 的 URL 就能播放。如果切片后出现“起播时间不对”或“首屏黑一下”的问题往往是因为原文件的关键帧位置没对齐。关键帧是视频编码里的 I 帧HLS 的每一个切片必须从关键帧开始否则播放器解码不出完整的画面。为了保证切点精准重新编码时可以用强制关键帧ffmpeg -i input.mp4 -c:v libx264 -force_key_frames expr:gte(t,n_forced*10) -sc_threshold 0 -c:a aac -hls_time 10 -hls_list_size 0 -hls_segment_filename output_%03d.ts -f hls output.m3u8-sc_threshold 0是关闭场景切换自动插入关键帧保证关键帧完全由你控制。这样切出来的每个切片时长都会非常接近 10 秒。2.3 切片时长怎么定6 秒、10 秒还是自定义切片时长直接影响起播速度和直播延迟我这几年实测下来没有一个万能值得看场景场景推荐切片时长原因点播长视频10 秒兼顾拖动精度和文件数量切片过多会增加 M3U8 体积和播放器解析压力点播短视频4 - 6 秒首屏更快适合用户随时划走的场景直播4 - 6 秒切片越短延迟越低但过度切短会增加服务器压力和播放器请求次数低延迟直播2 秒或 LL-HLS需要额外配置分片内 chunk普通 10 秒切片做不了低延迟点播场景里切片时长还和拖动进度的精度有关。如果你想拖动到视频的 37 秒位置播放器就用 37 除以每个切片的时长得到序号然后去请求那个切片。切片越短拖动定位越精确但代价是文件和请求数量变多。10 秒一个切片在这个权衡里比较折中。直播场景里切片时长直接决定了端到端延迟的下限。传统 HLS 直播播放器通常会缓冲 3 个切片才开始播如果你切片 10 秒延迟就是 30 秒起。这也是为什么现在的低延迟直播要么用 LL-HLS要么直接用 WebRTC 做。2.4 切片后常见的“不对劲”现象切片不是跑完命令就结束的事实际项目里我遇到过的坑基本集中在三块第一播放列表文件越来越大。直播切片不写-hls_list_size 0的话M3U8 里只会保留最近几个切片这在直播里是对的但有人把点播切片也这样配导致 M3U8 不完整用户拖到一半进度条就失效。点播必须加-hls_list_size 0。第二切片时长忽长忽短。原因通常是原文件的 GOP两组关键帧之间的距离不规整ffmpeg 找不到合适的关键帧就在一个很怪的位置强行切了。解决办法就是上面说的强制关键帧。第三直播画面卡在某一帧不动。这通常是切片文件没有按顺序更新或者 M3U8 里的#EXT-X-MEDIA-SEQUENCE没有递增。播放器是拿着这个序号来判断“我该播到哪了”的一旦序号跳变播放器会重新缓冲。切片生成脚本里要注意文件名排序不要用字符串排序要用数字序号排序否则第 10 片会排到第 2 片前面。3. AES-128 加密M3U8 里那行 EXT-X-KEY 到底干了什么3.1 加密流程切片怎么做到“加了密还能播”很多视频站下载下来一堆 TS 文件后直接播放画面是花的就是因为切片被加密了。HLS 的加密等级是“每个切片单独加密”而且用的是对称加密算法 AES-128-CBC。也就是说视频内容在切片阶段就完成了加密播放器拿到切片后要先解密再送入解码器。加密信息写在 M3U8 的EXT-X-KEY标签里。典型的加密后 M3U8 长这样#EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:10 #EXT-X-KEY:METHODAES-128,URIhttps://api.example.com/keys/key1.key,IV0x00000000000000000000000000000001 #EXTINF:10.0, segment_0000.ts #EXTINF:10.0, segment_0001.ts #EXT-X-ENDLIST播放器的处理流程是拉取 M3U8读到EXT-X-KEY标签看到METHODAES-128知道后面所有切片都需要解密用 HTTP 请求拿URI指向的密钥文件用密钥16 字节和 IV16 字节如果没写 IV 就默认用切片序号逐个解密 TS 切片解密完成后再交给解码器播放。注意加密粒度是“每个切片单独加密”每个切片解密互不依赖。这意味着播放器可以并行下载和解密后续切片这也是 HLS 在弱网下还能保持流畅的关键之一。3.2 密钥放哪里为什么说“盐”必须放后端网上经常有人说“AES 加密盐要放后端”很多人不理解。在 HLS 这个上下文里“盐”可以理解成密钥的生成因子或 IV 的随机因子。真正合理的设计是密钥文件本身不由前端生成也不写死在播放器页面里而是由后端接口动态下发。原因很直接如果密钥内嵌在前端 JS 里任何人打开控制台就能看到所有用户共用一个密钥等于没加密如果密钥放在 CDN 静态目录且没有鉴权别人拿到 M3U8 后直接访问密钥 URL 就能解密正确做法是密钥接口走鉴权播放器必须携带用户票据或访问令牌才能拿到密钥。在具体项目里我一般这么设计密钥文件真实路径存数据库但对外暴露的是一个带签名的临时 URLURL 里带过期时间比如 5 分钟有效过期后必须重新向业务接口申请每个视频可以配一个固定密钥也可以定期轮换密钥IV 不写死在 M3U8 里而是由后端生成随机 IV 并写入 EXT-X-KEY这样即使同样的明文切片两次加密产生的密文也完全不同。还有一种更谨慎的做法是“业务层再套一层加密”也就是 TS 文件在 HLS 的 AES 之外再在文件头拼一段随机盐播放器端用搬运代码处理。不过这种方案会让播放器兼容性变差如果不是版权保护要求特别高不建议轻易上。3.3 ffmpeg 给 TS 流加 AES-128 的操作给现有视频加 HLS 加密ffmpeg 一条命令就能搞定但要提前准备两个东西密钥文件和密钥信息文件。生成 16 字节随机密钥openssl rand 16 video.key创建一个 key.info 文件三行内容分别是密钥 URI、密钥文件路径、IVhttps://api.example.com/keys/video.key video.key 0x00000000000000000000000000000001然后执行ffmpeg -i input.mp4 -c copy -hls_key_info_file key.info -hls_time 10 -hls_list_size 0 -hls_segment_filename output_%03d.ts -f hls output.m3u8生成的 M3U8 里会自动带上EXT-X-KEY标签切片文件也是加密后的 TS。实际测试时直接把切片下载到本地再用播放器播放画面是花的这就说明加密生效了。这里有个细节key.info 里的密钥文件路径是相对执行命令的目录来解析的。如果 ffmpeg 和 video.key 不在同一个目录路径写错的话会在切片阶段直接报错。密钥 URI 则会被原样写入 M3U8必须是一个播放器能真实访问到的地址否则线上播放会失败但切片文件本身是正常的。3.4 AES 模式问答为什么每次加密结果都不一样热搜里有一条“aes 什么模式每次加密结果都不一样”我猜测提问者是发现同样一个切片每次加密后内容不同以为加密出错了。其实这正是 AES-CBC 模式的正常表现。AES 有 ECB、CBC、CTR 等模式。ECB 模式下同样的明文输入永远得到同样的密文所以它没有隐私性可言相同内容的加密块会重复容易被分析出规律。CBC 模式引入了 IV初始向量每两个加密分组之间还有链式依赖所以只要 IV 随机即使明文完全相同密文也会不同。可以这样理解把加密比作给白布染色ECB 是每个局部都用同一种染料染出同样的颜色CBC 是先在前一块布上倒点随机颜料然后沿着布料一步步把颜色传递下去。随机颜料就是 IV改变它最后整块布的颜色都会变。HLS 里用的正是 AES-128-CBC。如果 M3U8 的 EXT-X-KEY 不写 IV播放器会默认用切片的序列号作为 IV这也是合法的但容易被猜。更稳妥的做法是像上面 key.info 里那样显式指定一个随机 IV。只要密钥和 IV 都一致之前的切片就能正常解密。如果你在自建后端实现里发现解密失败优先自查这几点密钥是否刚好 16 字节M3U8 中 IV 是否与加密时一致是否多个语言系统同时参与比如 ffmpeg 加密、Java 解密两边 AES 填充模式是否一致HLS 的 AES-128 默认不填充必须跟规范对齐。4. 多码流自适应一个 M3U8 怎么适配千差万别的网络4.1 自适应是谁在做什么很多人说 HLS 是自适应码流的其实自适应发生在两个层面服务端准备好多个码率的视频版本播放器端根据实时网络状况选择下载哪一个版本。一个视频源文件转码后可能产生 1080p/720p/480p 三份切片每份切片对应一组 M3U8。播放器启动后先读取总索引Master M3U8里面会列出每个版本的带宽、分辨率等信息。播放器一边下载一边测速网络好就请求高码率切片网络变差就立刻切到低码率切片整个过程用户是无感的。这个机制解决了一个很实际的问题用户的地点和网络是千差万别的。同一个视频有人用千兆宽带有人在地下室 4G 网络里刷抖音。如果服务端只提供一个码率的视频要么让宽带用户看低清要么让弱网用户一直卡。多码流自适应的本质是把“视频质量决策”交给播放器实时完成。4.2 Master Playlist 是播放器的菜单栏多码流的目录结构通常长这样index.m3u8 1080p/ index.m3u8 segment_0000.ts ... 720p/ index.m3u8 segment_0000.ts ... 480p/ index.m3u8 segment_0000.ts ...最外层的 index.m3u8 就是 Master Playlist它不包含切片信息只描述各个子流。一个典型的 Master M3U8 是这样的#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH2500000,RESOLUTION1920x1080,CODECSavc1.640028,mp4a.40.2 1080p/index.m3u8 #EXT-X-STREAM-INF:BANDWIDTH1200000,RESOLUTION1280x720,CODECSavc1.4d401f,mp4a.40.2 720p/index.m3u8 #EXT-X-STREAM-INF:BANDWIDTH500000,RESOLUTION854x480,CODECSavc1.4d401e,mp4a.40.2 480p/index.m3u8播放器看到多个EXT-X-STREAM-INF就知道这份视频有多个档位可选。BANDWIDTH 的值是播放器做切换决策时最重要的参考指标之一。在 Master M3U8 里还可以用EXT-X-MEDIA做多音轨、多字幕用AUDIO分组把不同语言的音轨和视频组合起来这在点播场景中很常见。第一次做 HLS 的人容易把 Master M3U8 和子 M3U8 搞混我的经验就是Master 里只有“菜单”子 M3U8 里才是“菜”。4.3 多档位转码怎么生成一份“自适应套餐”生成多码流的方式有两种思路。第一种是普通做法把源文件分别转出 1080p、720p、480p 三个版本然后分别做切片。优点是每个档位可以独立管理、独立发布缺点是磁盘占用大、转码时间长。第二种是 ffmpeg 单进程多输出。一条命令同时输出多个码率的切片ffmpeg -i input.mp4 \ -vf scale1920:1080 -c:v libx264 -b:v 2500k -c:a aac -b:a 128k -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename 1080p/segment_%03d.ts 1080p/index.m3u8 \ -vf scale1280:720 -c:v libx264 -b:v 1200k -c:a aac -b:a 96k -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename 720p/segment_%03d.ts 720p/index.m3u8 \ -vf scale854:480 -c:v libx264 -b:v 500k -c:a aac -b:a 96k -f hls -hls_time 10 -hls_list_size 0 -hls_segment_filename 480p/segment_%03d.ts 480p/index.m3u8这种方法的优点是三个档位共用一次源文件读取转码效率高但要注意 CPU 压力很大建议在专门的转码服务器上跑不要和线上播放服务混在一起。转码完成后Master M3U8 一般由脚本生成或者在 CDN 控制台上配置。只要三个子索引能被公网访问把 Master M3U8 的地址给播放器多码流自适应就开始工作了。4.4 ABR 切换策略播放器怎么保证不卡播放器端负责做自适应决策的模块通常叫 ABRAdaptive Bitrate。不同播放器的 ABR 策略差异很大hls.js 是默认按带宽估算切换video.js 的 VHS 也是类似思路。我在实际项目里用 hls.js 比较多它的默认策略是启动时先看startLevel配置如果没有配置会从 max 或者 mid 起步播放过程中用下载速度和缓冲时间综合判断如果测速远高于当前码率就升档如果缓冲持续变小就降档并且有lowLatencyMode这类参数控制延迟。常用的调优参数大概这几个const hls new Hls({ maxBufferLength: 30, // 最大缓冲时长秒 maxMaxBufferLength: 60, startLevel: -1, // -1 表示自动选择也可以手动指定档位 abrEwmaDefaultEstimate: 1000000, abrBandWidthFactor: 0.8, abrBandWidthUpFactor: 0.7 });调参的原则是不要一刀切。如果业务场景是短视频用户可以接受首屏稍慢但要求画质高就把startLevel设为最高档如果业务是直播首屏速度比画质重要就让它默认从低档开始网络好再自动升上去。如果你发现播放器在某个档位之间反复横跳画面一下糊一下清晰一般不是播放器问题而是你没有限制变档阈值。可以在播放器端设置向上切换需要当前码率的 1.2 到 1.5 倍带宽再做减少切换次数。5. 从播放到转码实际项目里那些绕不开的坑与命令5.1 m3u8 转 MP4命令和失败场景把远程的 M3U8 转成 MP4是我被问得最多的问题之一。命令本身很简单ffmpeg -i https://example.com/path/index.m3u8 -c copy output.mp4但实际执行时经常遇到问题。最常见的情形是 M3U8 里的切片用了相对路径比如segment_0000.ts而 ffmpeg 会以 M3U8 的 URL 作为基准去解析这通常没问题。真正让人头疼的是下面几种失败现象原因处理方式403 拒绝访问服务端做了防盗链或签名校验用-headers带上 Referer、User-Agent 和鉴权头重试404 找不到切片M3U8 里的切片路径是错的或切片已清理检查切片路径点播列表被清理后就无法整段转存Invalid key length密钥长度不是 16 字节检查密钥文件确认是否被文本编辑器污染解密失败/花屏IV 或密钥不匹配核对 M3U8 的 EXT-X-KEY 与实际密钥中途卡住不退出某个切片下载超时加-timeout 30或-rw_timeout 3000000补充一个实测细节如果 M3U8 是加密的ffmpeg 会自动读取 EXT-X-KEY 里的 URI 去下载密钥并解密不用你手动干预。前提是密钥接口允许 ffmpeg 访问。如果密钥接口校验了 UA 或 Refererffmpeg 下载密钥同样会 403所以带 headers 时要同时考虑切片请求和密钥请求。这里也提醒一句下载和解析别人平台的加密资源可能涉及版权问题本文讨论的范围仅限于你自己拥有或已获授权的资源。5.2 Vue 里播放 M3U8hls.js 和 video.js 怎么选浏览器原生并不能直接播放 HLSSafari 是唯一的例外因为它自己就是 HLS 协议的发起方。其他浏览器要播放 M3U8都得借助 JavaScript 实现的播放器hls.js 是其中的事实标准。在 Vue 项目里集成 hls.js 很简单安装依赖后npm install hls.js组件里按生命周期初始化import Hls from hls.js; const video document.getElementById(video); if (Hls.isSupported()) { const hls new Hls({ maxBufferLength: 30, enableWorker: true }); hls.loadSource(https://example.com/index.m3u8); hls.attachMedia(video); hls.on(Hls.Events.MANIFEST_PARSED, () { video.play(); }); } else if (video.canPlayType(application/vnd.apple.mpegurl)) { video.src https://example.com/index.m3u8; }video.js 也提供类似的 HLS 支持它内部默认集成了 VHS适合不熟悉 hls.js API 但希望封装完整 UI 的场景。我的建议是项目偏底层、需要精细控制 ABR 和缓冲策略用 hls.js项目需要现成控件、皮肤、多格式兼容用 video.js如果既有 HLS 又有 FLV、DASH 需求可以考虑在播放器层做一层封装而不是堆多个播放器。5.3 加密视频播放的排查链路加密 M3U8 播放失败我在生产环境里排查过好多回总结出一个固定套路从打开播放器到画面出来浏览器网络面板里应该依次出现三类请求M3U8 请求返回 200 且内容包含 EXT-X-KEY密钥请求返回 200 且内容是 16 字节二进制数据TS 切片请求返回 200且响应体不能被直接解析为视频帧。如果哪一步断了就对症下药M3U8 404索引文件本身没发布对检查 CDN 回源M3U8 200 但密钥 403密钥接口鉴权失败多半是 cookie 或 token 没带上密钥 200 但播放器报“invalid key”或“decrypt error”密钥长度、IV 或加密模式不匹配切片请求 403切片防盗链生效真实业务里通常是 CDN 的 Referer 白名单拦住了而 M3U8 恰好没拦。一个常见的迷惑场景是把加密后的 TS 切片单独下载下来用本地播放器打开播放器显示时长剧增或完全黑屏。这不代表切片坏了只是本地播放器不知道密钥这点可以通过查看切片文件的大小来判断——加密切片的字节数和原始切片基本一致只是内容变成密文了。5.4 关于“120 分钟后才能下载”之类的业务限制有一种很常见的现象从某些视频站或工具里拿到的 M3U8 链接隔一段时间就失效或者系统提示“一个 HLS 下载只能在前次下载 120 分钟后进行”。这种限制本质上不是 HLS 协议的限制而是服务端为了让资源不被批量抓取而做的签名与频率控制。具体来说视频服务器通常会生成带签名和过期时间的 M3U8 URL签名参数里包含 IP、设备指纹、过期时间戳播放器首次打开页面时从业务接口获取这个签名 URL签名过期后切片请求全部返回 403播放器会尝试重新请求业务接口换新签名对同 IP 或同账号的下载频率做限制两次大规模拉流之间强制间隔一段时间。自己做视频站时如果担心资源被刷盗优先建议做两层防护CDN 层的 Referer 防盗链最简单但能绕过只做第一层过滤M3U8 下发接口的签名与鉴权签名里带时间戳和业务参数CDN 校验签名后再放行切片请求。这类设计不需要改动切片内容所有判断都发生在请求层也不影响播放器兼容性是性价比很高的防盗链方案。需要注意的是签名校验会产生额外的边缘计算或回源请求开销如果视频站访问量很大要用 CDN 的边缘函数或自定义鉴权服务来承载不要让业务源站扛全部校验压力。切片、加密、多码流这套技术组合从协议规范到生产落地的距离其实比想象中大得多。拿 AES 加密来说规范只写了怎么加、怎么解、标签怎么放但密钥怎么存、IV 怎么传、如何轮换都是要在业务层自己做决策的。我第一次给直播流加完加密和自适应后第二天线上反馈弱网播放成功率明显提升当时才真正体会到“索引 分片 密钥 码率阶梯”这套组合的威力。后面几套方案基本都是围绕这套链路做的演进核心思路没变过。如果你正在自建视频服务建议先把 TS 切片和 Master M3U8 跑通再逐步加上加密和多档位每加一层都留好开关这样线上出了任何问题都能快速定位是在哪一环出的故障。
返回列表