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,一经查实,立即删除!

相关文章

mysql57数据库命令_MySQL 5.7 mysql command line client 使用命令详解

MySQL 5.7MySQL command line client 使用命令1.输入密码:******2.ues mysql;使用Mysql3.show databases;显示数据库4.use register;使用数据库名为register5.show tables;显示register数据库中的表6.describe user;对表user进行操作:insert into user(u…

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

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

阿里云mysql 分布式_MySQL大型分布式集群

本套课程将通过分布式集群和分库分表两部分内容进行讲解1、主要解决针对大型网站架构中持久化部分中,大量数据存储以及高并发访问所带来是数据读写问题。分布式是将一个业务拆分为多个子业务,部署在不同的服务器上。集群是同一个业务,部署在多…

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

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

mysql 5.6.14 win32_mysql-5.6.14-win32为免安装解压缩版

mysql-5.6.14-win32为免安装解压缩版,安装版(http://dev.mysql.com/downloads/installer/5.5.html#downloads)存在很多弊端。mysql 5.6.14 win7 32位免安装版配置1.下载mysql 5.6.14;下载地址:http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.14-wi…

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

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

mysql 货币显示_在MySQL中以正确的格式显示USD货币记录

FORMAT()在MySQL中使用,以正确的格式显示USD货币记录。让我们首先创建一个表-mysql> create table DemoTable-> (-> Amount DECIMAL(15,4)-> );使用插入命令在表中插入一些记录-mysql> insert into DemoTable values(90948484);mysql> insert int…

js监听iframe关闭_Node.js文档NET[翻译]

Node.js v12.0.0 Documentation​nodejs.orgNet模块提供一个异步的网络API,这个API可以创建基于流的TCP,或者IPC服务器(net.createServer()),和客户端(net.createConnection())。它可以这样访问…

mysql 主键倒序查询速度慢_一亿条数据order by主键降序速度很慢

我用sysbench造了1亿条数据,mysql用了30分钟,tidb总共花了3个小时,感觉tidb在批量插入时比较慢,如果后面程序做分页查询会很慢的.count总数、降序排序也比mysql慢。tidb 执行时间,count 一亿条数据用了1分22秒多&#…

python切片逆序_Python 的逆序同时切片如何操作?

Python 的切片,语法是这样的a[[start]:[end][:[step]]]其中索引为 end 的元素不会被包括进来。start、end、step 和 step 前面的冒号都可以省略。这么多可以省略的,那么解释器是怎么设置默认值的呢?解释器对正序和逆序切片的默认值设置是不一…

camunda流程定义表无数据_创建流程实例时 act_ru_identitylink 表中没有出现相关的人员数据...

老师您好,我对流程实例有两个问题:创建流程实例的方法,视频中给出的是ProcessInstance processInstance runtimeService.startProcessInstanceByKey("Process_1", "business_id");请问这个方法和如下所示的方法有什么区…

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

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

mysql代码不熟_mysql存储过程的错误,语法不熟,找了好久没找到错误。。。

CREATEPROCEDUREupdate_pointer()begin/*done为1执行异常,停止执行*/DECLAREDoneINTDEFAULT0;DECLAREnowtimeINT;DECLAREyuefloat;DECLAREuidint;DECLAREyqmoneyfloat;DECLAREsummone...CREATE PROCEDURE update_pointer()begin/*done为1执行异常,停止执…

python axes_浅谈matplotlib.pyplot与axes的关系

最近在学习数据可视化,梳理一下其中一些诸如pandas绘图、matplotlib绘图、pyplot(plt)、axes等概念。重要的事情说三遍:axes不是axis!axes不是axis!axes不是axis!重要的事情说三遍:pyplot是接口不是对象&am…

protobuf2和3同时安装_安装protobuf可能遇到的问题

http://code.google.com/p/protobuf/downloads/list安装:unzip protobuf-2.3.0.zipcd protobuf-2.3.0./configuremakemake checkmake install1.每步在执行过程中注意权限问题,有的命令不sudo执行会出问题。./configuremakemake checkmake install2. 执行…

python制作考试系统_Python系统学习 - Pytest单元测试框架

哈咯,大家,我们今天来学习pytest单元测试框架,这个框架要比unittest更加易于使用,结构性也更加好,希望大家能够从中学习到有用的东西,然后在下一章,我们来使用pytest单元测试框架来搭建一个web自…

python分析推特_用Python关注者的关注者抓取Twitter数据的最快方法

我在用Python在Twitter上做一个关于用户社交关系的研究。在问题是“什么是最快的方式抓取某个用户的关注者信息”我搜索了很多信息,目前正在使用Tweepy:c tweepy.Cursor(api.followers_ids, idcentre, count5000).items()while True:try:followers_ids_…

python修复不了_如何修复Python代码?

当您将变量定义为str()时,就是将它们分配给一个空字符串(尝试在命令shell或IDLE中运行str(),然后查看其返回值)。在然后,使用input()函数,您将为某些字符串重新定义变量,并且在if语句中,您将使用这些比较运…

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

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

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

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