详解vue2.0+vue-video-player实现hls播放全过程


Posted in Javascript onMarch 02, 2018

起因

最近公司想做一套视频点播服务,因为考虑到成本问题,领导希望一切都用开源系统来完成。基于这个出发点,那就肯定排除了各大云视频平台(腾讯云 音视频点播VOD、网易云视频、七牛云、阿里云 视频服务等)。其实这里我还是建议购买云视频平台,因为自己造轮子肯定没有别人造的好(专门研发团队除外、以此业务为生的公司除外),再说,云视频平台服务商提供的都是一整套解决方案:收集、存储、转码、播放器等,并且在cdn和弹性扩容上都能得到最大保障。

准备

视频点播最少需要两样东西:流媒体服务、视频播放器。 因为这是一篇讲述前端播放器的帖子,关于流媒体服务的搭建我就pass了,以后有时间再补充新帖。

因为公司前端架构用的是vue全家桶,所以还是希望能够找一款基于vue封装的视频播放器。

首先到vue社区找到了vue-dplayer,于是就install到本地测试了一下,这时候出现个问题:此播放器在播放基于hls协议的m3u8文件时(视频文件在流媒体服务已经成功部署),在ios上能够正常播放(自家协议支持良好),但是在pc的chrome上是不支持的。然后我去github上找了找资料,资料显示Dplay(vue-dplayer就是依据Dplay封装的)是支持hls的,只是需要引入hls.js,然后用hls对video对象进行处理。因为hls.js与Dplayer示例代码是针对video对象处理的,引入到项目中还需要修改vue-dplayer的一个属性,时间紧迫,先放弃之(之后我会有一篇专门介绍Dplayer播放hls的帖子,已补充),转身投入vue-video-player的怀抱。

为什么会用vue-video-player

1. 我搭建的流媒体服务的管理页面内的播放器就是用的videoJs(vue-video-player是依据videoJs封装的),使用之后感觉良好。
2. 百度输入“vue video”,vue-video-player就在顶部。(哈哈,就是这么随意)
3. 当然还是看了demo页,支持的协议齐全。
4. 虽然vue-video-player的github上还有些issues没有关闭,但是自己觉得守着videoJs强大的库与万千使用者,总能解决问题。(迷之自信啊)

开整

安装依赖

npm install vue-video-player --save

引入样式

// 第一个是videoJs的样式,后一个是vue-video-player的样式,因为考虑到我其他业务组件可能也会用到视频播放,所以就放在了main.js内
require('video.js/dist/video-js.css')
require('vue-video-player/src/custom-theme.css')

把VueVideoPlayer导入并挂在到vue上

//在main.js内
import VideoPlayer from 'vue-video-player'
Vue.use(VideoPlayer);

编写业务组件 myPlayer.vue

<template>
 <div class="container">
 <div class="player">
  <video-player class="video-player vjs-custom-skin"
      ref="videoPlayer"
      :playsinline="true"
      :options="playerOptions"
      @play="onPlayerPlay($event)"
      @pause="onPlayerPause($event)"
  >
  </video-player>
 </div>
 </div>
</template>

