我是靠谱客的博主 谦让翅膀,最近开发中收集的这篇文章主要介绍视频云web播放器样式和组件自定义,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

web播放器介绍

视频云提供的web播放器是以videojs为基础,加入了视频云自身的一些业务逻辑封装并针对性的优化而成。当前视频云直播流支持rtmp,http-flv,hls三种格式,点播支持mp4,http-flv,hls三种格式。

在pc端浏览器上,我们优先使用flash模式来播放直播和点播的各种视频格式,以提供更强大的流控制和更好的稳定性。在移动端浏览器上,使用html5模式,支持hls播放和点播mp4播放。 我们的sdk接口也支持设置techOrder:["html5","flash"]来在优先使用html5模式,值得一提的是html5模式下的hls播放并不稳定,依浏览器不同可能更容易出现播放问题。

在即将到来的下一个版本的web sdk中,我们将可能接入hls.js和flv.js。前者将提供html5模式下hls流更强大的稳定性,后者给咱们带来http-flv流在移动端浏览器播放的黑科技(喜大普奔,orz)。

近来收到很多客户自定义播放器皮肤或者组件的需求,但官网的帮助文档中缺乏对这一块儿的细致说明,本文由此而生,希望能借由本文加深大家对咱们web播放器的理解,同时能更容易的接入咱们sdk,满足各自的业务需求。

我们的播放器提供了一些默认的组件,包括posterImage,loadingSpinner,bigPlayButton,errorDisplay,controlBar等,通过名字,您应该已经能大概明白这些组件的提供功能,下面会做更详细的介绍。这些默认组件应该能满足大部分用户的基础需求,但是在很多场景下,咱们需要更深度的制定符合业务需求的样式和功能。接下来会介绍一些相关api,以及两个简单示例,由浅入深,都是干货。

播放相关的事件

很多播放组件的状态都和播放事件有关联,因此要开发播放组件,一定要先了解我们播放器能提供哪些播放相关的事件。我们知道html5 video标签能提供下面这些事件:

Html5.Events = [
'loadstart',
'suspend',
'abort',
'error',
'emptied',
'stalled',
'loadedmetadata',
'loadeddata',
'canplay',
'canplaythrough',
'playing',
'waiting',
'seeking',
'seeked',
'ended',
'durationchange',
'timeupdate',
'progress',
'play',
'pause',
'ratechange',
'volumechange'
];

这些事件的相关说明可以参见MDN

我们的播放器在播放时有flash和html5两种模式,html5模式使用video的这些原生事件,flash模式下则对这些事件做了模拟。因此我们可以使用下面的方式来监听这些事件:

var myPlayer = neplayer('my-video');
function onEnded(){
console.log("ended");
myPlayer.off("ended",onEnded);
//do something
}
myPlayer.on("ended",onEnded);

播放器初始化的说明

我们使用neplayer(id,options,cb)或者video标签中的data-setup这两种方式来初始化播放器。初始化过程除了播放相关的逻辑,还有就是默认播放组件的添加。

聪明的同学在使用chrome查看播放器元素的时候可以看到,我们给video标签外面包裹了一个div,这个div就是我们播放器的容器。容器下面的子元素首先就是咱们的播放器元素(html5模式下的video标签或者flash模式下的object),后面的子元素们就是我们的各种播放组件啦。

播放容器div会在不同状态下动态添加一些很有用的class,合理运用这些class,可以简便咱们的组件的开发,在下面罗列一些。

vjs-playing
//播放状态
vjs-paused
//暂停状态
vjs-waiting
//播放buffer为空,等待数据中 (对应播放事件中的waiting)
vjs-seeking
//seeking中 (对应播放事件中的seeking)
vjs-ended
//播放结束
vjs-has-started
//播放已经开始了,默认组件的posterImage就是通过这个class来隐藏自己
vjs-live
//当前播放的是直播流,controlBar组件中的liveDisplay子组件通过这个来显示自己
vjs-controls-disabled
//应该隐藏所有的控制组件时,例如有错误发生时
vjs-error
//有错误时
vjs-user-inactive
//用户当前处于非活动状态
vjs-user-active
//用户处于活动状态, 活动状态是指用户最近是否有移动鼠标或者点击按钮等操作。
//这种活动状态在没有新操作情况下,默认维持两秒,然后就进入非活动状态。
//在非活动状态下,一般会隐藏控制条的显示,这时候就用到这两个class了
//活动状态维持的时间可以配置,配置选项中默认 inactivityTimeout:2000

