背景
老生常谈的东西:js获取video首帧,一直都知道大概怎么做,但也是第一次实践,往往这种东西都是深坑一般的存在。
开搞
首先有一个东西,就是canvas。它的上面有一个getContext方法,这个方法获得一个绘图上下文,并且可以开始绘制。canvas还有一个方法就是drawImage,这个方法接受一个image或者video对象,可以获取该对象的图像。
void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
好,现在我们有了工具,那现在要实现的就是 创建一个video对象,把我们的video的url放进去,然后设置好长宽,监听video的事件,再使用上面所说的drawImage方法就可以得到一个base64的图片。 video几个事件该如何去选择:
play: play 和 autoplay开始播放时触发
pause: 暂停时触发
waiting: 等待数据,并非错误
playing: 正在播放时触发,常常在 获取当前时长和总时长
ended: 播放结束时触发
loadeddata: 是当当前的数据已经加载完,但是,没有足够的数据去加载下一帧,会触发该事件
我这里是使用了loadeddata这个事件
let video = document.createElement('video')
video.setAttribute('crossOrigin', 'anonymous')// 处理跨域 实际屁用没有
video.setAttribute('src', url)
video.setAttribute('width', 400)
video.setAttribute('height', 240)
video.addEventListener('loadeddata', function () {
let canvas = document.createElement('canvas')
let width = video.width // canvas的尺寸和图片一样
let height = video.height
canvas.width = width
canvas.height = height
console.log(this, video)
canvas.getContext('2d').drawImage(this, 0, 0, width, height) // 绘制canvas
dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
})
现在让我们来试一下这些代码的运行情况
哇 黑屏,玩个鬼啊。这是咋回事呢。
emmm 大概感觉是当前这个时间不对,那我来手动设置一下当前视频的时间。
video.currentTime = 0.1
ok 这就可以完成了获取视频第一帧。
你以为这就完了? 太年轻了
之前的都是在chrome中,现在上真机。 在iphone上没有图片,翻找资料,哦哦哦~,原来是iphone不会自动加载,所以直接加上autoplay和muted属性,
video.setAttribute('autoplay', true)
video.setAttribute('muted', true)
但是 iphone会默认播放时是全屏的,哪怕你没有把这个video写进html里面。所以,加上行内播放。
video.setAttribute('playsinline', true)
video.setAttribute('webkit-playsinline', true)
再加一个小延时,用promise封装一下,然后就可以用啦。 完整代码:
/**
* 截取第一帧
*/
getVideoBase64(url) {
return new Promise(function (resolve, reject) {
let dataURL = ''
let video = document.createElement('video')
video.setAttribute('crossOrigin', 'anonymous')// 处理跨域
video.setAttribute('src', url)
video.setAttribute('autoplay', true)
video.setAttribute('muted', true)
video.setAttribute('playsinline', true)
video.setAttribute('webkit-playsinline', true)
video.setAttribute('width', 400)
video.setAttribute('height', 240)
video.currentTime = 0.1
video.addEventListener('loadeddata', function () {
setTimeout(() => {
let canvas = document.createElement('canvas')
let width = video.width // canvas的尺寸和图片一样
let height = video.height
canvas.width = width
canvas.height = height
canvas.getContext('2d').drawImage(this, 0, 0, width, height) // 绘制canvas
dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
resolve(dataURL)
}, 100)
})
})
},
坑点
网上资料繁杂,但是都不管用。但是我这个是我自己实践出来的,而且可以用。ios和安卓真的不一样,这个显示那个不显示的,适配是个恶心的东西