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