Облачные функции для Firebase: выполнение длинных процессов без превышения максимального времени ожидания

Мне нужно перекодировать видео из webm в mp4, когда они загружаются в хранилище firebase. У меня есть демо-версия кода, которая работает, но если загруженное видео слишком велико, функции Firebase будут отключены по тайм-ауту на меня до завершения преобразования. Я знаю, что можно увеличить лимит времени ожидания для функции, но это кажется беспорядочным, поскольку я никогда не могу подтвердить, что процесс займет меньше времени, чем ограничение времени ожидания.

Есть ли способ остановить тайм-аут firebase, не увеличивая максимальный лимит тайм-аута?

Если нет, есть ли способ завершить трудоемкие процессы (например, преобразование видео), при этом каждый процесс запускается с использованием триггеров функций Firebase?

Если даже завершение трудоемких процессов с использованием функций Firebase на самом деле не существует, есть ли способ ускорить преобразование fluent-ffmpeg, не сильно затрагивая качество? (Я понимаю, что в этой части много вопросов. Я планирую снизить качество, если мне это абсолютно необходимо, поскольку причина, по которой веб-сайты преобразуются в mp4, предназначена для устройств IOS)

Для справки, вот основная часть упомянутой мной демонстрации. Как я уже говорил, полный код можно просмотреть здесь, но эта часть скопированного кода является той частью, которая создает промис, обеспечивающий завершение транскодирования. Полный код состоит всего из 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);
        });
      })
    });
  });

person Scott Ewing    schedule 10.06.2017    source источник
comment
Привет ! Было бы лучше, если бы вы проверили Как создать минимальный, полный и проверяемый пример вашего кода для будущих попыток переполнения стека. -Спасибо   -  person Momin    schedule 10.06.2017
comment
Извини за это! Я понимаю, что люди привыкли смотреть на код. Я скопировал часть файла index.js в вопрос. Хотя, возможно, это не так уж и полезно.   -  person Scott Ewing    schedule 10.06.2017


Ответы (2)


Облачные функции для Firebase плохо подходят (и не поддерживаются) для длительных задач, которые могут превышать максимальное время ожидания. Ваш единственный реальный шанс использовать только облачные функции для выполнения очень тяжелых вычислительных операций — найти способ разделить работу на несколько вызовов функций, а затем объединить результаты всей этой работы в конечный продукт. Для чего-то вроде транскодирования видео это кажется очень сложной задачей.

Вместо этого рассмотрите возможность использования функции для запуска длительной задачи в App Engine или Compute Engine.

person Doug Stevenson    schedule 10.06.2017
comment
В продолжение этого, как вы думаете, имеет ли смысл запускать процесс ядра приложения, просто отправив ему HTTP-запрос? Есть ли лучший способ справиться с этим? Мне не нужно объяснять, как именно работает App Engine (вообще), поэтому любая информация, которая, по вашему мнению, будет наиболее полезной для моего случая, будет замечательной. - person Scott Ewing; 13.06.2017
comment
Облачные функции для Firebase плохо подходят (и не поддерживаются) для длительных задач, документирование этого сэкономило бы мне недели. Теперь изучаем App Engine. Спасибо - person CodeKiwi; 03.08.2017
comment
@ScottEwing Вы узнали, как запустить рабочий процесс в GAE? Столкнулись с теми же проблемами с ограничениями в облачных функциях и готовы перейти на GAE/GCE. - person Igniter; 16.10.2019
comment
Вот файл с обновленным кодом функций firebase , а здесь — файл app.js, который я использовал для GAE. Основной рабочий процесс заключался в том, что Firebase Functions отправляет http-запрос на URL-адрес процесса транскодера, который перекодирует видео, если оно существует. Некоторая угроза безопасности, когда любой может отправить запрос на перекодирование видео на сервере firebase, но не так много. Используйте этот код в сыром виде на свой страх и риск - person Scott Ewing; 19.10.2019

В качестве продолжения для случайного анонимного человека, который пытается выяснить, как пройти транскодирование видео или какие-либо другие длительные процессы, вот версия того же примера кода, который я привел, который вместо этого отправляет HTTP-запрос в процесс движка приложения Google, который перекодирует файл. На данный момент для него нет документации, но просмотр кода Firebase/functions/index.js и кода app.js может помочь вам решить вашу проблему.

https://github.com/Scew5145/GCSConvertDemo

Удачи.

person Scott Ewing    schedule 20.06.2017