<script>
import { videoPlayer } from 'vue-video-player';
export default {
 data () {
 return {
  playerOptions: {
//  playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
  autoplay: false, //如果true,浏览器准备好时开始回放。
  muted: false, // 默认情况下将会消除任何音频。
  loop: false, // 导致视频一结束就重新开始。
  preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
  language: 'zh-CN',
  aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
  fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
  sources: [{
   type: "application/x-mpegURL",
   src: "video.m3u8" //你的m3u8地址(必填)
  }],
  poster: "poster.jpg", //你的封面地址
  width: document.documentElement.clientWidth,
  notSupportedMessage: '此视频暂无法播放,请稍后再试', //允许覆盖Video.js无法播放媒体源时显示的默认信息。
//  controlBar: {
//   timeDivider: true,
//   durationDisplay: true,
//   remainingTimeDisplay: false,
//   fullscreenToggle: true //全屏按钮
//  }
  }
 }
 },
 components: {
 videoPlayer
 },
 methods: {
 onPlayerPlay(player) {
  alert("play");
 },
 onPlayerPause(player){
  alert("pause");
 },
 },
 computed: {
 player() {
  return this.$refs.videoPlayer.player
 }
 }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style type="text/css" scoped>
 .container {
 background-color: #efefef;
 min-height: 100%;
 }
</style>

注意:

1. video-player标签的class必须设置成“video-player vjs-custom-skin”,你引入的样式才能起作用。我刚开始做时,直接拷贝的github页的代码,那个代码的class是video-player-box。
2. 根据videoJS Api修改属性。我这里加了一些注释,可以参考。
3. 修改src、poster属性为你的服务器资源地址。

增加hls支持

//安装依赖
npm install --save videojs-contrib-hls

//在main.js内引入
require('videojs-contrib-hls/dist/videojs-contrib-hls');

启动服务,查看效果

npm run dev

详解vue2.0+vue-video-player实现hls播放全过程

videoJs的播放按钮默认为椭圆形,我个人有点不习惯,所以修改成了圆形。

增加css样式

.video-js .vjs-big-play-button{
  /*
  播放按钮换成圆形
  */
 height: 2em;
 width: 2em;
 line-height: 2em;
 border-radius: 1em;
 }

注意:

直接在 myPlayer.vue组件内增加样式会被覆盖,不论你有没有增加scoped属性,这取决于vue加载样式的顺序,之前查资料看了一个帖子,讲的很好,可惜找不着了。

我最终的解决方案是:自定义了一个css文件,使用require引入到了main.js内,放在上述样式引入之后。

require('video.js/dist/video-js.css');
require('vue-video-player/src/custom-theme.css');
require('@/../static/css/myVideoCss.css');

大bug: 播放按钮与fastclick冲突

冲突是这样的:播放器在手机浏览器或者chrome开发者工具(手机尺寸)内,点击播放按钮,播放与暂停事件会被触发多次。

刚开始不知道什么原因,在github上提了个issure,刚提完就发现上一个关闭的issure解决的就是这个问题,这里得向作者道个歉,给您添堵了。哈哈。于是我看了另外一个人给的答案:与fastclick插件冲突……,但是….. 没有解决方案。然后我尝试注释掉了fastclick,果然是它影响的。

然后我去fastclick github 地址看了看 ,页面说的很清楚,只要在触发的元素上增加一个needsclick的class就可以了。

但是我试了好久都没有成功。这时候看到了神贴,大体浏览了一下fastclick的源码过程,并且作者提到“Fastclick 把 this.needsClick 放到了 ontouchEnd 末尾去执行,才导致前面说的加上了“needsclick”类名也无效的问题。”所以我想尝试修改fastclick的源码,并且验证一下。

我把整个faseclick.js拷贝了出来,并采用require的方式引用。

const FastClick = require('@/../static/js/fastclick.js');
FastClick.attach(document.body);

打开代码,猜想为什么needsclick没有起到作用,所以就直接检索了一下这个单词,在 FastClick.prototype.needsClick方法的最后,有一个验证:

return (/\bneedsclick\b/).test(target.className);

首先FastClick.prototype.needsClick方法是判断元素是否要保留穿透功能,而最后一行肯定是验证触发的元素的class是不是含有needsclick。所以我先猜测是不是我触发的元素没有加上class,所以console了target.className:

详解vue2.0+vue-video-player实现hls播放全过程

果然没有,并且发现一个规律,我需要控制的按钮都是以vjs开头的,所以,在验证上再增加一个验证。

return ((/\bneedsclick\b/).test(target.className) || (/\bvjs/).test(target.className));

问题解决,当然解决问题的方式暴力了一些,所以这里我希望看到并觉得此帖有帮助的同学能够在此基础上继续补充完善。我就先趟到这。最后贴个版本

"fastclick": "^1.0.6",
 "videojs-contrib-hls": "^5.12.2",
 "vue": "^2.2.2",
 "vue-router": "^2.2.0",
 "vue-video-player": "^4.0.6",

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 日期分离成年月日的代码
May 14 Javascript
JavaScript模版引擎的基本实现方法浅析
Feb 15 Javascript
详解Backbone.js框架中的模型Model与其集合collection
May 05 Javascript
jquery实现垂直和水平菜单导航栏
Aug 27 Javascript
Bootstrap源码解读导航条(7)
Dec 23 Javascript
vue生成文件本地打开查看效果的实例
Sep 06 Javascript
Vue.js实现的购物车功能详解
Jan 27 Javascript
echarts大屏字体自适应的方法步骤
Jul 12 Javascript
Vue实现简单计算器案例
Feb 25 Javascript
vue同个按钮控制展开和折叠同个事件操作
Jul 29 Javascript
typescript配置alias的详细步骤
Aug 12 Javascript
JavaScript实例 ODO List分析
Jan 22 Javascript
vue2.0 + element UI 中 el-table 数据导出Excel的方法
Mar 02 #Javascript
浅谈FastClick 填坑及源码解析
Mar 02 #Javascript
利用vue和element-ui设置表格内容分页的实例
Mar 02 #Javascript
vue将时间戳转换成自定义时间格式的方法
Mar 02 #Javascript
Element-ui table中过滤条件变更表格内容的方法
Mar 02 #Javascript
使用vue-aplayer插件时出现的问题的解决
Mar 02 #Javascript
VUE2.0+Element-UI+Echarts封装的组件实例
Mar 02 #Javascript
You might like
PHP 字符串编码截取函数(兼容utf-8和gb2312)
2009/05/02 PHP
php学习笔记 面向对象的构造与析构方法
2011/06/13 PHP
从零开始学YII2框架(五)快速生成代码工具 Gii 的使用
2014/08/20 PHP
PHP实现APP微信支付的实例讲解
2018/02/10 PHP
PHP count_chars()函数讲解
2019/02/14 PHP
Thinkphp 框架基础之源码获取、环境要求与目录结构分析
2020/04/27 PHP
PHP dirname功能及原理实例解析
2020/10/28 PHP
网络之美 JavaScript中Get和Set访问器的实现代码
2010/09/19 Javascript
jQuery数据缓存功能的实现思路及简单模拟
2013/05/27 Javascript
把字符串按照特定的字母顺序进行排序的js代码
2014/01/28 Javascript
在Firefox下js select标签点击无法弹出
2014/03/06 Javascript
Jquery实现textarea根据文本内容自适应高度
2015/04/03 Javascript
基于JavaScript FileReader上传图片显示本地链接
2016/05/27 Javascript
JavaScript ES6中export、import与export default的用法和区别
2017/03/14 Javascript
详解vue2.0组件通信各种情况总结与实例分析
2017/03/22 Javascript
浅谈箭头函数写法在ReactJs中的使用
2017/08/22 Javascript
Angularjs实现上传图片预览功能
2017/09/01 Javascript
vue-router判断页面未登录自动跳转到登录页的方法示例
2018/11/04 Javascript
了解重排与重绘
2019/05/29 Javascript
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
JS关闭子窗口并且刷新上一个窗口的实现示例
2020/03/10 Javascript
Python中使用glob和rmtree删除目录子目录及所有文件的例子
2014/11/21 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
Django多进程滚动日志问题解决方案
2019/12/17 Python
python3连接kafka模块pykafka生产者简单封装代码
2019/12/23 Python
python itsdangerous模块的具体使用方法
2020/02/17 Python
30行Python代码实现高分辨率图像导航的方法
2020/05/22 Python
python中温度单位转换的实例方法
2020/12/27 Python
编码转换,怎样实现将GB2312编码的字符串转换为ISO-8859-1编码的字符串
2014/01/07 面试题
大学生水果店创业计划书
2014/01/28 职场文书
国际贸易专业个人鉴定
2014/02/22 职场文书
政协调研汇报材料
2014/08/15 职场文书
出纳工作检讨书
2014/10/18 职场文书
2015医德医风个人工作总结
2015/04/02 职场文书
2016大学生党校学习心得体会
2016/01/06 职场文书
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python