Video duration support (server)
authorChocobozzz <florian.bigard@gmail.com>
Tue, 3 May 2016 20:41:46 +0000 (22:41 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Tue, 3 May 2016 20:41:46 +0000 (22:41 +0200)
README.md
package.json
server/controllers/api/v1/videos.js
server/helpers/customValidators.js
server/models/videos.js
server/tests/api/multiplePods.js
server/tests/api/singlePod.js

index 37bee455dce2f732d3039bd6bbb5a6d375f35b3c..e2b52f6fdff8e017bf7e1a69215ba89e9d93db56 100644 (file)
--- a/README.md
+++ b/README.md
@@ -64,13 +64,15 @@ Thanks to [WebTorrent](https://github.com/feross/webtorrent), we can make P2P (t
   * **NodeJS >= 4.2**
   * OpenSSL (cli)
   * MongoDB
-  * xvfb-run libgtk2.0-0 libgconf-2-4 libnss3 libasound2 libxtst6 libxss1 libnotify-bin (for electron)
+  * ffmpeg xvfb-run libgtk2.0-0 libgconf-2-4 libnss3 libasound2 libxtst6 libxss1 libnotify-bin (for electron)
 
 #### Debian
 
-Install NodeJS 4.2: [https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions)
+  * Install NodeJS 4.2: [https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions)
+  * Add jessie backports to your *source.list*: http://backports.debian.org/Instructions/
 
-    # apt-get install mongodb openssl xvfb curl sudo git build-essential libgtk2.0-0 libgconf-2-4 libnss3 libasound2 libxtst6 libxss1 libnotify-bin
+    # apt-get update
+    # apt-get install ffmpeg mongodb openssl xvfb curl sudo git build-essential libgtk2.0-0 libgconf-2-4 libnss3 libasound2 libxtst6 libxss1 libnotify-bin
     # npm install -g electron-prebuilt
 
 #### Other distribution... (PR welcome)
index 85b383a69c6409b5c1ee404434ea4858f31b6d65..746a0d9688554e0ed13a98097f995a3d990aa5bc 100644 (file)
@@ -52,6 +52,7 @@
     "express": "^4.12.4",
     "express-oauth-server": "https://github.com/Chocobozzz/express-oauth-server",
     "express-validator": "^2.11.0",
+    "fluent-ffmpeg": "^2.1.0",
     "js-yaml": "^3.5.4",
     "lodash": "^4.11.1",
     "mkdirp": "^0.5.1",
index d25ca95f72c7b2c37646279df85b5c66f7057a7d..e696289619f9ac4f75a1286a88ff5fb507f466e2 100644 (file)
@@ -3,6 +3,7 @@
 const config = require('config')
 const crypto = require('crypto')
 const express = require('express')
+const ffmpeg = require('fluent-ffmpeg')
 const multer = require('multer')
 
 const logger = require('../../../helpers/logger')
@@ -60,26 +61,37 @@ function addVideo (req, res, next) {
       return next(err)
     }
 
-    const video_data = {
-      name: video_infos.name,
-      namePath: video_file.filename,
-      description: video_infos.description,
-      magnetUri: torrent.magnetURI,
-      author: res.locals.oauth.token.user.username
-    }
-
-    Videos.add(video_data, function (err) {
+    ffmpeg.ffprobe(video_file.path, function (err, metadata) {
       if (err) {
-        // TODO unseed the video
-        logger.error('Cannot insert this video in the database.')
+        // TODO: unseed the video
+        logger.error('Cannot retrieve metadata of the file')
         return next(err)
       }
 
-      // Now we'll add the video's meta data to our friends
-      friends.addVideoToFriends(video_data)
+      const duration = Math.floor(metadata.format.duration)
 
-      // TODO : include Location of the new video -> 201
-      res.type('json').status(204).end()
+      const video_data = {
+        name: video_infos.name,
+        namePath: video_file.filename,
+        description: video_infos.description,
+        magnetUri: torrent.magnetURI,
+        author: res.locals.oauth.token.user.username,
+        duration: duration
+      }
+
+      Videos.add(video_data, function (err) {
+        if (err) {
+          // TODO unseed the video
+          logger.error('Cannot insert this video in the database.')
+          return next(err)
+        }
+
+        // Now we'll add the video's meta data to our friends
+        friends.addVideoToFriends(video_data)
+
+        // TODO : include Location of the new video -> 201
+        res.type('json').status(204).end()
+      })
     })
   })
 }
@@ -144,7 +156,8 @@ function getFormatedVideo (video_obj) {
     podUrl: video_obj.podUrl,
     isLocal: videos.getVideoState(video_obj).owned,
     magnetUri: video_obj.magnetUri,
-    author: video_obj.author
+    author: video_obj.author,
+    duration: video_obj.duration
   }
 
   return formated_video
index a5ae32780c09b126075fe8452e6f00716b1e992d..0fbabab52da391e634b45a4ffa07979bcad91d2b 100644 (file)
@@ -13,7 +13,8 @@ function eachIsRemoteVideosAddValid (values) {
     return validator.isLength(val.name, 1, 50) &&
       validator.isLength(val.description, 1, 50) &&
       validator.isLength(val.magnetUri, 10) &&
-      validator.isURL(val.podUrl)
+      validator.isURL(val.podUrl) &&
+      !isNaN(val.duration)
   })
 }
 
