使用Node.js中的GM生成动画GIF

7

我已经花了几天时间解决这个问题,现在我需要寻求帮助。

我正在尝试在基于node.js的应用程序中使用graphicsmagic包生成一个动画gif。

我已经生成了几张幻灯片,看起来有点像这样。

var slides = [];

for (var i=0; i < 10; i++) {
  var slide = gm(200, 200, '#000000')
    .fill('#ffffff')
    .drawText("Slide #"+ i);

  slides.push(slide);
}

我可以将它们转换成流或缓冲区,也可以将它们保存为硬盘上的单独文件,这种方式有点可行。
但我的问题是如何在内存中完全创建一个动态gif,而不需要将单个文件保存到硬盘上?
我看到gm有像#delay()和#page()这样的方法,所以从技术上讲,我可以制作一个命令。
convert -delay 200 -page slide1.gif -page slide2.gif output.gif

我不知道如何做。我认为它应该看起来像这样。
var end_image = gm(200, 200, '#000000');

end_image.delay(500);

for (var i=0; i < slides.length; i++) {
  slides[i].toBuffer(function(err, buffer) {
    end_image.page(200, 200, ????);
  });
}

end_image.write("output.gif");

基本上我不知道如何将缓冲区转换为gm的参数。
有人以前做过吗?也许还有另一种方法?
PS:我也尝试使用gifencoder包,并成功地将gm缓冲区作为帧馈送到gifencoder的API中,但输出全部损坏了。

你能解决这个问题吗?我已经尝试了gifencoder(像你一样,但是在使用addFrame()与缓冲区时会出现分段错误)和gif模块(似乎只适用于较旧版本的node)。 - Gregir
@Gregir 没有,是通过将一堆文件倒入 /tmp 并进行 shell 外壳处理完成的。 - Nikolay
我有使用JIMP库完成此操作的代码,但我正在尝试自己使用GM来完成此操作。 - PirateApp
3个回答

4
这可能不是您想要的确切答案,但我认为以下内容回答了问题标题:“如何在Node.js中使用GM生成动态gif图像”。
var Gm = require("gm");

Gm()
.in("image1.jpg")
.in("image2.jpg")
.delay(100)
.resize(600,600)
.write("animated.gif", function(err){
  if (err) throw err;
  console.log("animated.gif created");
});

谢谢你挽救了我的一天。 - Javascript Hupp Technologies

2

有一个 gif 模块可以帮助你创建静态和动态的gif。


1
是的,我看到了,但据我所知它只适用于硬盘,会将所有内容转储到“/tmp”文件夹中。我需要在内存中处理所有内容,这样我就可以在Heroku上进行托管,并且没有HDD io。(我需要生成很多这些图像,我不想将它们保存在HDD上) - Nikolay
你也可以在内存中完成它。请查看此示例。 - mscdex
@Nikolay,在Heroku上你可以使用本地文件系统,并且编写临时文件也是完全可以的。但是请注意,在应用程序重新启动时不能依赖这些文件仍然存在。 - raine
@rane,是的,那就是我所做的,只是想知道是否有一种方法可以完全在内存中运行。 - Nikolay
1
值得注意的是,node-gif只能在node <= 0.8上运行,因此非常过时。 - Josiah Nunemaker

0

对于任何寻找 JavaScript 编码器(而不是 C++ Node 模块)的人来说,gifencoder 似乎能够胜任。以下是他们网页上的一个示例:

const GIFEncoder = require('gifencoder');
const encoder = new GIFEncoder(854, 480);
const pngFileStream = require('png-file-stream');
const fs = require('fs');

const stream = pngFileStream('test/**/frame?.png')
  .pipe(encoder.createWriteStream({ repeat: -1, delay: 500, quality: 10 }))
  .pipe(fs.createWriteStream('myanimated.gif'));

stream.on('finish', function () {
  // Process generated GIF
});

// Alternately, you can wrap the "finish" event in a Promise
await new Promise((resolve, reject) => {
  stream.on('finish', resolve);
  stream.on('error', reject);
});

太好了。有没有可能把gif作为响应返回,而不是将其写入文件中? - avijendr
不要使用.pipe(fs.createWriteStream('myanimated.gif')),而是使用.pipe(response)response.body。请提出一个详细的新问题。 - Tomáš Hübelbauer
1
谢谢 - 当然,有一个问题。您能否回答我提出的这个问题?- https://stackoverflow.com/questions/72823352/can-nodejs-gifencoder-directly-pipe-a-generated-gif-to-aws-lambda-response?noredirect=1#comment128628152_72823352 - avijendr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接