最近做视频功能,看了一些视频相关的插件,发现下面两个还是比较好用,这里推荐一下:
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截图,那几乎兼容所有视频格式的。
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图