Javascript 了解Firebase云函数中Firebase存储中存储的视频持续时间的最简单方法是什么?

Javascript 了解Firebase云函数中Firebase存储中存储的视频持续时间的最简单方法是什么?,javascript,node.js,firebase,google-cloud-functions,firebase-storage,Javascript,Node.js,Firebase,Google Cloud Functions,Firebase Storage,我有一个基于触发器的云函数,可以找到上传到Firebase存储的视频的持续时间 我尝试使用以下npm模块:它接受url、文件本身或流 使用我的文件的公共url无效,我的捕获日志: { Error: spawn ffprobe ENOENT at exports._errnoException (util.js:1020:11) at Process.ChildProcess._handle.onexit (internal/child_process.js:197:32)

我有一个基于触发器的云函数,可以找到上传到Firebase存储的视频的持续时间

我尝试使用以下npm模块:它接受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创建了一个流,然后我传递了它,它给了我一个
未找到的持续时间错误:

{ 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的库:

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

  • 您需要使用bluebird“promisify”fluent mmpeg,如下所示:
    const ffprobe=Promise.promisify(require(“fluent ffmpeg”).ffprobe)
  • 您需要同时安装ffmpeg和ffprobe的静态二进制文件,因此请将它们包含在您的pacakge
    npm i--save@ffmpeg installer/ffmpeg,@ffprobe installer/ffprobe
  • 最后,设置路径:
    const ffmpegPath=require(“@ffmpeg安装程序/ffmpeg”).path;
    const ffprobePath=require(“@ffprobe安装程序/ffprobe”).path;
    setFfmpegPath(ffmpegPath);
    ffmpeg.setFfprobePath(ffprobePath)
  • 下面是一些经过测试和运行的代码:

    从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"
    

    我试过了,但我发现:
    TypeError:Cannot readed属性'format'of undefined at/user\u code/ready/recordUploadedFile.js:38:35
    元数据似乎未定义,你能不能控制台
    err
    err
    也为空,但原因是firebase只处理异步函数,因此,我使用了
    bluebird
    来演示ffprobe函数。但是,当我发现错误时,我得到:
    error:not find ffprobe at/user\u code/node\u modules/fluent ffmpeg/lib/ffprobe.js:145:31
    我安装了ffmpeg、ffprobe和fluent mpeg。而且,它们都在我的
    package.js
    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();
    })
    
    "@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"