ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hyperframes方案:用分层超帧破解8K全景视频带宽与延迟难题

Hyperframes方案:用分层超帧破解8K全景视频带宽与延迟难题 做全景视频流媒体有段时间的人应该都撞上过同一个墙8K 360度视频怎么算码率都不够用。全帧传带宽扛不住只传视口转头就是一片糊。Hyperframes这个方案当初是一个做云VR的朋友推荐给我的它解决的问题恰好就是这个既要全又要快的死结。这篇文章我从方案诞生的动机讲起把它的分层参考结构、HEVC语法层的实现思路、实测效果和工程落地要点整个过一遍给想评估或直接上手的朋友一个参考。1. 全景视频的带宽死局hyperframes究竟解决了什么1.1 视口传输为什么被卡在既要又要上先算一笔账。一路8K 60fps 10bit 4:2:0的全景视频原始数据率轻松突破几十Gbps压缩成HEVC之后全质量的全景流也基本要25~50Mbps才能看。这对移动网络、家庭宽带上行乃至云VR的并发成本来说都是个不小的负担。更扎心的是这么大码率里有一大半是浪费的。人在VR头显里单次能看到的视野大概只有100度左右360度的画面你一次只能看到其中一小块。于是视口相关传输成了共识用户看到哪儿就把哪儿的画面高清晰度地给到他。思路所有人都认可可一落地就卡住了。传统做法是把全景画面切成若干tile只传用户当前视口覆盖的那些tile。听起来直接但视频编码里的参考帧机制让这事变得麻烦——编码器在压缩当前帧时要参考前一帧甚至前几帧的内容。如果用户的视口一直在动客户端就需要各种不同的参考帧数据服务器不可能把所有历史视口的全部tile都留着存储和调度成本很快失控。1.2 MCTS的尴尬能切块但代价不小后来业内引入了一项关键技术运动约束图块集MCTSMotion-Constrained Tile Sets。它是HEVC标准的一个特性核心作用是让编码器在编码某个tile时运动补偿搜索范围被限制在当前tile内部不能跑到别的tile里去取参考像素。这样一来每个tile的编解码就互相独立了。客户端只下载自己需要的tile也只需要对应位置的历史参考帧拼接出来的画面照样能解码。听起来问题已经解决了。但在实际测试编码效率时代价就显现出来了。MCTS本质上是在牺牲预测自由度换独立性运动估计设计的搜索窗口被锁死很多跨区域的相似内容没法互相参考。实测下来MCTS带来的额外码率开销大概在5%到15%运动剧烈的场景会更明显。更麻烦的是为了保证用户随时能切到任意视口服务器里的每个tile都得定期刷新成关键帧I帧I帧的体积比P帧大好几倍多个tile的刷新周期叠在一起缓冲和带宽压力一点儿没小。1.3 hyperframes把问题从空间拼接改成时间预测Hyperframes方案的高明之处在于它没有继续在tile的空间独立性上死磕而是换了个思路把用户可能需要的所有视角版本提前装进同一个超帧里。你可以把这帧理解成一个包含多份全景切片的容器一份覆盖全景的低质量画面一份覆盖用户当前视口附近的中等质量区域还有一份覆盖视口正中心的高质量区域。三份画面放进同一帧整体编码帧内仍然用MCTS切成独立的tile。这样做的好处在于帧和帧之间还是正常的预测参考关系。用户在任意时刻转头客户端都能在当前帧里找到对应位置的tile不需要等新的I帧也不需要重新拉历史参考。空间上的随便哪块都能看和时间上的稳定预测两个优点它同时拿走了。带宽和延迟的账一下子就好算了。2. 超帧的分层参考结构一张帧如何装下不同质量的世界版本2.1 三层区域设计逻辑Hyperframes的帧结构设计直观理解就是分层。我参照常见的参考实现把超帧内部拆成三个层级基础层B层覆盖整个360度全景分辨率相对较低码率占比也不高负责兜底。无论用户转到哪儿起码能看清画面内容不糊到没法看。增强层1E1层覆盖用户当前视口周围更大的区域质量中等负责转头有余量。用户一转新的视角能立即落到E1的范围内不会是空的。增强层2E2层覆盖用户正在看的那一小块质量最高负责看得爽。这一层的码率最大分辨率最高细节保留最好。三个层级不是三路独立的流而是打包在同一帧里一起编码、一起传输。你可以这样理解空间上它们是在同一个时刻对同一个场景拍了三个清晰度版本各自裁剪出不同大小的区域塞进一个画布里。画布里没被覆盖到的位置用基础层内容填充。帧与帧之间做预测时编码器会尽量让当前帧的E2区域参考上一帧的E2区域E1参考E1B层参考B层。由于MCTS约束预测不会跨tile乱跑每一层的独立性都保住了。2.2 预测参考与IRAP节奏实现上有个绕不开的问题什么节奏插入IRAP帧即IDR/CRA这类可随机访问的关键帧。传统tile流方案里由于客户端可能从任意位置开始拉流服务器不得不隔几帧就给全部tile来一个全I帧防止用户从新位置切入时找不到参考。Hyperframes有分层结构就不用这么死板了。我的建议是基础层B按固定周期刷新比如每32帧一个IRAP增强层E1和E2跟着视口走完全不需要自己做I帧直接参考B层的IRAP点重建就可以了。用户转头时只要E1和E2的位置切换发生在IRAP点附近客户端就能从新位置无缝续上中间不需要额外的关键帧传输。这种参考节奏把I帧的开销压低了不少对比传统方案的有效码率占用优势在长会话场景里尤其明显。2.3 与视口联动转头那一瞬间发生了什么用户转头瞬间的体验最能体现hyperframes方案的含金量。传统方案里你转头播放器要先上报新的朝向服务器重新切tile列表再拉新tile的参考帧对齐时间戳中间如果恰好没到I帧可能还要等一下刷新延迟几百毫秒是常有的事。Hyperframes方案里客户端手头已经有当前超帧的全部数据或者至少缓存了B层上一帧的E1/E2转头时只需要从同一帧里提取新视口对应的tile重新拼接上屏。这一步是纯粹的本地内存操作延迟压到了几十毫秒级别。头动和画面之间的贴合感主观体验是完全不同的层次。2.4 码率预算分配问题实操中码率分配是大家最纠结的地方。根据我测试不同序列的经验建议的分配比例大致是层级码率占比参考说明B层15% ~ 25%保证最低可看不宜过高否则浪费E1层30% ~ 40%覆盖转头余量权重略高减少E2切换频率E2层40% ~ 50%核心体验优先保障E2的比例往往被低估很多人习惯把码率给B层铺满觉得全景画面清晰了才安心。但用户真正盯着的只有视口里那一小块B层的清晰度对体验贡献有限。如果你把码率从B层匀给E2用户主观清晰度提升非常明显且整体码率不变。3. 把hyperframes落到编码器上语法、配置与参考软件3.1 tile网格划分与MCTS语法要用HEVC实现hyperframes先得在编码配置里把tile和MCTS打开。我拿HM参考软件举例关键的配置片段长这样# Tile configuration TileColumns : 4 TileRows : 2 UniformSpacing : 1 # MCTS-related TilesFixedStructure : 1 MVConstraint : 1TileColumns和TileRows决定tile网格划分hyperframes方案通常建议至少4列2行这样基础层、增强层可以灵活组合不同tile块。UniforSpacing设为1可以让网格均匀分布方便客户端根据视口中心计算落在网格里的tile索引。MVConstraint是MCTS的关键开关打开后编码器在运动估计时会强制约束运动矢量不能跨tile边界。如果你选的是非均匀网格还需要在PPS里显式指定每个tile的列宽行高。这个自由度在工程上有用因为视口周边的tile可以切得更细保证E2区域的边界更贴合实际视野。3.2 编码器配合运动估计搜哪里MCTS的编码器实现核心是改运动估计逻辑。HM里对应修改在MotionEstimation.cpp需要在搜索时判断当前像素块是否跨tile边界跨了就过滤掉对应的候选运动矢量。有一个容易忽略的细节参考帧里同一tile位置的内容才允许作为预测来源。也就是说编码当前帧E2区域的tile时参考帧里它只能去参考上一帧同样坐标的那个tile。实现时需要给参考帧列表打标记或者在tile级记录参考索引不然解码端一校验就会报错。我在早期测试时踩过这个坑现象是画面能解出来但部分区域出现块效应定位了很久才发现是参考帧管理只做了帧级管理没做tile级管理。3.3 360Lib与参考软件实验目前想直接做hyperframes实验最接近的路径是基于HM加上360Lib扩展工具集。360Lib支持全景图从ERP到CMP等各种投影格式的转换也内置了针对全景图优化的编码工具。实验配置建议按这个顺序来先用360Lib做ERP/CMP的投影转换转出测试序列然后按3.1节的方式开启tile和MCTS再把超帧的封装逻辑写成一个预处理/后处理的脚本把B、E1、E2三个区域的内容按预设坐标拼进同一画布解码后再剪出来还原成三个区域。整个链路跑通你就能拿到基础的实测数据了。3.4 一个容易踩的坑tile独立性校验解码端/验证端经常忽略的是tile独立性校验。你可以用工具检查编码后的码流确认每个tile的运动矢量都没有跨越tile边界。如果用了自研编码器或者修改过的HM这一步尤其重要。校验不通过的表现往往是某个tile解出来有几行花屏或者色偏因为解码端在没有参考数据的情况下拿到了一个依赖其他tile的预测块。我的建议是在工程上专门加一个自动化校验脚本跑完编码后逐tile解码比较解码结果的哈希值与编码器内部的中间值是否一致。这个脚本平时不觉得有用一旦你改了任何跟参考帧管理相关的代码它能帮你省下一天调试时间。4. 带宽对比与体感提升实测中到底省了什么4.1 我们当时做的一组对照数据当初评估hyperframes方案时我们用同一段全景测试序列在码率基本对齐的情况下做了三组对照。结果大致是方案总码率视口内主观清晰度转头后清晰度恢复延迟全全景高清流整个8K全景高码率45Mbps好无一直是好的传统tile流切块仅传视口18Mbps好约500ms视口越偏越久hyperframes方案22Mbps好约80~120ms传统tile流在码率上确实占优但转头延迟对VR来说几乎是致命的画面跟不上头动晕眩感立刻上来。Hyperframes用一定码率余量换来了几乎无感的视口切换明显更划算。4.2 省带宽只是表面真正的收益在延迟很多人聊hyperframes都盯着带宽但我个人觉得它最大的价值在延迟曲线的改善。由于客户端手里始终有一个当前帧的完整超帧所有视口切换和解码组合都在本地完成不依赖网络往返这在云VR、无线VR这类延迟敏感的场景里是一个结构性优势。你可以把视频编码从按用户需求动态组装换成按区域静态可访问后者在分布式部署、边缘缓存、内容预分发上都要好操作得多。从用户体感上讲转头画面从糊到清晰的经历被砍掉了整套体验更接近整块屏幕实时刷新视觉疲劳感低一个档次。4.3 什么情况下这套优势会减弱没有方案是万能药。实测中发现当画面运动剧烈、场景切换频繁时hyperframes的增强层E2覆盖范围可能跟不上视口移动。用户快速转头新视口瞬间落到E2外面只能由E1甚至B层兜底主观清晰度下降还是会发生。区别在于传统方案此时会陷入等关键帧、重新拉流的僵局hyperframes则是平滑降级等视口稳定后增强层再跟上。运动场景下优势减弱的部分可以靠提高视口预测精度和加大E1层面积来弥补。E1的面积加大意味着码率上升这是个取舍问题至少在目前的技术条件下我还做不到既让E2精准覆盖又压低码率每一步都得跟应用场景match着调。5. 工程化落地从参考实验到真实流媒体链路5.1 打包与传输DASH/CMAF下怎么玩参考实验跑通只是第一步真要做到可交付打包和传输层还得打通。目前比较成熟的做法是用DASH加SRDSpatial Relationship Description空间关系描述来播发tile。具体来说每个tile编码成独立轨道在MPD清单里通过SRD字段标注它对应全景画面的具体坐标和空间范围。播放器从MPD里解析出SRD结合用户当前朝向动态选择要下载哪些tile轨道。对于hyperframes方案因为基础层和增强层都在同一帧里打包时建议把每个tile拆成独立的DASH segment再按视口需求做组合效果比较好。CMAFCommon Media Application Format这块主要是考虑多端兼容。如果目标平台都支持CMAF可以直接用CMAF chunked模式配合低延迟DASH做HTTP chunked传输端到端延迟能进一步压缩。5.2 播放器解码与合成不是所有播放器都能玩播放器端的现状是我认为整个链条里最容易被低估的一环。很多开源播放器对HEVC的tile支持并不完整它们默认把整个帧当作一个整体解码遇到tile属性就忽略要么全帧软解要么直接黑屏。这里要提醒一下软解全帧是可以的但会丢掉tile独立解码的并行优势。VR头显的解码芯片一般都支持tile并行你得确认播放器真的把tile解码任务分发给了硬件解码器的多路并行通道而不是在一个线程里全帧解完。测试时可以观察头动时的断流率如果转头瞬间卡顿明显大概率是播放器的tile调度没做好。5.3 服务端转码与编码延迟预算实时全景直播场景下服务端编码延迟预算依然紧。基础层和增强层同时编码如果你按顺序把B层全编完再编E1、E2整帧延迟会叠加用户端体感明显变差。建议参考WPPWavefront Parallel Processing和slice并行来压编码延迟。具体做法是让B层的编码在CPU的不同核上并行执行E1和E2层紧随其后尽可能让输入全景帧→输出打包后码流的总延迟控制在100ms以内。分层调度的优先级也值得自定义B层优先输出保证解码端先有画面上屏E1次之E2最后。即便E2稍微慢一点用户看到的也是清晰度逐步提升而不是黑屏等待。5.4 ROI/视口预测模型的配合视口预测准确度直接决定增强层放哪儿。我现在用的是过去N秒的头动轨迹陀螺仪积分的轻量预测方案效果足够稳定建议还没上模型的团队从这里起步。预测模型的评估指标我建议直接用覆盖率预测出的E2区域和用户下一时刻实际视角的重合比例。覆盖率90%以上才值得扩大E2面积否则你只是在烧码率。等覆盖率的收益到瓶颈再去试更复杂的深度预测模型性价比更清晰。6. 与现网方案的关系OMAF、低延迟全帧流、空间分片6.1 OMAF标准卡的正是这个位置ISO的OMAFOmnidirectional Media Format标准里视口相关流媒体基本是基于MCTS实现的。Hyperframes可以理解成一种配合OMAF的编码层策略——OMAF解决了文件格式、传输协议、播放器接口的问题hyperframes则解决同一时刻同一用户的多个清晰度版本应该怎么组织进一个帧里的问题。两个标准放在一起用是自然的OMAF负责把hyperframes超帧里的tile封装成合规的轨道SRD负责空间定位播放器再按视口组合。如果你的目标是做商业产品而非纯技术demo直接往OMAF v1方向靠不用在协议层重复造轮子。6.2 全高清低延迟流另一个性价比之王有段时间我也经常纠结是不是直接全全景低码率流插值就够用了。很多商用VR播放器确实是这么做的全景整体清晰度不高但胜在简单、兼容性好任何硬解HEVC的设备都能跑。对此我的看法是这属于低成本方案里的最优解但体验上限就摆在那儿。对轻度用户或者带宽预算极其敏感的场景全全景低清流仍然值得考虑而一旦要求看得清文字、能看清脸全低清的插值方案马上就露馅。Hyperframes适合做体验分级里的高体验档跟低清档并行不冲突。6.3 全景直播中的多路协同最后说一个比较前端的思路在演唱会、体育直播这类多机位全景场景中可以尝试让多个视点共享同一个基础层每个视点只需要额外的增强层数据。由于B层占超帧码率的15%~25%多视点复用B层能省下一大笔码率。这个我之前在测试环境里验证过可行性但工程化的坑还不少比如不同视点之间的时间轴对齐、B层投影基准统一等这里就不展开细节了。如果你正好在做全景直播产品这个方向值得关注。说了这么多如果你也准备动手试hyperframes我的建议是别一上来就啃全链路。先从HMMCTS把tile独立性跑通确认运动矢量约束没问题再叠加视口切换逻辑。每一步都单独验证最后再做端到端联调这样即便出问题排查的面也小得多。这个方案的工程收益只有你亲手把链路完整跑过一遍才能真正有体感。
返回列表