运用 src 属性
图1.1 一般mp4的下载要求历程
图1.2 Youtube视频下载要求历程
这两张图不难看出,在默许状况下 mp4 运用一次 http 要求一切的视频数据,Youtube 则分次要求。固然这个形貌很不专业,但确切抽象。形成这类差别的是 video 不支撑流式的视频数据,Youtube 采纳的是流式的视频容器 webm,而 mp4 黑白流式的。那怎样诠释清晰流式的视频数据呢,从专业的角度一言半语很难说清晰,但用大白话翻译过来就是流式的视频数据支撑分段自力播放,非流式的不能够。换句话说一个10M的视频文件,流式的视频能够把0~1M的数据要求返来零丁播放,但黑白流式的不能够。
上面我们形貌了视频花样的差别,接下来我们要说的是第一张图中的视频加载是阅读器来掌握的,经由过程给 video 的 src 属性设置视频地点,触发播放以后阅读器就会最先下载了,JS过问不了。而 Youtube 的视频加载是经由过程JS来掌握的,列位能够再次看下第二张图的收集要求范例:xhr,足以证实这一点。
上面两点搞清晰以后我们就该说下清晰度切换的事变了。这个需求人人都不生疏,然则直接运用 mp4 花样做无缝清晰度切换,难度还挺大的。先诠释下“无缝清晰度切换”的观点:从播放一个分辨率的视频到另一个分辨率且保证画面、声响不停顿的腻滑切换历程。了解了这个观点,人人应当知道了用 video 无缝切换 mp4 有多灾。一方面,video 是不支撑流式的视频花样的,一方面,video 的加载是不受JS掌握的。经由过程切换 video 的 src 属性,必然会致使画面中缀、从新要求视频数据等。有的同砚想到说应用两个 video 再连系 z-index 来搞,然则当你天生另一个video去加载视频的时候,没法保证两个画面是严厉一致的,纵然将本来的画面暂停到一个时候,用另一个视频经由过程 currentTime 属性与之同步,切换依然看到画面闪灼,基础没法和 Youtube 无缝切换的体验对抗。而且还会形成更多流量的糟蹋,背地的缘由人人能够研讨下 mp4 容器和 webm 容器的异同,也能够看下视频解码相干的文章。
另有一种要领就是将 mp4 花样一切转码到流式的视频花样比方 hls、webm 等。不过这类看上去可行的体式格局现实上会带来很大的本钱开支,如将大批视频做转码会斲丧奋发的机械资本、双倍存储的用度、CDN的双倍用度等等。实在我们也是在这类背景下研讨出来新的手艺题目处理清晰度无缝切换的。
起首,我们转变对 mp4 视频的播放流程,不再直接运用 video 的 src 来播放,由于我们没有任何能够操纵的空间。video不仅支撑 src 属性还支撑 Blob 对象,我们就是应用后者。播放的流程以下:
图1.3 mp4 视频新播放流程
- 来要求 mp4 视频数据,如许能够连系视频 Range 效劳,做到准确加载。
- 编写剖析器将加载返来的部份 mp4 视频数据举行解复用
- 将解复用的视频数据转成 fmp4 花样并传递给 MediaSource
- 运用 video 举行解码完成播放
然后在做清晰度切换的时候流程以下:
图1.4 mp4视频清晰度切换道理示意图
- 来要求 mp4 视频数据,如许能够连系视频 Range 效劳,做到准确加载。
- 编写剖析器将加载返来的部份 mp4 视频数据举行解复用
- 将解复用的视频数据转成 fmp4 花样并传递给 MediaSource
运用 video 举行解码完成播放
然后在做清晰度切换的时候流程以下:
图1.5 mp4视频清晰度切换流程示意图
这个历程看上去比较烦琐,然则一切的操纵都是在阅读器端完成,也就是说都是JS来完成的。如许之前说的一切本钱题目都不存在,还能做到youtube雷同体验的无缝切换。假如人人也想运用这个功用不需要本身再去完成一遍上述流程,能够运用以下代码:
import Player from 'xgplayer';
import 'xgplayer-mp4';
let player = new Player({
el:document.querySelector('#mse'),
url: [{src:'/mp4/',type:"video/mp4"},{src:'/mp5/',type:'video/mp4'}]
});
player.emit('resourceReady', [{name: '高清', url: '/mp4/',cname:'高清'}, {name: '超清', url: '/mp5/',cname:'超清'}]);
假如对这段代码有什么迷惑或许想深切了解下它背地是怎样完成的能够参考 文档 或许 Github。
节约视频流量
我们日常平凡直接运用video加载视频,大概是如许的:
图2.1 video默许下载截图
我随意找了个视频,人人看下视频总长度是 02:08,在播放到 00:05 的时候,阅读器已下载到 01:30 了,假如用户停止寓目,下载的视频就如许被糟蹋掉了。固然,假如不停的 seek 也会形成较多的流量糟蹋。根据我们之前的统计在短视频范畴,用户 seek 的频次在 80%,所以这部份流量是能够节约掉的。详细道理以下:
图2.2 播放器加载视频道理
- 设置每次加载的数据包大小
- 设置预加载时长
- 开启加载行列,完成第一次数据包下载,推断缓冲时候和预加载时长是不是满足,不满足要求下一个数据包
详细完成代码以下:
import Player from 'xgplayer';
import 'xgplayer-mp4';
const player = new Player({
id:'vs',
url:'//abc.com/a/mp4',
preloadTime:10
});
如许就完成了视频在播放历程当中永久只预加载10秒的数据,进而保证节约流量。
一切代码来自带剖析器、能节约流量的西瓜播放器,Github