网站首页 > 技术教程 正文
作者 | 阿里文娱前端技术专家 归影
责编 | 夕颜
出品 | CSDN(ID:CSDNnews)
这不是一篇基于MSE开发Web播放器的入门文章,而是围绕Web播放器开发遇到的常见问题与解决方案,毕竟入门文章常有而趟坑干货不常有。如果您有Web播放开发经验和音视频技术基础,读起来会更有共鸣。
Web播放器开发基础知识
先介绍Web播放器开发的一些基础知识。有人要问了,Web播放器开发难道不是一个video标签就够了么?非也!
1、浏览器Video支持的格式非常有限
在W3C的标准里面Video只支持MP4格式 准确的说是ISOBMFF(Fragment MP4)。当然chrome支持WEBM,safari支持HLS(MPEG-TS)这都是自家的私有实现,做不得数。
2、浏览器Video无法逐个加载视频切片
现在主流的流媒体点播/直播技术,都会把视频切片。而video标签src只能挂载整个MP4资源。没法逐个的加载视频分段。
所以我们的主角出场—— MediaSource Extenstion,简称MSE,是一套能不断的把音视频二进制数据塞给video标签播放的API。
图1:MSE简明结构
MSE内部可以创建一系列的sourcebuffer,一般是一个音频buffer,一个视频buffer。把MSE做成blob url之后绑定给video的src。然后就可以通过appendBuffer往video里追加音视频数据了。有了MSE,播放器器的整体结构是什么样的呢,见下图。
图2:Web播放器简明结构
首先在浏览器层面,主要使用video标签、MSE、XHR 和UI。那么播放器主要由Manager驱动加载视频的playlist(比如HLS里的m3u8,dash里的MPD,FLV虽然不是playlist概念,但是是原理上差别不大,都是为了拿到视频的一个个的片段的地址),并通过数据服务加载这一个个的分片。然后通过transmuxer也就是所谓的转封装器,把分片的封装格式比如TS拆开(demux) 把连原始的音视频数据解出来,再重新打包成fmp4(remux),最后通过MSE API喂给video标签里,让video去播放。
因此播放器所做的事情最主要有两点:
1) 转封装。即将video不支持的封装格式转码成video所支持的封装格式;
2) 如何驱动整个播放进行。即决定何时下载下一个分片,何时需要解码插入到video的buffer里。
时间戳对齐
转封装除了的封装格式的解复用(demux)和再复用(remux)之外最重要的环节就是分片的时间戳对齐策略,以及音视频同步。
图3(传说中的“开局一张图 原理全靠猜”)
简单讲一下上图:红色代表音频的时间轴。蓝色/青色是视频的时间轴。PTS(Presentation Time Stamp) 指的是这一帧需要渲染的时间。 DTS(Decoding Time Stamp) 指的是这一帧需要解码的时间。
1、首片首帧的对齐策略
正常来说音频PTS和DTS是一样的,而视频如果有B帧的话DTS往往要比PTS早一些(因为要预留一定的时间解码)。因此视频的首帧会有一个洞(gap/shift随便你怎么叫),如果不经处理插到video里,那么video里的buffer也会呈现出一小段的洞,一般是0.08s(比如10s的分片 插进去可能出现0.08~10.08的情况)。现在主流的做法是削掉这个洞。就是把DTS跟PTS强行拉平,一般来说chrome 不会出现太大的问题。但是safari不行,如果不预留一定的DTS/PTS偏移,safari前两帧的播放会明显卡顿。
2、后续对齐策略后续分片的对齐,会通过DTS/PTS两个尾部指针来做。如果发现后续分片时间轴有间隔就往前推从而填上间隔。如果发现重叠,就把重叠帧后移。这样虽然会导致后续分片的前几帧重叠。但在播放的过程中几乎没有影响。
音视频同步
首先,什么情况下会导致音画不同步?
1、视频源流压根没对齐。没救了,看下一点。
2、还是因为有洞。很多时候视频切出来的每个分片之间都不一定是严丝合缝的,分片间的音视频时间戳可能有洞。而且对于TS由于音频每一帧的duration(≈23ms) 跟视频每一帧的duration(40ms@25fps) 无法吻合(整除) 所以加剧了这种参差不齐的情况。那么,重点来了!chrome有个特殊的机制,如果发现音频之间有洞之后,为了保证音频的平顺,会自动把后续音频往前推抹平这个洞。如果每个分片都有洞,悲剧了,这种往前推的操作就会积累越来越多导致音视频不同步。
小tips:
打开chrome的媒体调试页面 chrome://media-internals 可以看到媒体播放相关的所有debug信息和error信息非常有用。其中就会有一条关于音频处理的提示:
当然这条显示的具体原因是自动切掉重叠overlap导致的。其实gap/overlap本质是一样的。怎么办?当然是播放器自己主动把洞填上。具体做法是插帧。目前主要是插静音帧,或者复制前一帧。静音帧会带来毛刺音,复制帧会导致拖音。我们目前的优化方案是判断附近的音频数据量,数据量大时说明此处声音丰富(其实不算靠谱,姑且这么处理,因为没有更好的判断方式),如果插静音帧会毛刺很明显,所以此时用复制帧,反之插静音帧。
那些年我们趟过的坑
1、 不同版本表现差异 容忍度不同
1) Chrome 35分水岭。chrome35之前要求关键帧之后的第一帧dts不允许跟关键帧dts相同,否则抛错。
2) 低延迟的模式。把转封装出来的FMP4中的视频轨duration(tkhd box) 设置成0xffffffff 时会让chrome认为这是直播流,会开启低延迟模式,所谓低延迟模式就是会极大的减少帧缓存,基本上视频帧立马解码立马播放减少每个分片的起播延迟。但是呢在CPU负载过高的情况下(解不过来)会造成视频频繁卡顿(网络无关的)。
2、 不同浏览器表现有差异
1) timeupdate事件。W3C的标准是不能超过250ms触发一次。windows下360等浏览器会达到500ms左右。
2) safari对每一帧duration平顺度更敏感。safari需要对每一视频帧的duration标准化处理,例如TS下要处理成3600。
3) 对洞的容忍度不同。chrome遇到buffer中有0.08的间隔以内会自动跳过去。像IE edge等浏览器不行会卡住,所以播放器一定要有跳洞逻辑。比如判断当前卡在洞的边界,要主动跳过去(seek)。
3、内存限制
通过MSE push给video的视频数据会在内部维护一个buffer,这个尺寸是有限制的。
1) chrome系列约100M
2) IE系列约30M
超过的话就会导致抛出 QuotaExceededError 。所以需要处理好buffer的尺寸以及及时清除不用的buffer。比如已经播放过的,正常浏览器会自己清除,但是不那么的及时。
优化
简单说一下卡顿相关的优化。
多级Buffer控制
ABR 自适应码率算法
基于WebRTC的P2P
1、多级buffer
为什么要有多级的buffer?因为video本身的解码buffer有大小限制,而且buffer过长会导致长时间解码,会导致CPU一直占用高。所以我们搞了两级buffer一级就是video的buffer另外一级是内存中的,只负责下载,二级很长。可以消除网络抖动带来的卡顿影响。
2、ABR自适应码率的算法
这个主要是来预测用户本身的带宽范围,然后选用不同码率的视频流来无缝切换播放。当然还有一些策略算法,比如根据用户现在buffer的水位,或者检测到用户频繁超时,来采用不同的策略。
3、基于WebRTC的P2P ??
因为P2P是基于UDP的传输,可以突破一些带宽限制或网络拥塞而导致的卡顿问题。不过P2P不一定靠谱所以还是要辅以普通的HTTP传输相结合。我们一般是利用P2P加indexDB 来变相延长视频的缓冲区。因为P2P带宽成本便宜,我们利用P2P做了一个非常长又很便宜的buffer。这样的话网络再波动也不会导致卡顿了。
- 上一篇: 服务发现与配置管理高可用最佳实践
- 下一篇: 全链路灰度在数据库上我们是怎么做的?
猜你喜欢
- 2024-10-13 阿里云 ACK One 新特性:多集群网关,帮您快速构建同城容灾系统
- 2024-10-13 使用AMP得到更高效的PyTorch模型 mpi pytorch
- 2024-10-13 超性能 WASM 播放器WXInlinePlayer
- 2024-10-13 微服务容器化最短路径,微服务 on Serverless 最佳实践
- 2024-10-13 并没媒体说的那么难用~优雅用好win10的正确姿势
- 2024-10-13 「他山之石」PyTorch trick 集锦 他山之石图片
- 2024-10-13 模型量化与量化在LLM中的应用 | 得物技术
- 2024-10-13 Windows软件必装清单?看看有没有你想要的!
- 2024-10-13 重装系统后,送你一份 Windows 软件必装清单
- 2024-10-13 视频编码器的智能化——AI辅助编解码的ASIC解决方案
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)