最近做視頻功能等限,看了一些視頻相關的插件,發(fā)現(xiàn)下面兩個還是比較好用芬膝,這里推薦一下:
videojs
Mui Player
videojs應該很多人都知道望门,比較成熟的插件了這里是官網(wǎng)地址:
然后Mui Player也是很不錯跟videojs差不多都很好用,對比videojs優(yōu)勢應該就是文檔更好閱讀點對于英語不好的是個好事锰霜。
我自己用了videojs筹误,
然后項目主要是做了視頻的一個上傳和視頻的展示功能
看看效果圖:
使用的話官方文檔自己翻
最后主要說一下我用了插件后踩的一些坑,特別是上傳部分癣缅,其它的都還好厨剪。
我項目需求上傳需要做封面圖,然后安卓用戶的插件可以支持自動截取視頻第一張圖友存,ios手機上的因為限制不支持視頻自動去加載元數(shù)據(jù)不會自動截取視頻第一張圖祷膳,所以ios的需要特殊處理一下,先將視頻設置為運行小窗口播放屡立,然后視頻加載時執(zhí)行一下手動播放然后馬上暫停直晨,因為ios不支持自動播放要獲取第一幀必須點擊一下播放視頻,代碼如下:
videoScreenshot(file, key) {
let tthis = this;
try {
var reader = new FileReader();
reader.onload = function () {
var videoDom = document.createElement("video");
videoDom.setAttribute('muted', true);
videoDom.setAttribute('autoplay', true);
videoDom.setAttribute('x5-video-player-fullscreen', true);
videoDom.setAttribute('webkit-playsinline', true);
videoDom.setAttribute('playsinline', true);
videoDom.setAttribute('x5-playsinline', true);
videoDom.setAttribute('x-webkit-airplay', 'allow');
videoDom.onloadeddata = function () {
videoDom.play();
videoDom.pause();
}
videoDom.onplay = function() {
setTimeout(()=>{
var canvas = document.createElement("canvas");
canvas.width = this.videoWidth;
canvas.height = this.videoHeight;
canvas.getContext("2d").drawImage(this, 0, 0, canvas.width, canvas.height);
tthis[key].poster = canvas.toDataURL('image/png');
tthis[key].duration = this.duration;
tthis[key].coverImg = tthis.base64ToFile(canvas.toDataURL('image/png'));
tthis.compressorImg(tthis[key].coverImg, key);
tthis.upVideo();
}, 100)
}
videoDom.src = URL.createObjectURL(new Blob([file], { type: "video/mp4" }));
}
reader.readAsDataURL(file);
} catch (e) {
console.log(e)
}
},
這樣就能兼容到ios上的視頻格式了
對于mac還有其它設備測試后可以給一個與加載元數(shù)據(jù)屬性能夠自動去加載視頻第一幀做為封面就不需要去截圖其實:
preload: "metadata",
寫了一個視頻組件配置代碼:
<template>
<div class="contentVideo" :id="'myVideoWrap_' + videoData.name" :class="{blur: videoData.blur}">
<video :id="'myVideo_' + videoData.name" class="video-js">
<source :src="videoData.url" type="video/mp4">
</video>
</div>
</template>
<script>
import Video from 'video.js'
import 'video.js/dist/video-js.css'
export default {
name: 'videoTemplate',
data() {
return {
myVideo: '',
}
},
props: ['videoData', 'startFn', 'endFn'],
mounted() {
this.initVideo();
},
destroyed() {
this.myVideo.dispose();
},
methods: {
initVideo() {
let tthis = this;
let option = {
controls: true,
playbackRates: [0.7, 1.0, 1.5, 2.0], // Set playback speed options
loop: false,
muted: true,// Default Mute Play or Not
disablePictureInPicture: true,
playsinline: true,
//autoplay: "muted", // Mute Play or Not
preload: "metadata",
//poster: this.videoData.poster,
...this.videoData.plugins,//Replace the Default Configuration
};
this.myVideo = Video('myVideo_' + this.videoData.name, option,function onPlayerReady() {
this.on('play', function() {
_.forEach(document.getElementsByTagName('video'), (val) => {
if (val != this.el_.children[0]) {
val.pause()
}
});
tthis.startFn ? tthis.startFn(tthis.videoData) : '';
});
this.on('ended', function() {
tthis.endFn ? tthis.endFn(tthis.videoData) : '';
});
});
}
},
}
</script>
<style lang="less" scoped>
.contentVideo {
width: 100%;
height: 100%;
overflow: hidden;
/deep/ .video-js .vjs-big-play-button {
width: 40px;
height: 40px;
line-height: 40px;
border-radius: 50%;
font-size: 18px;
top: 50%;
left: 50%;
margin-top: -20px;
margin-left: -20px;
border: 1px solid #FFFFFF;
}
/deep/ .video-js {
width: 100%;
height: 100%;
}
/deep/ .video-js .vjs-picture-in-picture-control {
display: none;
}
/deep/ .video-js .vjs-play-progress:before {
top: -0.45em;
}
/deep/ .vjs-slider-horizontal .vjs-volume-level:before {
top: -0.45em;
}
}
.contentVideo.blur /deep/ video {
-webkit-filter: blur(6px);
filter: blur(6px);
transform: scale(1.1);
}
</style>
調用時:
<videoTemplate1 :videoData="videoDataFormat(item)" :startFn="hideVideoDuration" :endFn="videoEndFn"/>
videoDataFormat(item) {
let videoData = {
id: item.attachments[0].video.id,
name: 'list_' + item.attachments[0].video.id + Date.now(),
canWatch: item.canWatch,
url: item.attachments[0].video.url,
profId: item.userId,
poster: item.attachments[0].cover.url,
blur: !parseInt(item.canWatch) && item.userId != this.myUserInfo.userId,
}
return videoData;
},
屬性和方法根據(jù)自己的業(yè)務需求自己去添加
然后關于截圖也有另外的方式膨俐,那就是使用ffmpeg的方式
這個npm安裝@ffmpeg包就可以了勇皇,然后運行ffmpeg命令就可以做截圖很簡單,但是可能包比較大有20多M焚刺,對于項目可能才幾十M來說這個包實在可能太冗余了蒜绽。
如果覺得包太大可以自己做wasm包蛤织,將多余的ffmpeg的功能剔除掉生成wasm包然后壓縮,如果只是截圖功能估計能壓縮到3-4M左右,完全能符合上線的要求减余。
對于如何生成ffmpeg 的wasm包這個要用到 WebAssembl, 感興趣的可以去了解下運行起來也是很絲滑就是上手難度較高。
用ffmpeg截圖让虐,那幾乎兼容所有視頻格式的诅炉。