最近在自己的小程序实现视频转gif的功能,开发过程中发现网上的很多方案在小程序中实现效果不好或不能实现,比如:
使用前端canvas方案实现的(gif.js,gifshot.js等),在h5上效果没问题,但是在小程序中获取数据的时候极慢;
后来就转而使用uniCloud的云函数方式实现,即使用node.js实现。node.js使用node-canvas后端生成gif,这个是可以的,但是uniCloud使用的服务器node版本自己无法升级,导致想要发布,就只能放弃这个方案。
自己研究了很久,最终使用前端canvas按间隔时间截取一组图片,然后上传到uniCloud,再通过node的gif-encoder,get-pixels等第三方包在云服务端将图片合成gif文件,上传到服务器,就可以在小程序将文件下载到本地了。
小程序前端生成视频截图的代码参考:
视频转gif(一):前端(小程序)实现截取视频画面图片
node.js 使用gif-encoder和get-pixels实现多图转gif
const GIFEncoder = require('gif-encoder');
const getPixels = require('get-pixels')
const fs = require('fs');
const path = require('path');
const urlArr = [
'/tmp/1.png',
'/tmp/2.png',
'/tmp/3.png',
'/tmp/4.png',
'/tmp/5.png',
'/tmp/6.png',
]
const gif = new GIFEncoder(300, 150);
var file = fs.createWriteStream(`pixels-gif${Date.now()}.gif`);
gif.pipe(file)
gif.writeHeader();
gif.setRepeat(0); // 0 for repeat, -1 for no-repeat
gif.setDelay(500); // frame delay in ms
gif.setQuality(10); // image quality. 10 is default.
gif.on('readable', async (err) => {
console.log('readable:');
})
gif.on('end', function () {
console.log('end:');
});
var addToGif = async function (images, counter = 0) {
// http + gif-encoder
try {
// 读取图片像素信息
const pixels = await getImgPixels(urlArr[counter])
gif.addFrame(pixels.data)
if (counter === images.length - 1) {
gif.finish();
} else {
addToGif(images, ++counter);
}
} catch(err) {
console.log("Bad image path", err)
}
}
// http 请求图片资源,转为pixels(getPixels包实现)
function getImgPixels(url, name) {
const p = new Promise((resolve, reject) => {
getPixels(url, function(err, pixels) {
if(err) {
console.log("Bad image path")
reject(err)
return
}
resolve(pixels)
})
})
return p
}
addToGif(urlArr)
也欢迎,扫码体验一下,如有使用问题可以联系我(目前小程序云服务器未续费,导致无法正常使用20231218)