起因
最近公司想做一套視頻點播服務,因為考慮到成本問題,領導希望一切都用開源系統來完成。基於這個出發點,那就肯定排除了各大雲視頻平台(騰訊雲 音視頻點播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
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:
果然沒有,並且發現一個規律,我需要控制的按鈕都是以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",
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持我們。
您可能感興趣的文章:
- 使用vue-aplayer插件時出現的問題的解決
- vue-music關於Player播放器組件詳解
- vue音樂播放器插件vue-aplayer的配置及其使用實例詳解