在 graphicsmagick 中从远程流创建 GIF

Posted

技术标签:

【中文标题】在 graphicsmagick 中从远程流创建 GIF【英文标题】:Creating a GIF from remote stream in graphicsmagick 【发布时间】:2018-04-03 14:52:57 【问题描述】:

我正在通过将每个图像下载到文件系统中的 tmp 文件夹,从节点中的远程文件创建一个 GIF。

我想绕过将图像保存到 tmp 文件夹并保存在内存中。这可能吗?

如您所见,我的 AWS 类中有一个下载功能,它保存到 tmp 文件夹:

download(key)
    return new Promise((resolve, reject) => 
      request.head(`$this.base_url/$this.bucket/$key`, (err, res, body) => 
        request(`$this.base_url/$this.bucket/$key`)
            .pipe(fs.createWriteStream(`tmp/$key`)).on('close', resolve )
      )
    )
;

一旦它们全部下载完毕,我的 GifService 类中有一个 createGif 函数,它将每个文件路径添加为 gm 的自定义参数,添加 50 毫秒的延迟,调整大小然后输出为缓冲区,然后我将其上传到 AWS s3.

import gm from 'gm';

...

constructor()
    this.gm = gm()


generateGif(images, prefix)

    return new Promise((resolve, reject) => 

        // for each image we want in array, we pass to gm
        images.forEach(image => 
            this.gm.in(`tmp/$image.Key`)
        )

        // Now we create the gif with 50sec delay between images, sized to 600px x 2
        this.gm
            .delay(50)
            .resize(600,600)
            .toBuffer('gif', async (err, buffer) => 
        if (err) reject(err)

        const params = 
                ACL: 'public-read',
                Bucket: config.aws_bucket,
                ContentType: 'image/gif',
                Key: `$prefix/$uuid().gif`,
                Body: buffer
              

              try
                // uplaod to S3
            const upload = await this.aws.upload(params)

            // resolve s3 URL
            resolve(upload)

              catch(err) 
                console.log('err', err)
                reject(err)
              

      );
    )


理想情况下,如果我可以将远程文件流作为自定义参数传递,或者将缓冲区作为自定义参数传递,而不是我当前在 tmp 文件路径中传递的方式:

images.forEach(image => 
    this.gm.in(`tmp/$image.Key`)
)

【问题讨论】:

更新了我的帖子,展示我如何实例化 gm / graphicsmagick 【参考方案1】:

我设法通过首先将图像转换为miff 并将它们连接成单个流来仅使用streams 使其工作。然后使用delay 再次将bufferstream 传递给gm 就可以了。

您需要安装 concat-stream npm 才能正常工作。

抱歉,混合了 ES5 代码。

import gm from 'gm';
var concat = require('concat-stream');
...

constructor() 
    this.gm = gm()


start() 

    return getYourReadAbleStreamsSomehow().then(streams => 

        return generateGif(streams);

    ).then(gifBuffer => 

        return uploadToAWS(gifBuffer, prefix);

    ).catch(err => 
        console.log(err)
    )



uploadToAWS(buffer, prefix) 
    const params = 
        ACL: 'public-read',
        Bucket: config.aws_bucket,
        ContentType: 'image/gif',
        Key: `$prefix/$uuid().gif`,
        Body: buffer
    

    try 
        // uplaod to S3
        const upload = await this.aws.upload(params)

        // resolve s3 URL
        resolve(upload)

     catch (err) 
        console.log('err', err)
        reject(err)
    


generateGif(imageStreams, delay) 

    return new Promise((resolve, reject) => 

        var write = concat(function(buffer) 
            gm(buffer)
                .delay(delay)
                .toBuffer('gif', function(err, buffer) 

                    if (err) 
                        reject(err);

                    resolve(buffer);

                )
        )

        //Convert to miff and concat streams
        var i = 0;
        var streamHandler = function() 

            gm(imageStreams[i])
                .resize('600', '600')
                .stream('miff', function(err, stdout, stderr) 
                    if (err)
                        reject(err)

                    var lastOne = i === streams.length - 1;

                    if (!lastOne)
                        stdout.once('end', streamHandler)

                    stdout.pipe(write, 
                        end: lastOne
                    );

                    i++;

                );
        

        streamHandler();

    )


【讨论】:

如果我错了,请纠正我,但基本上streamHandler 正在从我所有的原始图像缓冲区中创建 1 个流? 是的,它将每个图像转换为miff,然后可以用于转换为gif。我尝试使用 png 但它不起作用。告诉我你有没有用。

以上是关于在 graphicsmagick 中从远程流创建 GIF的主要内容,如果未能解决你的问题,请参考以下文章

异步GraphicsMagick For Node

如何在 android 中从远程 url 播放实时视频流?

在 CentOS6 上安装 GraphicsMagick-1.3.30

在 AWS Lambda 函数中从 S3 获取对象并发送到 Api Gateway

graphicsmagick - 将图像转换为 pdf,反之亦然

如何通过 graphicsmagick 命令编辑 exif 元数据?