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

Posted 蓝with黑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了视频转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的功能。

也欢迎,扫码体验一下,如有使用问题可以联系我

三行代码使用Python将视频转Gif

一、前言

很多网站提供视频转GIF的功能,但要么收费要么有广告

实际上我们通过python,几行代码就能够实现视频转gif

(PS:最近发现了一个不错的人工智能学习网站:captainai,觉得不错请三连支持一下)


二、教程

1. 安装必备库moviepy

pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple


2. 写入代码

from moviepy.editor import *

clip = (VideoFileClip("movie.mp4"))  # 需要转为GIF的视频文件路径
clip.write_gif("movie.gif")

3. 转换效果


刚刚的GIF图虽然只有几秒,但大小却有9M之多!(还是已经缩放了分辨率的情况下)



如果需要转换的视频有几十秒,那文件大小就得上百兆甚至更多!

那该怎么解决呢?


4. GIF很大的解决方案

我们除了设置缩放分辨率resize外,还可以通过设置fps参数抽帧来减少大小

from moviepy.editor import *

clip = (VideoFileClip("movie.mp4").resize((488,225)))
clip.write_gif("movie.gif",fps=15)  #设置为每秒15帧

设置为每秒15帧后,文件大小只有2m多,一下缩小了4倍之多!



而且视觉效果也没有多大的区别


4. 截取视频长度转换

我们还可以通过设置subclip参数来指定转换的视频范围:

subclip:截取原视频中的自t_startt_end间的视频片段

将视频1-2秒片段转化为Gif

from moviepy.editor import *

clip = (VideoFileClip("movie.mp4").subclip(t_start=1, t_end=2).resize((488, 225)))
clip.write_gif("movie.gif", fps=15)

5. 指定转换后的图片大小(分辨率)

resize参数可指定转换后的图片大小

接受的参数为:

  1. 以像素或浮点表示的(width,height)
  2. 缩放百分比,如 0.5

示例

1.设置转换后的图片为600*400

clip = (VideoFileClip("movie.mp4").resize((600, 400)))

2.原视频缩放50%

clip = (VideoFileClip("movie.mp4").resize(0.5))




👇🏻欢迎关注公众号,带你从0开始学测开!👇🏻

以上是关于视频转gif:前端(小程序)实现截取视频画面图片的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg如何把5秒内的视频转成wep图片,并且每隔5秒执行一次的命令

三行代码使用Python将视频转Gif

为啥将视频转为GIF后,文件反而比视频大的多了?

怎么把视频转成gif

AVI怎么转成GIF

ffmpeg实现视频转gif及gif缩放(ffmpeg4.2.2)