视频转gif(一):前端(小程序)实现截取视频画面图片

最近在自己的小程序实现视频转gif的功能,开发过程中发现网上的很多方案在小程序中实现效果不好或不能实现,比如:
使用前端canvas方案实现的(gif.js,gifshot.js等),在h5上效果没问题,但是在小程序中获取数据的时候极慢;
后来就转而使用uniCloud的云函数方式实现,即使用node.js实现。node.js使用node-canvas后端生成gif,这个是可以的,但是uniCloud使用的服务器node版本自己无法升级,导致想要发布,就只能放弃这个方案。
自己研究了很久,最终使用前端canvas按间隔时间截取一组图片,然后上传到uniCloud,再通过node的gif-encoderget-pixels等第三方包在云服务端将图片合成gif文件,上传到服务器,就可以在小程序将文件下载到本地了。

实现该功能分两步,第一步是将视频按时间间隔截取图片;第二部:将视频按顺序拼接成gif图,并保存导出。本文章先介绍如何在前段将视频画面截图。

云函数node.js 将多图合成gif的代码和思路参考:
视频转gif(二):后端,云函数nodejs实现多图转gif

获取video元素,作为参数传给ctx.drawImage(video,),setInterval每间隔一段时间截图画面。

// 获取canvas
const getCanvasNode = (id, instance) => {
			const query = uni.createSelectorQuery().in(instance);
			const queryCvs = query.select(`#${id}`).node();
			
			return new Promise((resolve, reject) => {
				queryCvs.exec(res => {
					resolve(res);
				});
			});
		}

// 获取video节点
const getVideoContext = (id, instance) => {
			const query = uni.createSelectorQuery().in(instance);
			const queryVideo = query.select(`#${id}`).context();
			return new Promise((resolve, reject) => {
				queryVideo.exec(res => {
					resolve(res);
				});
			});
		}
async drawNative() {
			const { width, height, duration } = this.videoInfo; // 实现获取到的视频的信息
			
			// 获取video元素和canvas元素(这里是uniapp 实现,网页版可用getElementById获取)
			const videoRes = await getVideoContext('video-play', this);
			const video = videoRes[0].context;
			const canvasRes = await getCanvasNode('cas-item', this);
			const canvas = canvasRes[0].node; 
			// 改变canvas的尺寸,适配横屏视频和 竖屏视频
			canvas.width = this.cvsWidth.replace('rpx', '')
			canvas.height = this.cvsHeight.replace('rpx', '')
			
			const ctx = canvas.getContext('2d');
			// 截取视频的张数
			this.intTime = duration * 20; // 每个多少毫秒截取 2s-> 40 3s -> 60 5s -> 100
			let computedLen = Math.ceil((duration * 1000) / this.intTime); // 计算可截取的数量
			const imgNameDate = Date.now(); // 用与命名截取的图片
			try {
				
				this.timer = setInterval(async () => {
					// 微信开发工具里canvas不会动,但是真机可以
					if (computedLen < 1) {
						clearInterval(this.timer);
						// 截取完成,将图片上传到存储
						this.uploadToOssTmp(); 
						return;
					}
					// 使用canvas context drawImage将视频画面绘制到画布
					ctx.drawImage(video, 0, 0, width, height, 0, 0, canvas.width, canvas.height);
					// 从canvas获取图片像素数据
					const imgData = canvas.toDataURL('image/png', this.qualityVal);
					// genImg将imgData转换为图片base64并保存
					computedLen >= 1 && this.genImg(imgData, imgNameDate, computedLen);
					computedLen--;
				}, this.intTime);
			} catch (err) {
			}
		},
// 图片像素数据转base6并保存
async genImg(imgData, name, count, loading) {
	const fm = wx.getFileSystemManager();
	let filePath = `${this.baseTmpDirName}/${name}_${count}.png`;
	this.imgBase64.push(imgData.split(',')[1]);
},

到此,视频转GIF的第一步就完成了,接下来就是要实现多张图片转为GIF的功能。

也欢迎,扫码体验一下,如有使用问题可以联系我
在这里插入图片描述

你可能感兴趣的:(小程序,前端,小程序,javascript)