原生JS实现视频截图功能的示例代码
作者:Marco-hui
视频截图效果预览
利用Canvas进行截图
要用原生js实现视频截图,可以利用canvas
的绘图功能 ctx.drawImage
,只需要获取到视频标签,就可以通过drawImage
把视频当前帧图像绘制在canvas画布上。
const video = document.querySelector('video') const canvas = document.createElement('canvas') const w = video.videoWidth const h = video.videoHeight canvas.width = w canvas.height = h const ctx = canvas.getContext('2d') ctx.drawImage(video, 0, 0, w, h)
接下来,需要把画布转化为图片,canvas提供了两个2D转换为图片的方法:canvas.toDataURL()
和canvas.toBlob()
canvas.toDataURL(mimeType, qualityArgument)方法
toDataURL可以把图片转换成base64格式的图片,是一个同步方法,使用很简单,在上面已经绘制好画布的基础上,只需要下面一行代码就可以获取到当前视频帧的截图了
const imageUrl = canvas.toDataURL("image/png") console.log(imageUrl)
可以看到,它最终生成了一个很长字符串的base64图片地址。
canvas.toBlob(callback, mimeType, qualityArgument)方法
这个方法相比上一个方法的优点是它是异步的,所以有一个callback回调,这个callback回调方法默认的第一个参数就是转换好的blob文件信息,本文也想重点介绍这种方法的使用。
先说明一下这个方法的三个参数:
参数 | 类型 | 是否必传 | 说明 |
---|---|---|---|
callback | Function | 是 | toBlob()方法执行成功后的回调方法,支持一个参数,表示当前转换的Blob对象 |
mimeType | String | 否 | 表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等 |
qualityArgument | Number | 否 | 表示转换的图片质量。范围是0到1。由于Canvas的toBlob()方法转PNG是无损的,因此,此参数默认是没有效的,除非,指定图片mimeType是image/jpeg或者image/webp,此时默认压缩值是0.92 |
使用写法如下:
canvas.toBlob((blob) => { console.log(blob) }, 'image/png', 0.92)
可以看到方法执行得到的是当前转换的Blob对象
那么剩下的就是要将此Blob对象进一步转化为可供img
显示的图片地址。
将Blob对象转化为图片地址
下面介绍三种方法进行转化:
方式一: 通过URL.createObjectURL()方法将Blob转化为URL
canvas.toBlob((blob) => { const imageUrl = URL.createObjectURL(blob) console.log(1, imageUrl) }, 'image/jpeg', 1)
如下图所示,转化得到的是一个bold流的图片地址。
方式二: 通过FileReader将Blob转化为DataURL
canvas.toBlob((blob) => { const reader = new FileReader() reader.readAsDataURL(blob) reader.onload = () => { const imageUrl = reader.result console.log(2, imageUrl) } }, 'image/webp', 1)
如下图所示,转化得到的是一个base64的图片地址。
方式三: 通过ajax将Blob上传到服务器
canvas.toBlob((blob) => { const formData = new FormData() formData.append('file', blob) // 这里的'file'是接口接收参数的字段名,需要根据实际情况改变 const xhr = new XMLHttpRequest() xhr.onload = () => { const imageUrl = JSON.parse(xhr.responseText).data // 接口回调参数,需要根据实际情况处理 console.log(3, imageUrl) } xhr.open('POST', '/api/upload', true) // '/api/upload'是上传接口,需要根据实际情况改变 xhr.send(formData) }, 'image/webp', 1)
由此就会将图片上传到你的文件服务器里,最终可以得到一个你自己文件服务器下对应的图片地址。
toBlob()方法的兼容
首先,toBlob()方法IE9浏览器不支持,因为Blob数据格式IE10+才支持。
然后,对于IE浏览器,toBlob()的兼容性有些奇怪,IE10浏览器支持ms私有前缀的toBlob()方法,完整方法名称是msToBlob()。而IE11+,toBlob()方法却不支持。
但是,我们可以基于toDataURL()方法进行polyfill,性能相对会差一些,JavaScript代码如下:
if (!HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { value: function (callback, type, quality) { var canvas = this setTimeout(function() { var binStr = atob( canvas.toDataURL(type, quality).split(',')[1] ) var len = binStr.length var arr = new Uint8Array(len) for (var i = 0; i < len; i++) { arr[i] = binStr.charCodeAt(i) } callback(new Blob([arr], { type: type || 'image/png' })) }) } }) }
注意事项
使用外部链接播放视频的话需要在视频标签上设置允许跨域的处理,添加属性crossOrigin='anonymous'
即可,
<video className="videoTag" crossOrigin='anonymous' controls> <source src="https://www.w3school.com.cn/example/html5/mov_bbb.mp4" type='video/mp4' /> </video> <video className="videoTag" crossOrigin='anonymous' controls> <source src="https://www.w3school.com.cn/example/html5/mov_bbb.mp4" type='video/mp4' /> </video>
或者,在js里处理
const video = document.querySelector(".videoTag") video.setAttribute('crossOrigin', 'anonymous') video.load()
否则会报以下错误:
完整封装示例
最后,给出一个利用toBlob
进行视频截图,最终获取base64图片地址
的封装方法,代码示例如下:
function getBase64ByVideo(video) { const canvas = document.createElement("canvas") const w = video.videoWidth const h = video.videoHeight canvas.width = w canvas.height = h return new Promise((resolve, reject) => { // 由于toBlob方法是异步的,所以这里用Promise const ctx = canvas.getContext('2d') ctx.drawImage(video, 0, 0, w, h) canvas.toBlob((blob) => { // 通过FileReader将Blob转化为DataURL const reader = new FileReader() reader.readAsDataURL(blob) reader.onload = () => { const imageUrl = reader.result resolve(imageUrl) } }, 'image/webp', 1) // 根据需要可以自行配置这里的两个参数 }) }
调用方法:
const videoTag = document.querySelector(".videoTag") const dataUrl = await getBase64ByVideo(videoTag)
以上就是原生JS实现视频截图功能的示例代码的详细内容,更多关于JS视频截图的资料请关注脚本之家其它相关文章!