我目前正在寻求有关云存储上传触发的云功能的帮助。它检查文件是否是视频,如果是,我们通过 ffmpeg 处理此视频以提取单个帧以稍后用于海报图像。
除了我将图像上传回云存储不起作用之外,一切似乎都有效。在我的云功能所在的这一点上,它根本不会产生任何错误,所以我不知道为什么将图像上传到云存储不起作用。如果任何有经验的人可以在下面查看我的云功能并提供一些关于它不起作用的原因的见解,我将不胜感激。如果可能的话,请指教!!谢谢!!!!^_^
注意:代码片段下方提供了云函数日志的屏幕截图
const admin = require('firebase-admin'); // Firebase Admin SDK
const functions = require('firebase-functions'); // Firebase Cloud Functions
const gcs = require('@google-cloud/storage')(); // Cloud Storage Node.js Client
const path = require('path'); // Node.js file and directory utility
const os = require('os'); // Node.js operating system-related utility
const fs = require('fs'); // Node.js file system API
const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('@ffmpeg-installer/ffmpeg').path;
const ffprobePath = require('@ffprobe-installer/ffprobe').path;
// Initialize Firebase Admin
admin.initializeApp(functions.config().firebase);
// Listen for changes in Cloud Storage bucket
exports.storageFunction = functions.storage.object()
.onChange((event) => {
const file = event.data; // The Storage object.
const fileBucket = file.bucket; // The Storage bucket that contains the file.
const filePath = file.name; // File path in the bucket.
const fileName = path.basename(filePath); // Get the file name.
const fileType = file.contentType; // File content type.
if (!fileType.startsWith('video/')) {
return;
}
const bucket = gcs.bucket(fileBucket);
const tempFilePath = path.join(os.tmpdir(), fileName);
const tempFolderPath = os.tmpdir();
// Download video to temp directory
return bucket.file(filePath).download({
destination: tempFilePath
}).then(() => {
console.log('Video downloaded locally to', tempFilePath);
// Generate screenshot from video
ffmpeg(tempFilePath)
.setFfmpegPath(ffmpegPath)
.setFfprobePath(ffprobePath)
.on('filenames', (filenames) => {
console.log(`Will generate ${filenames}`);
})
.on('error', (err) => {
console.log(`An error occurred: ${err.message}`);
})
.on('end', () => {
console.log(`Output image created at ${tempFilePath}`);
const targetTempFileName = `${fileName}.png`;
const targetFilePath = path.join(path.dirname(filePath), targetTempFileName);
console.log(targetTempFileName);
console.log(targetFilePath);
// Uploading the image.
return bucket.upload(tempFilePath, { destination: targetFilePath })
.then(() => {
console.log('Output image uploaded to', filePath);
})
.catch((err) => {
console.log(err.message);
});
})
.screenshots({
count: 1,
folder: tempFolderPath
});
});
});
云功能日志
看起来您正在尝试从 ffmpeg 回调 API 返回一个承诺:
.on('end', () => {
return bucket.upload(tempFilePath, { destination: targetFilePath })
.then(...)
})
我不知道 ffmpeg API,但我几乎可以肯定这不会导致函数等待上传完成。 相反,您需要直接从函数返回一个承诺,该承诺仅在所有异步工作完成后解析。
如果最后一项工作在回调中,并且您需要等待,则可以将整个工作包装到新的承诺中,并在正确的时间手动解决它。 在伪代码中:
return new Promise((resolve, reject) => {
// ffmpeg stuff here...
.on('end', () => {
// the last bit of work here...
bucket.upload(...)
.then(() => { resolve() })
})
})
请注意如何调用新承诺提供的 resolve
方法,以指示何时应解析该承诺本身。