详解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 相关文章推荐
动态的创建一个元素createElement及删除一个元素
Jan 24 Javascript
javascript实现动态模态绑定grid过程代码
Sep 22 Javascript
浅谈JavaScript实现面向对象中的类
Dec 09 Javascript
JavaScript获取两个数组交集的方法
Jun 09 Javascript
Jquery简单分页实现方法
Jul 24 Javascript
Javascript中的prototype与继承
Feb 06 Javascript
windows下更新npm和node的方法
Nov 30 Javascript
vue 设置proxyTable参数进行代理跨域
Apr 09 Javascript
详解javascript 正则表达式之分组与前瞻匹配
May 30 Javascript
微信开发之微信jssdk录音功能开发示例
Oct 22 Javascript
JS module的导出和导入的实现代码
Feb 25 Javascript
JS大坑之19位数的Number型精度丢失问题详解
Apr 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
解析PayPal支付接口的PHP开发方式
2010/11/28 PHP
PHP实现数据库的增删查改功能及完整代码
2018/04/18 PHP
jQuery(1.3.2) 7行代码搞定跟随屏幕滚动的层
2009/05/21 Javascript
jquery在Chrome下获取图片的长宽问题解决
2013/03/20 Javascript
JS实现拖动示例代码
2013/11/01 Javascript
js实现简单锁屏功能实例
2015/05/27 Javascript
javascript每日必学之基础入门
2016/02/16 Javascript
Vue学习笔记之表单输入控件绑定
2017/09/05 Javascript
vue学习之mintui picker选择器实现省市二级联动示例
2017/10/12 Javascript
js中el表达式的使用和非空判断方法
2018/03/28 Javascript
vue完成项目后,打包成静态文件的方法
2018/09/03 Javascript
JavaScript学习笔记之数组基本操作示例
2019/01/09 Javascript
JS数据类型STRING使用实例解析
2019/12/18 Javascript
jquery将信息遍历到界面上实例代码
2020/01/21 jQuery
vue 授权获取微信openId操作
2020/11/13 Javascript
[01:33]一分钟玩转DOTA2第三弹:DOTA2&DotA快捷操作大对比
2014/06/04 DOTA
python操作日期和时间的方法
2014/03/11 Python
快速解决pandas.read_csv()乱码的问题
2018/06/15 Python
Python使用ctypes调用C/C++的方法
2019/01/29 Python
python调用摄像头拍摄数据集
2019/06/01 Python
pyqt5 实现在别的窗口弹出进度条
2019/06/18 Python
详解DeBug Python神级工具PySnooper
2019/07/03 Python
Python 迭代,for...in遍历,迭代原理与应用示例
2019/10/12 Python
python实现树的深度优先遍历与广度优先遍历详解
2019/10/26 Python
Python利用全连接神经网络求解MNIST问题详解
2020/01/14 Python
Django用数据库表反向生成models类知识点详解
2020/03/25 Python
纯CSS3实现绘制各种图形实现代码详细整理
2012/12/26 HTML / CSS
css3实例教程 一款纯css3实现的环形导航菜单
2014/10/20 HTML / CSS
夜大毕业生自我鉴定
2013/10/31 职场文书
采购部主管岗位职责
2014/01/01 职场文书
餐厅保洁员岗位职责
2015/04/10 职场文书
大学生暑假实习总结
2015/07/13 职场文书
学校体育节班级口号
2015/12/25 职场文书
2016开学第一课心得体会
2016/01/23 职场文书
使用CSS实现一个搜索引擎的原理解析
2021/09/25 HTML / CSS
WIN10使用IIS部署ftp服务器详细教程
2022/08/05 Servers