chrome查看容器下dom结构截图: 

默认组件的说明

前面提到,我们的播放器提供了一些默认的组件,下面对这些组件做些粗略的说明。

  • posterImage: 这个组件用来在播放之前显示一张静态图片。 播放容器的vjs-has-started类来控制它的隐藏。
  • bigPlayButton: 大播放按钮,默认左上角,可以通过给video标签添加vjs-big-play-centered类来居中。播放开始后也会隐藏掉。
  • loadingSpinner: 在waiting或者seeking事件出现后会显化于在屏幕中间然后转圈圈。 它的出现其实依赖于容器div的vjs-waiting或者vjs-seeking类
  • errorDisplay: 在播放错误出现时显示一个错误信息
  • controlBar: 控制条。包含了很多的播放控制相关的子组件。下面再详细说明

这几个是默认使用的播放控件,假如您嫌弃它们,可以在初始化选项中配置舍弃,例如您要实现自己的bigPlayButton,您可以配置{"bigPlayButton":false},这样默认的bigPlayButton就不会被添加到播放器中,然后您可以使用后面我们将会提到的添加播放组件相关api来添加自定义的大播放按钮。

controlBar组件的说明

controlBar组件是咱们播放器的默认控制条组件,它包含了一系列的子组件。


'playToggle',
//播放暂停按钮
'volumeMenuButton',//音量控制
'currentTimeDisplay',//当前播放时间
'timeDivider',
//
'/'
'durationDisplay',
//总时间
'progressControl',
//点播流时,播放进度条,seek控制
'liveDisplay',
//直播流时,显示LIVE
'remainingTimeDisplay',
//当前播放时间
'playbackRateMenuButton', //播放速率
'fullscreenToggle'
//全屏控制

从左到右,当前默认显示的子组件有 playToggle volumeMenuButton progressControl liveDisplay remainTimeDisplay,fullscreenToggle。要注意的是liveDisplay组件在播放直播流时才显示,下图为点播示例: 

currentTimeDisplay,timeDivider,durationDisplay是相对于 remainingTimeDisplay的另一套组件,后者只显示当前播放时间,前者还显示总时间。若要显示成前者这种模式,即 '当前时间/总时间',可以在初始化播放器选项中配置:

var myPlayer = neplayer('my-video', {controlBar:{
'currentTimeDisplay':true,
'timeDivider':true,
'durationDisplay':true,
'remainingTimeDisplay':false
}}, function() {
console.log('播放器初始化完成');
});

playbackRateMenuButton,设置播放速率的组件。当前只有html5模式下才支持设置播放速率。

var myPlayer = neplayer('my-video', {controlBar:{
'playbackRateMenuButton':{
'playbackRates': [0.1, 0.5, 1, 1.5, 2, 5]
}
}}, function() {
console.log('播放器初始化完成');
});

使用'当前时间/总时间'组件,并添加播放速率控制的效果图:

默认组件样式的修改

上面说到,每个组件和子组件都在播放容器中有对应的标签元素,这些元素上面都有各自的class类,因此要修改默认组件的样式,定义自己喜欢的皮肤将会灰常简单,您只需要写几句覆盖默认样式的css即可。 我们播放组件中的图标,使用的都是字体图标,意味着您可以随意修改图标的大小,颜色。来个栗子:

/* add css */
.vjs-control-bar{
color:red;
font-size:20px;
}

可以得到:

添加自定义组件

终于到本文的核心内容了,直接先上一盘栗子。 给咱们播放器的默认controlBar组件中加入一个新子组件,一个刷新的按钮,用来刷新播放器。 No more talk, show me the code !!!

