高仿 优酷 播放器 dash-player

预览

先看效果
http://yangchaojie.top/plugin/dash-player

image.png

why do it

如果你点了上面的地址。你就会发现,视频要加载几秒时间才能播放,虽然我已经使用的流媒体形式(下面会讲)。主要原因还是服务器带宽不够,像我这样个人服务器只有1M的速度,一个小短片15M的话就要加载十几秒才能开始播放。
像youku,B站 这种视频网站,虽然带宽高,但访问的人多,视频也更大,不会蠢蠢的放的静态MP4地址上去,等加载完2G的妇联4,妇联5都快出来了。

How to solve it

扯了这么多,进入正题,怎么解决大视频加载问题。

本文档内容使用的操作环境

系统 linux 
浏览器 firefox (`一定要使用火狐,先放弃一下chrome`)
编辑器 vscode 

有业务经验的人肯定知道,文件体积大就分割嘛,就像分片上传一样,浏览器不能一次上传太大文件那就分割上传。视频文件大就分段加载。

看看youku 怎么做的

来看下youku 上的video.src 上绑定的啥
image.png

什么是blob:https://...

Blob URL(参考W3C,官方名称)或Object-URL(参考MDN和方法名称)与BlobFile对象一起使用。

Blob URL只能由浏览器在内部生成。URL.createObjectURL()将创建一个特殊的
File 对象、Blob 对象或者 MediaSource 对的引用,

那么普通视频文件地址怎么转成blob:https://...

  • 创建一个 File对象 的引用

直接使用 input 选择本地视频即可

    

  • 创建一个 Blob对象 的引用

    Blob(Binary Large Object) 对象表示一个不可变、原始数据的类文件对象。
    Blob对象代表了一段二进制数据。其它操作二进制数据的接口都是建立在此对象的基础之上。

File对象其实继承自Blob对象,并提供了提供了name , lastModifiedDate, size ,type 等基础元数据。
所以他们互相转换很容易, File=>Blob

XMLHttpRequest第二版XHR2允许服务器返回二进制数据,创建blob对象的引用更适合加载网络视频

function ajax(url, cb) {
    const xhr = new XMLHttpRequest();
    xhr.open("get", url);
    xhr.responseType = "blob"; 
    // "text"-字符串 "blob"-Blob对象 "arraybuffer"-ArrayBuffer对象
    xhr.onload = function () {
        cb(xhr.response);
    };
    xhr.send();
}
ajax('video.mp4', function (res) {
    const src = URL.createObjectURL(res);
    video.src = src;
})

image.png

用调试工具查看视频标签的src属性已经变成一个Blob URL,表面上看起来是不是和各大视频网站形式一致了,但是考虑一个问题,这种形式要等到请求完全部视频数据才能播放,依然面临大视频加载缓慢的问题。

答案应该就在对MediaSource 的引用上。

  • 对MediaSource的引用

    什么是Media Source

    MediaSource包含在Media Source Extensions (MSE)标准中。
    MSE解决的问题:现有架构过于简单,只能满足一次播放整个曲目的需要,无法实现拆分/合并数个缓冲文件。
    MSE内容:MSE 使我们可以把通常的单个媒体文件的 src 值替换成引用 MediaSource 对象(一个包含即将播放的媒体文件的准备状态等信息的容器),以及引用多个 SourceBuffer 对象(代表多个组成整个串流的不同媒体块)的元素。MSE 让我们能够根据内容获取的大小和频率,或是内存占用详情(例如什么时候缓存被回收),进行更加精准地控制。 它是基于它可扩展的 API 建立自适应比特率流客户端(例如DASH 或 HLS 的客户端)的基础。

简单的说就是先让video 加载 MediaSource 对象,但MediaSource 对象没有视频具体内容,内容被分割在SourceBuffer 对象中,可能有音频SourceBuffer,视频SourceBuffer,字幕SourceBuffer,
image.png

看到buffer就有谱了,可以向缓存区一点点写入video数据
SourceBuffer.appendBuffer(source)

source

一个 BufferSource 对象(ArrayBufferView 或 ArrayBuffer),存储了你要添加到 SourceBuffer 中去的媒体片段数据。

值得注意的是这里使用的是追加ArrayBuffer
xhr.responseType 应该等于 "arraybuffer"
ArrayBuffer对象也代表储存二进制数据的一段内存,
Blob与ArrayBuffer的区别是,除了原始字节以外它还提供了mime type作为元数据,Blob和ArrayBuffer之间可以进行转换。

阅读文档,可以很快写出一个加载示例

我这里已经对视频做好了分割,后面会讲如何分割,下面chunk-stream0 代表240分辨率,如果感觉加载快可以换成chunk-stream1 代表480分辨率,甚至chunk-stream2 代表1280分辨率,相应init-stream0 也要变化


查看控制台 已经不断的请求分割的片段
image.png

但你肯定发现没有音频信息,对的,你音响坏了,
这里我们只加载了视频信息,并没有加载音频,所以我们还要加载音频


    

稍微改动下代码,ok 现在一个基本流媒体播放 搞定
image.png

但是,还有一个问题,很严重的问题,就是没有办法拖动进度。
因为它不知道整个视频是什么样的,有多长,是否有声音轨,有几条等等。只知道加载过的片短视频是什么样的。
所以需要一个描述文件 mpd。

MPD

MPD是一个XML文件,描述了媒体的分段方式,类型和编解码器(此处为MP4),视频的比特率,长度和基本分段大小。MPD文件还能包含音频信息,您可以将内容拆分为视频和音频播放器的单独流(就像上面我拆成了多个流)。

DASH

那么MPD 文件和上面的分段文件 是怎么生成的?需要先了解DASH
DASH(Dynamic Adaptive Streaming over HTTP )是一个规范了自适应内容应当如何被获取的协议。它实际上是建立在 MSE 顶部的一个层,用来构建自适应比特率串流客户端。虽然已经有一个类似的协议了(例如 HTTP 串流直播(HLS)),但 DASH 有最好的跨平台兼容性。

是一种服务端、客户端的流媒体解决方案:
服务端:
将视频内容分割为一个个分片,每个分片可以存在不同的编码形式(不同的codec、profile、分辨率、码率等);
播放器端:
就可以根据自由选择需要播放的媒体分片;可以实现adaptive bitrate streaming技术。不同画质内容无缝切换,提供更好的播放体验。

个人理解:MSE是标准,描述了媒体文件可以流式接收,DASH是协议规范了媒体文件如何分轨,如何分段,如何接收。

概念太多,给大家看点实际的

ffmpeg -i  你的文件.mp4 -c copy -use_template 0 -single_file 0  -f dash index.mpd

执行上面命令可以得到 所需的 mpd 文件 和 分段后媒体文件
ffmpeg可以 面向搜索引擎安装。

有了描述文件MPD ,怎么解决拖动视频

很简单了,mpd已经描述了媒体长度提前告诉mediaSource就行了

MediaSource 接口的属性 duration 用来获取或者设置当前媒体展示的时长.
image.png

我使用的视频长度是1M8.2s,也就是1分钟+8.2秒=68.2秒

mediaSource.duration = 68.2;

image.png

现在再来看看视频就有长度,可以拖动进度了。
image.png

有点小激动

到这里还只是仅仅正常播放,还有许多问题没有解决,比如现在拖动进度虽然可以播放,但还是要加载完之前内容片段才行,需要改进成只加载当前,还有切换多分辨率没有实现,最头痛的是兼容性,如果你坚持使用chrome或其他浏览器没有使用火狐,应该是大部分代码没有办法运行。问题还很多,这时候就要找轮子了。(也没时间搞,因为公司倒闭了,要花点时间找工作,过段时间再深入研究)

投入 dash.js 怀抱

Dash.js是用JavaScript编写的开源MPEG-DASH视频播放器。其目标是提供一个健壮的跨平台播放器,可以在需要视频播放的应用程序中自由重用。
高仿优酷播放器就是应用了dash.js, 但是dash.js也存在一些问题(也不算问题,就是没有直接提供API),比如不能立即切换分辨率,必须等当前已加载片段播放完后才能切换,所以在dash.js 基础上稍加包裹,不敢说封装,人家已经相当完美。提供一些更易上手的播放器API。dash-player

资源下载

dash-demo

参考文档

你可能感兴趣的:(javascript,html,视频,流媒体播放器,前端)