Cloud Functions for Firebase:在不触及最大超时的情况下完成长流程

Posted

技术标签:

【中文标题】Cloud Functions for Firebase:在不触及最大超时的情况下完成长流程【英文标题】:Cloud Functions for Firebase: completing long processes without touching maximum timeout 【发布时间】:2017-11-12 03:57:27 【问题描述】:

当视频上传到 Firebase 存储时,我必须将视频从 webm 转码为 mp4。 I have a code demo here that works,但是如果上传的视频太大,我的firebase函数会在转换完成之前超时。我知道可以增加函数的超时限制,但这似乎很麻烦,因为我无法确认该过程将花费比超时限制更少的时间。

有什么方法可以阻止 firebase 超时而不只是增加最大超时限制?

如果没有,有没有办法完成耗时的过程(如视频转换),同时仍然让每个过程开始使用 firebase 函数触发器?

如果甚至使用 firebase 函数完成耗时的过程并不是真正存在的东西,有没有什么方法可以在不影响质量的情况下加快 fluent-ffmpeg 的转换? (我意识到这部分有很多问题。如果绝对必要,我计划降低质量,因为 webms 转换为 mp4 的原因是用于 ios 设备)

作为参考,这是我提到的演示的主要部分。正如我之前所说,完整的代码可以是seen here,但复制过来的这部分代码是创建确保转码完成的 Promise 的部分。完整的代码只有 70 多行,所以如果需要的话应该比较容易通过。

const functions = require('firebase-functions');
const mkdirp = require('mkdirp-promise');
const gcs = require('@google-cloud/storage')();
const Promise = require('bluebird');
const ffmpeg = require('fluent-ffmpeg');
const ffmpeg_static = require('ffmpeg-static');

(这里有一堆文本解析代码,后面是 onChange 事件中的下一段代码)

function promisifyCommand (command) 
    return new Promise( (cb) => 
        command
        .on( 'end',   ()      =>  cb(null)   )
        .on( 'error', (error) =>  cb(error)  )
        .run();
    )

return mkdirp(tempLocalDir).then(() => 
    console.log('Directory Created')
    //Download item from bucket
    const bucket = gcs.bucket(object.bucket);
    return bucket.file(filePath).download(destination: tempLocalFile).then(() => 
      console.log('file downloaded to convert. Location:', tempLocalFile)
      cmd = ffmpeg(source:tempLocalFile)
               .setFfmpegPath(ffmpeg_static.path)
               .inputFormat(fileExtension)
               .output(tempLocalMP4File)
      cmd = promisifyCommand(cmd)
      return cmd.then(() => 
        //Getting here takes forever, because video transcoding takes forever!
        console.log('mp4 created at ', tempLocalMP4File)
        return bucket.upload(tempLocalMP4File, 
            destination: MP4FilePath
        ).then(() => 
          console.log('mp4 uploaded at', filePath);
        );
      )
    );
  );

【问题讨论】:

嗨!如果您签出代码中的How to create a Minimal, Complete, and Verifiable example 以备将来在堆栈溢出时使用会更好。 -谢谢 对不起!我意识到人们习惯于看代码。我已将一些 index.js 文件复制到问题中。不过,它可能没有那么有用。 【参考方案1】:

Cloud Functions for Firebase 不太适合(也不支持)可能超过最大超时时间的长时间运行任务。 only Cloud Functions 执行非常繁重的计算操作的唯一真正机会是找到一种方法将工作拆分为多个函数调用,然后将所有工作的结果合并到最终产品中。对于像视频转码这样的事情,这听起来是一项非常艰巨的任务。

相反,请考虑在App Engine 或Compute Engine 中使用函数来触发长时间运行的任务。

【讨论】:

接下来,您认为仅通过向其发送 http 请求来触发应用引擎进程最有意义吗?有没有更好的方法来处理它?我并不清楚 App Engine 的工作原理(完全),所以您认为对我的案例最有用的任何信息都会很棒。 “Cloud Functions for Firebase 不太适合(并且不支持)长时间运行的任务”,记录这一点可以为我节省数周时间。现在正在研究 App Engine。谢谢:D @ScottEwing 您知道如何在 GAE 上触发工作流程吗?面临与 Cloud Functions 相同的限制问题并愿意迁移到 GAE/GCE Here 是更新后的 firebase 函数代码的文件,here 是我用于 GAE 的 app.js 文件。基本工作流程是 Firebase Functions 向转码器进程的 url 发送一个 http 请求,如果视频存在,它将对视频进行转码。 anyone 可以发送请求以在 firebase 服务器上对视频进行转码,但安全风险不大。使用原始代码需要您自担风险【参考方案2】:

作为对试图弄清楚如何通过转码视频或其他一些漫长过程的随机匿名人员的跟进,这是我给出的相同代码示例的一个版本,它向谷歌应用程序引擎进程发送了一个 http 请求它对文件进行转码。目前还没有相关文档,但查看 Firebase/functions/index.js 代码和 app.js 代码可能会帮助您解决问题。

https://github.com/Scew5145/GCSConvertDemo

祝你好运。

【讨论】:

以上是关于Cloud Functions for Firebase:在不触及最大超时的情况下完成长流程的主要内容,如果未能解决你的问题,请参考以下文章