var myPlayer;
//获取咱们组件的基类,所有组件都要继承自这个类。
var Component = neplayer.getComponent("Component");
//nePlayer.extend
继承基类
//第二个参数是一个对象,包含createEl方法,这个方法中需要返回一个html元素
//这个组件元素在后面将被添加到播放容器中
var RefreshComponent = neplayer.extend(Component,{
createEl:function(){
var button = document.createElement("button");
button.innerHTML = "刷新";
return button;
}
});
//实例化这个组件
var refreshComponent = new RefreshComponent();
//组件基类实现了事件绑定相关的接口,可以使用on绑定事件,off解绑事件
//这里给组件绑定了click事件,当点击组件元素的时候会触发
refreshComponent.on("click",function(){
console.log("click refresh button component");
myPlayer.refresh();
});
//组件被销毁时触发,可以在这里做一些回收操作,防止内存泄露
refreshComponent.on("dispose",function(){
console.log("dispose refresh button component");
});
//可以使用refreshComponent.dispose()来移除并销毁这个组件
//在初始化播放器完成的回调函数中,将组件添加到容器中
myPlayer = neplayer('my-video', {}, function() {
console.log('播放器初始化完成');
//myPlayer.corePlayer是播放器组件的基础容器,可以看做组件树的根节点
//myPlayer.corePlayer.controlBar 拿到默认组件controlBar
//使用组件的addChild方法来添加子组件
//addChild第二个参数传空对象就好,第三个参数为一个数值,代表子组件元素添加到父组件所在的位置
//第三个参数传空时表示添加到父组件的末尾,这里值为1表示为父组件孩子中的第二个节点
myPlayer.corePlayer.controlBar.addChild(refreshComponent,{},1);
});

效果如下: (the button is so ugly,why not a icon? do not mind these detail,then we can be good friends. -_-)

栗子虽然简单,但是已经覆盖了自定义组件全部相关接口。 本来这里我还想搞一个多清晰度选择的menu,但是因为时间有限(其实是懒),所以就不弄了,但是真要做也大同小异。 下面再来一个自定义错误提示的栗子,然后完美收官。

/* css */
.my-error-display{
position:absolute;
font-size:20px;
color:red;
width:80%;
top: 50%; left: 50%;
transform: translate(-50%,-50%);
border:1px solid white;
padding:10px;
display:none;
}
/*
前面提到,播放器出现错误时,我们的播放容器div会添加class vjs-error
*
这里我们使用这个类来作为错误信息的显示前提
*/
.vjs-error .my-error-display{
display:block;
}
/* js */
//错误组件使用的元素
var errorElement = document.createElement("div");
//添加class
my-error-display
neplayer.addClass(errorElement,"my-error-display");
//继承组件
var Component = neplayer.getComponent("Component");
var ErrorComponent = neplayer.extend(Component,{});
//和上面的刷新按钮那个栗子比较,这里提供了第二种声明组件元素的时机,即在实例化组件的时候传入组件元素
var errorComponent = new ErrorComponent(null,{el:errorElement});
//注意初始化选项里面的 `errorDisplay:false` ,这个配置告诉播放器别添加默认的错误组件
myPlayer = neplayer('my-video', {errorDisplay:false}, function() {
console.log('播放器初始化完成');
//添加组件到 myPlayer.corePlayer根节点
myPlayer.corePlayer.addChild(errorComponent,{});
});
//监听播放器错误事件,以展示错误消息
myPlayer.onError(function(error){
errorElement.innerHTML = error.errMsg;
//或者使用error.errCode
//您可以利用errCode显示自定义的错误提示内容
//
//errorElement.innerHTML = error.errCode===2?'网络出错':error.errMsg;
//
//播放器常见的错误消息有
//
1: 'You aborted the media playback',
//
2: 'A network error caused the media download to fail part-way.',
//
3: 'The media playback was aborted due to a corruption problem
or because the media used features your browser did not support.',
//
4: 'The media could not be loaded, either because the server or network failed
or because the format is not supported.',
//
5: 'The media is encrypted and we do not have the keys to decrypt it.',
//
6: '请勿使用推流地址拉流'
//
7: '拉流超时'
});




---------------------------------------- thanks -----------------------------------------

最后

以上就是谦让翅膀为你收集整理的视频云web播放器样式和组件自定义的全部内容,希望文章能够帮你解决视频云web播放器样式和组件自定义所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部