从云功能触发器将图像上载到云存储

时间:2018-01-24 20:33:32

标签: javascript firebase google-cloud-storage google-cloud-functions

我目前正在寻求云存储上传触发的云功能方面的帮助。它检查文件是否为视频,如果是,我们通过ffmpeg处理此视频以提取稍后用于海报图像的单个帧。

除了我将图像上传回云存储系统不起作用外,这一切似乎都有效。此时我的云功能根本不会产生任何错误,所以我不知道为什么将图像上传到云存储不起作用。如果有经验的人可以在下面查看我的云功能并提供一些有关它无法正常工作的信息,我将不胜感激。请尽可能的建议!!谢谢!!!! ^ _ ^

注意:代码段

下方提供了Cloud Function Log的屏幕截图
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
        });
    });
});

Cloud Function Log

1 个答案:

答案 0 :(得分:3)

看起来你正试图从ffmpeg回调API返回一个承诺:

.on('end', () => {
   return bucket.upload(tempFilePath, { destination: targetFilePath })
   .then(...)
})

我不知道ffmpeg API,但我几乎肯定不会导致该函数等待上传完成。相反,您需要return a promise from directly from your function仅在所有异步工作完成后才能解析。

如果最后一项工作在回调中,并且您需要等待,那么您可以将整个事物包装到新的承诺中并在适当的时候手动解决它。在伪代码中:

return new Promise((resolve, reject) => {
    // ffmpeg stuff here...
    .on('end', () => {
        // the last bit of work here...
        bucket.upload(...)
        .then(() => { resolve() })
    })
})

注意如何调用新promise提供的resolve方法来指示该promise何时解决。