title: What is the easiest method to know the duration of a video stored in Firebase Storage in a Firebase Cloud Function?
body: <p>I have a trigger-based cloud function that should find the duration of a video uploaded to Firebase Storage.</p>
  
  <p>I tried using the following npm module:  <a href="https://www.npmjs.com/package/get-video-duration" rel="nofollow noreferrer"><code>get-video-duration</code></a> which takes url, the file itself, or stream.</p>
  
  <p>Using the public url of my file doesn't work, my catch logs:</p>
  
  <pre><code>{ 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&amp;Expires=16447017600&amp;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&amp;Expires=16447017600&amp;Signature=cbhn%2BtY2%2FtvcRkvsFp1ywhHKiz%2FLfabfMk6HbD4TEGd%2Brf4njcMz1mQVf6H8nyulTBoRHIgC2uENFEPoEjtON6Um0Jb9P9jgikj6PdhS98m1sPDpTjMiFCTWk6ICjTI%2B%2BWuSVGgDX0tRuq3fADZABKaEcl3CEAI17DCVH98a40XttIDZqeqxIDu1iLi%2F8apQy44pAPJsmVR2dkYHk8Am8e7jIT1OnXG3adO34U3TNhsziPryIIpzo68QANENeieulvleic2BEi7KUhN1K8IxzJXxAfkt9RAFbdrwh%2FOpQ7zTGPRzTC3Vz2FnmKSXVtdKtmftg7BlEXrRr3D7ELJ53g%3D%3D',
    timedOut: false,
    killed: false }
  </code></pre>
  
  <p>Downloading the file then passing it directly don't work too:</p>
  
  <pre><code>{ 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 }
  </code></pre>
  
  <p>Finally, I created a stream using fs then I passed it, and it it gave me a <code>Duration Not Found!</code> error:</p>
  
  <pre><code>{ 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 }
  </code></pre>
  
  <p>My cloud function code:</p>
  
  <pre><code>exports.recordUploadedFile = functions.storage.object().onFinalize(object =&gt; {
    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 =&gt; {
          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(() =&gt; {
              const stream = fs.createReadStream(tempFilePath);
              return getDuration(stream).then(duration =&gt; {
                console.log(duration);
                file.duration = duration;
                return setFile(file, uid, fileID);
              }).catch(error =&gt; {
                console.log(error);
              });
            });
          } else {
            return setFile(file, uid, fileID);
          }
        });
    } else {
      return admin.storage().bucket().file(object.name).delete();
    }
  });
  </code></pre>
  
  <p>I tried multiple video files of multiple sizes, and none of them work.</p>
  
  <p>If there is a better solution to know the video duration, I would love to know it too.</p>
  
  <p>Thank you.</p>