欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

消除奇怪的前端错误:1 比特损失导致音频/视频播放时间无限增长 - Http 分路传输的核心分析和坑洞 - 调试程序

最编程 2024-10-14 20:27:45
...

1. 初步分析

首先,我注意到播放器的duration显示为无穷大。为了进一步测试,我尝试将currentTime设置为一个非常大的值,但问题依然存在。但是在单独的页面播放和oppo的某手机播放没问题,就猜测是某个特殊点的兼容性问题,但部分尝试做了兼容,所以正常,但大部分的设备或者webview都没有兼容,导致这个问题没被处理,从而出现时长无限。这时候测试得到一个比较重要的信息:

  • 特别小的文件,时长在5秒内的不会出现无限时长,视频文件大概率都会出现

于是就进一步猜测,肯定和网络传输有关,而且和文件体积有关系,这时候想起了大文件分片,因为上传的时候就是分片上传的

2. 网络请求分析

观察到网络请求一直处于pending状态,我怀疑可能是由于socket没有正确关闭导致无限加载。我尝试在数据流关闭后结束请求,但这并没有解决问题。

  1. 而且发现浏览器在不同的发送包内容基本一样的请求

3. 请求头分析

仔细查看请求头,我发现了一些奇怪的Range请求,如Range=11333-11333/11334。起初,我认为可能是因为起始值和结束值相同导致的问题。我尝试在这种情况下重写Range,对于Range=11333-这样的请求则返回416状态码。但这些措施都没有解决问题。

也就是这里引起了我的警觉,因为是不停的在请求,一开始的时候,还以为是触发了某个浏览器的bug,但是分析请求头,有一点引起可我的注意,就是11333-11333/11334 ,为什么会请求这样的数据,第一反应是一个0字节的请求

然后我就开始读HTTP1.1-rfc2616规范文档,发现这了这个反直觉的坑,那就是范围的结尾值是包含的。

这里基本上我猜测到了问题出现的原因,下一步就是验证了

附rfc的说明 - inclusive,开始还不确定这个单词的意思
在这里插入图片描述

4. 深入源码

分析第三方库的源码后,我发现了问题的根源:

  • HTTP的Content-Range头中,start和end都是包含的(inclusive)。
  • 而在JavaScript和MongoDB中,类似slice()这样的操作,end是不包含的(exclusive)。

这种不一致性导致了在处理最后一个字节时出现问题。具体来说:

  1. 当客户端请求最后一个字节时(例如Range: bytes=11333-11333),服务器正确地解释了这个请求。
  2. 但是,当服务器使用JavaScript或MongoDB的API来获取这个范围的数据时,由于end是exclusive的,实际上没有返回任何数据。
  3. 这导致客户端认为还有更多数据需要获取,因此会继续发送请求,造成无限加载的情况。