vue中好用的视频插件推荐,video+canvas实现视频截图第一帧,ffmpeg实现视频截图第一帧
我项目需求上传需要做封面图,然后安卓用户的插件可以支持自动截取视频第一张图,ios手机上的因为限制不支持视频自动去加载元数据不会自动截取视频第一张图,所以ios的需要特殊处理一下,先将视频设置为运行小窗口播放,然后视频加载时执行一下手动播放然后马上暂停,因为ios不支持自动播放要获取第一帧必须点击一下播放视频,代码如下:...
·
最近做视频功能,看了一些视频相关的插件,发现下面两个还是比较好用,这里推荐一下:
videojs
Mui Player
videojs应该很多人都知道,比较成熟的插件了这里是官网地址:
然后Mui Player也是很不错跟videojs差不多都很好用,对比videojs优势应该就是文档更好阅读点对于英语不好的是个好事。
我自己用了videojs,
然后项目主要是做了视频的一个上传和视频的展示功能
看看效果图:
使用的话官方文档自己翻
最后主要说一下我用了插件后踩的一些坑,特别是上传部分,其它的都还好。
我项目需求上传需要做封面图,然后安卓用户的插件可以支持自动截取视频第一张图,ios手机上的因为限制不支持视频自动去加载元数据不会自动截取视频第一张图,所以ios的需要特殊处理一下,先将视频设置为运行小窗口播放,然后视频加载时执行一下手动播放然后马上暂停,因为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还有其它设备测试后可以给一个与加载元数据属性能够自动去加载视频第一帧做为封面就不需要去截图其实:
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;
},
属性和方法根据自己的业务需求自己去添加
然后关于截图也有另外的方式,那就是使用ffmpeg的方式
这个npm安装@ffmpeg包就可以了,然后运行ffmpeg命令就可以做截图很简单,但是可能包比较大有20多M,对于项目可能才几十M来说这个包实在可能太冗余了。
如果觉得包太大可以自己做wasm包,将多余的ffmpeg的功能剔除掉生成wasm包然后压缩,如果只是截图功能估计能压缩到3-4M左右,完全能符合上线的要求。
对于如何生成ffmpeg 的wasm包这个要用到 [WebAssembl](http://webassembly.org.cn/), 感兴趣的可以去了解下运行起来也是很丝滑就是上手难度较高。
![ffmpeg运行图](https://img-blog.csdnimg.cn/a0ef35fbaa35401e9045c4f0da4fc20c.png)
用ffmpeg截图,那几乎兼容所有视频格式的。
更多推荐
已为社区贡献2条内容
所有评论(0)