繁体   English   中英

在Firebase Cloud Function中了解存储在Firebase存储中的视频的持续时间最简单的方法是什么?

[英]What is the easiest method to know the duration of a video stored in Firebase Storage in a Firebase Cloud Function?

我有一个基于触发器的云功能,该功能应查找上传到Firebase Storage的视频的时长。

我尝试使用以下npm模块: get-video-duration ,它获取url,文件本身或流。

使用我文件的公共URL不起作用,我的捕获日志:

{ Error: spawn ffprobe ENOENT
    at exports._errnoException (util.js:1020:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:197:32)
    at onErrorNT (internal/child_process.js:376:16)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'spawn ffprobe',
  path: 'ffprobe',
  spawnargs: 
   [ '-v',
     'error',
     '-show_format',
     '-show_streams',
     'https://storage.googleapis.com/adboard-dev.appspot.com/5HRuyysoMxe9Tb5vPLDbhEaHtkH2%2F-LAve5VogdAr4ZohU-DE%2FSampleVideo_1280x720_1mb.mp4?GoogleAccessId=firebase-adminsdk-3lthu@adboard-dev.iam.gserviceaccount.com&Expires=16447017600&Signature=cbhn%2BtY2%2FtvcRkvsFp1ywhHKiz%2FLfabfMk6HbD4TEGd%2Brf4njcMz1mQVf6H8nyulTBoRHIgC2uENFEPoEjtON6Um0Jb9P9jgikj6PdhS98m1sPDpTjMiFCTWk6ICjTI%2B%2BWuSVGgDX0tRuq3fADZABKaEcl3CEAI17DCVH98a40XttIDZqeqxIDu1iLi%2F8apQy44pAPJsmVR2dkYHk8Am8e7jIT1OnXG3adO34U3TNhsziPryIIpzo68QANENeieulvleic2BEi7KUhN1K8IxzJXxAfkt9RAFbdrwh%2FOpQ7zTGPRzTC3Vz2FnmKSXVtdKtmftg7BlEXrRr3D7ELJ53g%3D%3D' ],
  stdout: '',
  stderr: '',
  failed: true,
  signal: null,
  cmd: 'ffprobe -v error -show_format -show_streams https://storage.googleapis.com/adboard-dev.appspot.com/5HRuyysoMxe9Tb5vPLDbhEaHtkH2%2F-LAve5VogdAr4ZohU-DE%2FSampleVideo_1280x720_1mb.mp4?GoogleAccessId=firebase-adminsdk-3lthu@adboard-dev.iam.gserviceaccount.com&Expires=16447017600&Signature=cbhn%2BtY2%2FtvcRkvsFp1ywhHKiz%2FLfabfMk6HbD4TEGd%2Brf4njcMz1mQVf6H8nyulTBoRHIgC2uENFEPoEjtON6Um0Jb9P9jgikj6PdhS98m1sPDpTjMiFCTWk6ICjTI%2B%2BWuSVGgDX0tRuq3fADZABKaEcl3CEAI17DCVH98a40XttIDZqeqxIDu1iLi%2F8apQy44pAPJsmVR2dkYHk8Am8e7jIT1OnXG3adO34U3TNhsziPryIIpzo68QANENeieulvleic2BEi7KUhN1K8IxzJXxAfkt9RAFbdrwh%2FOpQ7zTGPRzTC3Vz2FnmKSXVtdKtmftg7BlEXrRr3D7ELJ53g%3D%3D',
  timedOut: false,
  killed: false }

下载文件然后直接传递文件也不起作用:

{ Error: spawn ffprobe ENOENT
    at exports._errnoException (util.js:1020:11)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:197:32)
    at onErrorNT (internal/child_process.js:376:16)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickDomainCallback (internal/process/next_tick.js:128:9)
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'spawn ffprobe',
  path: 'ffprobe',
  spawnargs: 
   [ '-v',
     'error',
     '-show_format',
     '-show_streams',
     '/tmp/SampleVideo_1280x720_1mb.mp4' ],
  stdout: '',
  stderr: '',
  failed: true,
  signal: null,
  cmd: 'ffprobe -v error -show_format -show_streams /tmp/SampleVideo_1280x720_1mb.mp4',
  timedOut: false,
  killed: false }

最后,我使用fs创建了一个流,然后通过了它,它给了我一个Duration Not Found! 错误:

{ AssertionError: No duration found!
    at ffprobe.then (/user_code/node_modules/get-video-duration/index.js:34:3)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)
  name: 'AssertionError',
  actual: null,
  expected: true,
  operator: '==',
  message: 'No duration found!',
  generatedMessage: false }

我的云功能代码:

exports.recordUploadedFile = functions.storage.object().onFinalize(object => {
  let fileType = object.contentType;
  if (fileType.startsWith("image/") || fileType.startsWith("video/")) {
    let dir = object.name.split("/");
    let name = dir.pop();
    let fileID = dir.pop();
    let uid = dir.pop();
    return admin
      .storage()
      .bucket()
      .file(object.name)
      .getSignedUrl({
        action: "read",
        expires: "03-09-2491"
      })
      .then(urls => {
        let file = {
          name: name,
          link: urls[0],
          type: fileType,
          duration: 0
        }
        if (fileType.startsWith("video/")) {
          const tempFilePath = path.join(os.tmpdir(), name);
          return admin.storage().bucket().file(object.name).download({
            destination: tempFilePath
          }).then(() => {
            const stream = fs.createReadStream(tempFilePath);
            return getDuration(stream).then(duration => {
              console.log(duration);
              file.duration = duration;
              return setFile(file, uid, fileID);
            }).catch(error => {
              console.log(error);
            });
          });
        } else {
          return setFile(file, uid, fileID);
        }
      });
  } else {
    return admin.storage().bucket().file(object.name).delete();
  }
});

我尝试了多个大小不一的视频文件,但都无法正常工作。

如果有更好的解决方案来了解视频时长,我也很想知道。

谢谢。

尝试使用名为fluent-ffmpeg的库: https : //github.com/fluent-ffmpeg/node-fluent-ffmpeg

var ffmpeg = require('fluent-ffmpeg');

ffmpeg.ffprobe(tempFilePath, function(err, metadata) {
  //console.dir(metadata); // all metadata
  console.log(metadata.format.duration);
});

我最终使用了faruk建议的库:fluent-mmpeg,但是要使其在Firebase上运行,您需要执行以下操作:

  1. 您需要使用bluebird来像这样“承诺” fluent-mmpeg: const ffprobe = Promise.promisify(require("fluent-ffmpeg").ffprobe);
  2. 您需要安装ffmpeg和ffprobe的静态二进制文件,因此将它们包含在pacakge npm i --save @ffmpeg-installer/ffmpeg, @ffprobe-installer/ffprobe
  3. 最后,设置路径: const ffmpegPath = require("@ffmpeg-installer/ffmpeg").path; const ffprobePath = require("@ffprobe-installer/ffprobe").path; ffmpeg.setFfmpegPath(ffmpegPath); ffmpeg.setFfprobePath(ffprobePath); const ffmpegPath = require("@ffmpeg-installer/ffmpeg").path; const ffprobePath = require("@ffprobe-installer/ffprobe").path; ffmpeg.setFfmpegPath(ffmpegPath); ffmpeg.setFfprobePath(ffprobePath);

这是一些经过测试的有效代码:

os = require('os');
path = require('path');
gcs = require('@google-cloud/storage')();
const filePath = object.name;
const const fileBucket = object.bucket;
var Promise = require("bluebird");
var ffmpeg = Promise.promisify(require("fluent-ffmpeg"));
var ffmpegPath = require("@ffmpeg-installer/ffmpeg").path;
var ffprobePath = require("@ffprobe-installer/ffprobe").path;
ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg.setFfprobePath(ffprobePath);
const fileName = filePath.split('/').pop();
const tempFilePath = path.join(os.tmpdir(), fileName);
const bucket = gcs.bucket(fileBucket);

bucket.file(filePath).download({
  destination: tempFilePath,
  validation: false
}).then(function() {

ffmpeg.ffprobe(tempFilePath, function(err, metadata) {
if (err) {
    reject(err);
} else {
if (metadata) {
  console.log(metadata.format.duration);
  console.log(metadata.streams[0].width);
  console.log(metadata.streams[0].height);
  console.log(metadata);
  resolve();
} else {
    reject();
}
}
})

}).catch(function(error) {
    console.error(error); reject();
})

从package.json中:

"@ffmpeg-installer/ffmpeg": "^1.0.17",
"@ffprobe-installer/ffprobe": "^1.0.9",
"@google-cloud/storage": "^1.1.1",
"bluebird": "^3.5.3",
"fluent-ffmpeg": "^2.1.2"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM