web td不对齐_珍稀干货!阿里 Web 音视频开发趟坑指南

73febc7763f55e1146279a2617c17320.png

作者 | 阿里文娱前端技术专家 归影

责编 | 夕颜

出品 | CSDN(ID:CSDNnews)

这不是一篇基于MSE开发Web播放器的入门文章,而是围绕Web播放器开发遇到的常见问题与解决方案,毕竟入门文章常有而趟坑干货不常有。如果您有Web播放开发经验和音视频技术基础,读起来会更有共鸣。

85e78fa0d2a9ab3fb1cd55dbe16049c7.png

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。

d3372fa5b3f3dcec6f33e19a8654dd60.png

图1:MSE简明结构

MSE内部可以创建一系列的sourcebuffer,一般是一个音频buffer,一个视频buffer。把MSE做成blob url之后绑定给video的src。然后就可以通过appendBuffer往video里追加音视频数据了。有了MSE,播放器器的整体结构是什么样的呢,见下图。

26058c91c1dc316b8400d226f455460b.png

图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里。

89f49a00bc2310b0d75d527d21ada8a3.png

时间戳对齐

转封装除了的封装格式的解复用(demux)和再复用(remux)之外最重要的环节就是分片的时间戳对齐策略,以及音视频同步。

c2c012a451eda4e0063b9123312dd755.png

图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两个尾部指针来做。如果发现后续分片时间轴有间隔就往前推从而填上间隔。如果发现重叠,就把重叠帧后移。这样虽然会导致后续分片的前几帧重叠。但在播放的过程中几乎没有影响。

140d3efa48703d3635d9fa91244c0e74.png

音视频同步

首先,什么情况下会导致音画不同步?

1、视频源流压根没对齐。没救了,看下一点。

2、还是因为有洞。很多时候视频切出来的每个分片之间都不一定是严丝合缝的,分片间的音视频时间戳可能有洞。而且对于TS由于音频每一帧的duration(≈23ms) 跟视频每一帧的duration(40ms@25fps) 无法吻合(整除) 所以加剧了这种参差不齐的情况。那么,重点来了!chrome有个特殊的机制,如果发现音频之间有洞之后,为了保证音频的平顺,会自动把后续音频往前推抹平这个洞。如果每个分片都有洞,悲剧了,这种往前推的操作就会积累越来越多导致音视频不同步。

小tips:

打开chrome的媒体调试页面 chrome://media-internals 可以看到媒体播放相关的所有debug信息和error信息非常有用。其中就会有一条关于音频处理的提示:

29dc95d5575770e3042207aa1d1e18ae.png

当然这条显示的具体原因是自动切掉重叠overlap导致的。其实gap/overlap本质是一样的。怎么办?当然是播放器自己主动把洞填上。具体做法是插帧。目前主要是插静音帧,或者复制前一帧。静音帧会带来毛刺音,复制帧会导致拖音。我们目前的优化方案是判断附近的音频数据量,数据量大时说明此处声音丰富(其实不算靠谱,姑且这么处理,因为没有更好的判断方式),如果插静音帧会毛刺很明显,所以此时用复制帧,反之插静音帧。

71bbdbbcc94608a972aa15f8a7f2bbb7.png

那些年我们趟过的坑

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。比如已经播放过的,正常浏览器会自己清除,但是不那么的及时。

547bb9119458bbab42f9cf7a5aa73660.png

优化

简单说一下卡顿相关的优化。

  • 多级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。这样的话网络再波动也不会导致卡顿了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/502626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

subscribe error不执行_你不知道的redis:第三方jar无封装命令我们该怎么执行?

redis的基本操作指令就不多说了,今天对redis的进阶操作给大家介绍一下,以及对于jedis和redisTemplate等工具包没有封装的命令我们该如何使用?相信大家读了本篇对redis的整体会有更深的认知。一、Pipelin模式介绍1、redis的通常使用方式大多数…

子窗体 记录选择_如何设计一个简单的Access登录窗体(1)

Access是一个对数据库新手相当友好的软件。Access的窗体功能确实是一种独一无二的前端设计平台,很多常见的人机交互用法,可以用Access的窗体来轻松实现,同时Access的查询和计算功能,也需要窗体的配合才能获得最佳的表达效果。 一、…

网页javascript加载不出_写给初学者的JavaScript异步编程和背后思想

导读:对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程。为什么顺序执行程序就不行了呢?非要使用异步回…

静态网页托管_求职季,教你制作一份精美的在线网页简历,程序员必看!!

引言近期和学弟交流了一下找实习的相关的话题,谈到了简历这块。虽然近期没有找工作的打算,但还是会不定期的更新自己的简历。于是将自己的简历分享了一下,没想到得到了这样的评价,心里还是挺高兴的。简历的形式是一个在线的静态网…

为什么不可以使用哈曼顿距离_K-means真的不能使用曼哈顿距离吗?

问题说到k-means聚类算法,想必大家已经对它很熟悉了,它是基于距离计算的经典无监督算法,但是有一次在我接受面试时,面试官问了我一个问题:“k-means为什么不能使用曼哈顿距离计算,而使用欧式距离进行计算&a…

linux 查看进程_Linux怎么查看和监控每个进程的实时流量

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号**“智传网优”**直接开始自助**视频学习**1. 前言NetHogs是一个开源的命令行工具(类似于Linux的top命令),用来按进程或程序实时统计网络带宽使用率。来自NetH…

mysql修改密码1820_mysql5.7初始化密码报错ERROR1820(HY000):YoumustresetyourpasswordusingALTERUSERstateme...

1,mysql5.6是密码为空直接进入数据库的,但是mysql5.7就需要初始密码cat /var/log/mysqld.log | grep password或者:grep temporary password /var/log/mysqld.lo2,然后执行 mysql -uroot -p,输入上面的到的密码进入&am…

linux复制文件夹到另一个目录_Linux|一个命令行统计给定目录中有多少个子目录,学浪计划...

wc命令用于统计指定文件的字节数、字数、行数、并将统计结果显示出来。一般格式: wc [选项] [文件]选项:-c,--bytes 统计字节数-l,--lines 统计行数-w,--words 统计字数ls命令-l 以长格式显示文本的详细信息。-R 表示递…

mysql源码安装分析_MySQL源码分析(0):编译安装及调试(转)

编译安装为了实现MySQL的更高级别的性能调优,我们通常需要理解其内部实现机制,并对其进行优化调试。在下面的系列中,我们会分别介绍MySQL的部分内部实现机制。首先我们介绍如何从源代码部署一台MySQL服务器。1.下载MySQL Community Server源码…

前端做后台管理系统有前途吗_关于后台管理系统前端项目的思考

开发后台管理系统是大部分前端开发人员接触过的项目,如何更好的进行项目的搭建、组件的开发、数据结构的设计等等,这些都是需要考虑的问题。以下是我结合一些项目的经历和其他大佬的项目代码与技术分享,做出了对于后台管理系统中前端项目的思…

响应式编程优点 有效_什么是响应式编程?

响应式编程是一种通过异步和数据流来构建事物关系的编程模型。这里每个词都很重要,“事物的关系”是响应式编程的核心理念,“数据流”和“异步”是实现这个核心理念的关键。为了帮助大家理解这个概念,我们不妨以APP初始化业务为例来拆解一下这…

虚拟跳线软件干什么用的_视频教程:用 ESI 的虚拟跳线给你的声音添加效果

本视频讲述了如何在互联网上给你的声音添加效果。你可以使用任何想用的效果器,而且不仅可以输入你的声音,输入信号还可以是任何乐器音源,例如键盘或吉他,你甚至可以直播你的整个工程。请先看视频:视频中使用Bitwig给声…

极光推送java demo_极光推送- 3 分钟 Demo - 极光文档

3 分钟快速使用 JPush Android Demo本文目的在于,指导新接触极光推送的开发者,在短短几分钟时间内把极光推送跑起来:安装 Demo 客户端到手机在 Portal 上推送通知客户端收到推送并显示在状态栏创建极光推送开发者帐号Portal 上创建应用使用注…

java ldap添加用户名密码_java ldap用户密码md5加密

在这里不过多介绍ldap,因为这样的文章特别多,这里就简单直接的记录这一个问题。在springboot中通过引入spring-boot-starter-data-ldap,使用LdapTemplate真的挺方便,现在遇到一个问题,添加用户时,userPassw…

java dumpstack_Java获取执行进程的dump文件及获取Java stack

转发自https://blog.csdn.net/MCC_MCC_MCC/article/details/806231561.Windows/Linux环境下查看Java进程ID方法使用Java自带的工具VisualVM工具实现,在CMD或者是Linux终端下执行“jvisualvm”命令即可以进入VisualVM控制台,双击左侧的进程即可以查看到详…

mysql not in优化_实践中如何优化MySQL(收藏)

SQL语句的优化:1、尽量避免使用子查询3、用IN来替换OR4、LIKE前缀%号、双百分号、_下划线查询非索引列或*无法使用到索引,如果查询的是索引列则可以5、读取适当的记录LIMIT M,N,而不要读多余的记录6、避免数据类型不一致7、分组统计可以禁止排…

java 鼠标精灵_纯Java实现跨平台鼠标键盘模拟、找图找色,Java版按键精灵

由原本的Java使用JNI调用dll实现模拟辅助操作,升级到纯Java来实现,最新: https://github.com/xnx3/xnx31.[代码][Java]代码/*** 鼠标、键盘、延迟等基本操作*/public static void simple(){Robot robot new Robot();robot.delay(1000); //延…

o2oa二次开发比开发难吗_6年经验大牛,带你一起打开 Revit 二次开发的新世界大门...

​知乎视频​www.zhihu.com你好,这里是BIMBOX。一线的BIM工作者使用最多的软件是Revit,它功能强大,涵盖建筑、结构、MEP等专业,也正因为涵盖专业太多,它显得有点繁琐和笨拙,不仅约束了创造力,有…

python中的str方法和repr方法_Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些

Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些发布时间:2020-11-05 17:11:48来源:亿速云阅读:95作者:Leah本篇文章给大家分享的是有关Python中 的 __str__ 方法和 __repr__ 方法的区别有哪些,小编觉得挺实用的…

requestbody前端怎么传_学习前端开发前的基础知识了解「V1001」

一、什么是http协议?什么是协议,就是一群人协商好了,统一认知的规则。【例】你,我,他,还有她他他,大家一致认定结婚的时候都要给份子钱,这种大家认同的就是协议。http协议,就规定了…