你能在Firebase云函数中调用FFMPEG吗

你能在Firebase云函数中调用FFMPEG吗,firebase,ffmpeg,google-cloud-functions,Firebase,Ffmpeg,Google Cloud Functions,根据Firebase云函数文档,您可以在云函数中利用ImageMagick: 是否可以执行类似的操作,但调用FFMPEG而不是ImageMagick?虽然缩略图图像很棒,但我也希望能够将传入的图像附加到存储在Firebase存储上的视频文件中。ffmpeg没有预先安装(基本上只是ImageMagick);要查看安装的内容,请查看此处的Dockerfile: 但是,当您使用gcloud beta functions deploy上载代码时,您可以上载任意二进制文件,因为当前目录中的所有内容(除了节

根据Firebase云函数文档,您可以在云函数中利用ImageMagick:


是否可以执行类似的操作,但调用FFMPEG而不是ImageMagick?虽然缩略图图像很棒,但我也希望能够将传入的图像附加到存储在Firebase存储上的视频文件中。

ffmpeg
没有预先安装(基本上只是ImageMagick);要查看安装的内容,请查看此处的Dockerfile:

但是,当您使用
gcloud beta functions deploy
上载代码时,您可以上载任意二进制文件,因为当前目录中的所有内容(除了
节点模块
)都已上载

注意:您只能在
/tmp/
上进行磁盘写入访问

选项1:使用ffmpeg静态npm模块
ffmpeg static
是一个npm模块,它在
npm安装过程中基于当前系统构建正确的ffmpeg二进制文件。由于云函数在云中构建代码,它将构建正确的ffmpeg二进制文件

您可以在中看到它的作用

const ffmpeg=require('fluent-ffmpeg');
const ffmpeg_static=require('ffmpeg-static');
var cmd=ffmpeg('/tmp/video.avi')
.setFfmpegPath(ffmpeg_static.path)
.视频比特率(1024)
.videoCodec(“divx”)
.format('avi'))
.on('end',()=>{
// ...
})
.on('error',err=>{
控制台错误(err);
})
.save('/tmp/file out.avi')使用库


虽然从技术上讲,您可以在Firebase函数实例上运行FFMPEG,但很快就会达到较小的配额限制

根据,您可以使用函数触发对GCP更强大的应用程序引擎或计算引擎服务的请求。appengine进程可以从同一个bucket抓取文件,处理转码,并将完成的文件上传回bucket。如果你在链接上查看其他答案,一位用户发布了一份示例回购协议

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for t`he specific language governing permissions and
 * limitations under the License.
 */
'use strict';

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();
const path = require('path');
const os = require('os');
const fs = require('fs');
const ffmpeg = require('fluent-ffmpeg');
const ffmpeg_static = require('ffmpeg-static');

/**
 * When an audio is uploaded in the Storage bucket We generate a mono channel audio automatically using
 * node-fluent-ffmpeg.
 */
exports.generateMonoAudio = functions.storage.object().onChange(event => {
  const object = event.data; // The Storage object.

  const fileBucket = object.bucket; // The Storage bucket that contains the file.
  const filePath = object.name; // File path in the bucket.
  const contentType = object.contentType; // File content type.
  const resourceState = object.resourceState; // The resourceState is 'exists' or 'not_exists' (for file/folder deletions).
  const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.

  // Exit if this is triggered on a file that is not an audio.
  if (!contentType.startsWith('audio/')) {
    console.log('This is not an audio.');
    return;
  }

  // Get the file name.
  const fileName = path.basename(filePath);
  // Exit if the audio is already converted.
  if (fileName.endsWith('_output.flac')) {
    console.log('Already a converted audio.');
    return;
  }

  // Exit if this is a move or deletion event.
  if (resourceState === 'not_exists') {
    console.log('This is a deletion event.');
    return;
  }

  // Exit if file exists but is not new and is only being triggered
  // because of a metadata change.
  if (resourceState === 'exists' && metageneration > 1) {
    console.log('This is a metadata change event.');
    return;
  }

  // Download file from bucket.
  const bucket = gcs.bucket(fileBucket);
  const tempFilePath = path.join(os.tmpdir(), fileName);
  // We add a '_output.flac' suffix to target audio file name. That's where we'll upload the converted audio.
  const targetTempFileName = fileName.replace(/\.[^/.]+$/, "") + '_output.flac';
  const targetTempFilePath = path.join(os.tmpdir(), targetTempFileName);
  const targetStorageFilePath = path.join(path.dirname(filePath), targetTempFileName);

  return bucket.file(filePath).download({
    destination: tempFilePath
  }).then(() => {
    console.log('Audio downloaded locally to', tempFilePath);
    // Convert the audio to mono channel using FFMPEG.
    const command = ffmpeg(tempFilePath)
      .setFfmpegPath(ffmpeg_static.path)    
      .audioChannels(1)
      .audioFrequency(16000)
      .format('flac')
      .on('error', (err) => {
        console.log('An error occurred: ' + err.message);
      })
      .on('end', () => {
        console.log('Output audio created at', targetTempFilePath);

        // Uploading the audio.
        return bucket.upload(targetTempFilePath, {destination: targetStorageFilePath}).then(() => {
          console.log('Output audio uploaded to', targetStorageFilePath);

          // Once the audio has been uploaded delete the local file to free up disk space.     
          fs.unlinkSync(tempFilePath);
          fs.unlinkSync(targetTempFilePath);

          console.log('Temporary files removed.', targetTempFilePath);
        });
      })
      .save(targetTempFilePath);
  });
});

实际上,FFMPEG处理的音频/视频文件通常超过(10MB上传)的容量


您需要运行。

ffmpeg
现在包含在云函数环境中,因此可以直接使用:

spawn(
  'ffmpeg',
  ['-i', 'video.mp4'] 
)

已安装软件包的完整列表:

请记住,您的磁盘空间和内存有限。事实上,临时磁盘是存储在内存中的,所以如果你有一个大的视频,你可能很容易耗尽内存。我如何在cloud firebase函数中引用文件,我的意思是,在FFMPEG命令中写入什么路径来引用firebase存储中的文件?@OmarHossamEldin作为功能一部分上载的所有内容都存储在服务器上的
/user\u code/
目录中。这是一个救命稻草-谢谢!!让参考文献访问Github页面真是帮了大忙。不过,这只是一个附带说明,我使用的是
fluent ffmpeg
npm包,需要将ffmpeg路径作为ENV变量添加到Docker文件中的二进制文件中:
ENV path=“/usr/src/app/node\u modules/ffmpeg static/bin/linux/x64:${path}”
ffmpeg
现在包含在云函数环境中请注意:当前版本的ffmpeg static直接返回路径,因此您需要直接调用
.setFfmpegPath(ffmpeg\u static)
,而不使用
.path
谢谢,只是想知道您是否见过任何带有代码模板的回购协议,您可以基于这些模板来完成这些任务?具体如何在GAE中触发工作流?请注意,当前版本的ffmpeg static直接返回路径,因此需要直接调用
.setFfmpegPath(ffmpeg\u static)
,而不调用
.path
spawn(
  'ffmpeg',
  ['-i', 'video.mp4'] 
)