视频转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的功能。

也欢迎,扫码体验一下,如有使用问题可以联系我(目前小程序云服务器未续费,导致无法正常使用20231218)
在这里插入图片描述

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝with黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值