index 13ef2295a6276e1e40e599d076fc3c3f030ea5a5..e02158be78a3d3c3b50b1522c2cc06d5e11cde81 100644 (file)
@@ -22,7 +22,8 @@ const videosSchema = mongoose.Schema({
   description: String,
   magnetUri: String,
   podUrl: String,
-  author: String
+  author: String,
+  duration: Number
 })
 const VideosDB = mongoose.model('videos', videosSchema)
 
@@ -72,7 +73,8 @@ function addRemotes (videos, callback) {
       namePath: null,
       description: video.description,
       magnetUri: video.magnetUri,
-      podUrl: video.podUrl
+      podUrl: video.podUrl,
+      duration: video.duration
     }
 
     to_add.push(params)
index ba4ce70c91d6c33eba5cc526e8951bff671ae8a5..adc99f7145a4860822933f72e76b1153680483bb 100644 (file)
@@ -95,6 +95,7 @@ describe('Test multiple pods', function () {
               expect(video.description).to.equal('my super description for pod 1')
               expect(video.podUrl).to.equal('http://localhost:9001')
               expect(video.magnetUri).to.exist
+              expect(video.duration).to.equal(10)
 
               if (server.url !== 'http://localhost:9001') {
                 expect(video.isLocal).to.be.false
@@ -144,6 +145,7 @@ describe('Test multiple pods', function () {
               expect(video.description).to.equal('my super description for pod 2')
               expect(video.podUrl).to.equal('http://localhost:9002')
               expect(video.magnetUri).to.exist
+              expect(video.duration).to.equal(5)
 
               if (server.url !== 'http://localhost:9002') {
                 expect(video.isLocal).to.be.false
@@ -190,17 +192,20 @@ describe('Test multiple pods', function () {
               const videos = res.body
               expect(videos).to.be.an('array')
               expect(videos.length).to.equal(4)
+
               const video1 = videos[2]
               expect(video1.name).to.equal('my super name for pod 3')
               expect(video1.description).to.equal('my super description for pod 3')
               expect(video1.podUrl).to.equal('http://localhost:9003')
               expect(video1.magnetUri).to.exist
+              expect(video1.duration).to.equal(5)
 
               const video2 = videos[3]
               expect(video2.name).to.equal('my super name for pod 3-2')
               expect(video2.description).to.equal('my super description for pod 3-2')
               expect(video2.podUrl).to.equal('http://localhost:9003')
               expect(video2.magnetUri).to.exist
+              expect(video2.duration).to.equal(5)
 
               if (server.url !== 'http://localhost:9003') {
                 expect(video1.isLocal).to.be.false
index efd8a64bc7fd4e94708c2754fb36b056a9eb660b..e2999530eab334b5f5918ccc404ea5502467ac23 100644 (file)
@@ -4,6 +4,7 @@ const async = require('async')
 const chai = require('chai')
 const expect = chai.expect
 const fs = require('fs')
+const keyBy = require('lodash/keyBy')
 const pathUtils = require('path')
 
 const webtorrent = require(pathUtils.join(__dirname, '../../lib/webtorrent'))
@@ -165,6 +166,37 @@ describe('Test a single pod', function () {
     })
   })
 
+  it('Should upload 6 videos', function (done) {
+    this.timeout(25000)
+    const videos = [
+      'video_short.mp4', 'video_short.ogv', 'video_short.webm',
+      'video_short1.webm', 'video_short2.webm', 'video_short3.webm'
+    ]
+    async.each(videos, function (video, callback_each) {
+      utils.uploadVideo(server.url, server.access_token, video + ' name', video + ' description', video, callback_each)
+    }, done)
+  })
+
+  it('Should have the correct durations', function (done) {
+    utils.getVideosList(server.url, function (err, res) {
+      if (err) throw err
+
+      const videos = res.body
+      expect(videos).to.be.an('array')
+      expect(videos.length).to.equal(6)
+
+      const videos_by_name = keyBy(videos, 'name')
+      expect(videos_by_name['video_short.mp4 name'].duration).to.equal(5)
+      expect(videos_by_name['video_short.ogv name'].duration).to.equal(5)
+      expect(videos_by_name['video_short.webm name'].duration).to.equal(5)
+      expect(videos_by_name['video_short1.webm name'].duration).to.equal(10)
+      expect(videos_by_name['video_short2.webm name'].duration).to.equal(5)
+      expect(videos_by_name['video_short3.webm name'].duration).to.equal(5)
+
+      done()
+    })
+  })
+
   after(function (done) {
     process.kill(-server.app.pid)
     process.kill(-webtorrent.app.pid)