最近在开发一个类似腾讯视频这样的电影播放网站,遇到了不少问题,记录一下使用videojs插件时,在safari浏览器下引入插件后,清晰度失效的问题

因为电影、电视剧播放器这块是我负责的模块,项目中使用的是videojs,因为要实现播倍速切换、清晰度切换等功能,所以又引入了videojs-contrib-quality-levels.js 插件。并且项目要求兼容IE11及以上,chrome,firefox,safari等主流浏览器。

页面简化后如下:

//引入的css
<link href="video-js.css" rel="stylesheet" />
//html内容
    <video id=example-video width=600 height=300 class="video-js" controls>
    	        <source src=''demo.m3u8">
    </video>
//引入的js
<script src="video.min.js"></script>
<script src="videojs-contrib-hls.min.js"></script>
<script src="videojs-hls-quality-selector.js"></script> 
<script src="videojs-contrib-quality-levels.js"></script>

//js代码如下

 var player = videojs('example-video', {
            bigPlayButton: true
        }, function () {
            let qualityObj = this.hlsQualitySelector({
                displayCurrentQuality: true
            })
        });

其他浏览器清晰度切换都正常,在mac的safari浏览器下,出现了一场,浏览器清晰度切换栏未出现,并且出现了异常的图标。在视频播放的时候,报错信息如下:

Unhandled Promise Rejection: AbortError: The operation was aborted.

通过查咨询得知,需要这样设置

videojs.options.hls.overrideNative = true;
videojs.options.html5.nativeAudioTracks = false;
videojs.options.html5.nativeVideoTracks = false;

还不行,最后改为这样才解决了BUG:

//引入的css
<link href="video-js.css" rel="stylesheet" />
//html内容 (source里不写源地址,而且实际项目中也是通过js设置播放源的)
    <video id=example-video width=600 height=300 class="video-js" controls>
    </video>
//引入的js
<script src="video.min.js"></script>
<script src="videojs-contrib-hls.min.js"></script>
<script src="videojs-hls-quality-selector.js"></script> 
<script src="videojs-contrib-quality-levels.js"></script>

//js代码如下
videojs.options.hls.overrideNative = true;
videojs.options.html5.nativeAudioTracks = false;
videojs.options.html5.nativeVideoTracks = false;
 var player = videojs('example-video', {
            bigPlayButton: true
        }, function () {
        	this.src({
        		src: 'my-demo.m3u8'
        	})
            let qualityObj = this.hlsQualitySelector({
                displayCurrentQuality: true
            })
        });

期间查阅资料如下:

https://github.com/videojs/videojs-contrib-quality-levels/issues/32

https://github.com/videojs/videojs-contrib-quality-levels/issues/20

https://github.com/videojs/videojs-contrib-hls#overridenative


问题分析:

在最后一个链接里是引入的videojs-contrib-hls插件的官方文档:

其中关于 overrideNative 有写到:

Try to use videojs-contrib-hls even on platforms that provide some level of HLS support natively. There are a number of platforms that technically play back HLS content but aren’t very reliable or are missing features like CEA-608 captions support. When overrideNative is true, if the platform supports Media Source Extensions videojs-contrib-hls will take over HLS playback to provide a more consistent experience.

NOTE: If you use this option, you must also set videojs.options.html5.nativeAudioTracks and videojs.options.html5.nativeVideoTracks to false. videojs-contrib-hls relies on audio and video tracks to play streams with alternate audio and requires additional capabilities only supported by non-native tracks in video.js.

这段话的大意是:即使一些平台支原生支持HLS,但是考虑到一些稳定性,一些字母支持等功能,还是建议使用该插件(哈哈)。但是必须设置overrideNative 为true。

同时下面的NOTE是告诉我们,既然设置overrideNative 为true,就必须设置videojs的另外两个属性为false.

基本读到这里搞清楚了。


何为HLS?

HTTP Live Streaming,也就是我们常说的HLS。HLS是苹果公司提出的基于HTTP的流媒体网络传输协议。类似于MPEG-DASH,但是HLS更加简洁,它的基本原理也是服务端把文件或媒体流按照不同的码率切分成一个个小片段进行传输,客户端在播放码流时,可以根据自身的带宽及性能限制,在同一视频内容的不同码率的备用源中,选择合适码率的码流进行下载播放。


由此可见,safari是原生支持HLS的,所以我们必须如官方文档所说,做上述设置。

而代码中的this.src({})这种方式设置播放源,也是官方文档给的正确的使用姿势。