aboutsummaryrefslogblamecommitdiffhomepage
path: root/server/lib/videos.js
blob: a74c77dc4c98b8bdf37cb80c7d67a4b03275030f (plain) (tree)
1
2
3
4
5
6
7
8
9

            

                                
                                       

                                 
                                 
 
                                                      
                                           
                                         
                                          
                                               
 
                                                                                      
                                                                                             
 
                
                                             
                                         
                                     
                               
                                             

                                                     



                                  






















                                                                              

                                                
                                                                 

                                 
                                             


    

                                                      





                                                               
                                

                                



                                     
                                       

 
                                                     

                                                         













                                                          
                                                     






                                                                
                                    

           
                            

              
                          












                                                         










                                                           
                                               




                                                            
                                                           





                                                       
                          







                                                                              



                                                                              
                         
 
                                                     
                                                   

                                                                 
 


                                                                                      






                                         
                                   

                              
         
                                 
 
                          





                                 
                                


    

                                                                                     
 
'use strict'

const async = require('async')
const config = require('config')
const ffmpeg = require('fluent-ffmpeg')
const fs = require('fs')
const map = require('lodash/map')
const pathUtils = require('path')

const constants = require('../initializers/constants')
const logger = require('../helpers/logger')
const utils = require('../helpers/utils')
const Videos = require('../models/videos')
const webtorrent = require('../lib/webtorrent')

const uploadDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads'))
const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails'))

const videos = {
  convertVideoToRemote: convertVideoToRemote,
  createRemoteVideos: createRemoteVideos,
  getVideoDuration: getVideoDuration,
  getVideoState: getVideoState,
  createVideoThumbnail: createVideoThumbnail,
  removeVideosDataFromDisk: removeVideosDataFromDisk,
  removeRemoteVideos: removeRemoteVideos,
  seed: seed,
  seedAllExisting: seedAllExisting
}

function convertVideoToRemote (video, callback) {
  fs.readFile(thumbnailsDir + video.thumbnail, function (err, thumbnailData) {
    if (err) {
      logger.error('Cannot read the thumbnail of the video')
      return callback(err)
    }

    const remoteVideo = {
      name: video.name,
      description: video.description,
      magnetUri: video.magnetUri,
      author: video.author,
      duration: video.duration,
      thumbnailBase64: new Buffer(thumbnailData).toString('base64'),
      tags: video.tags,
      createdDate: video.createdDate,
      podUrl: video.podUrl
    }

    return callback(null, remoteVideo)
  })
}

function createRemoteVideos (videos, callback) {
  // Create the remote videos from the new pod
  createRemoteVideoObjects(videos, function (err, remoteVideos) {
    if (err) return callback(err)

    Videos.addRemotes(remoteVideos, callback)
  })
}

function getVideoDuration (videoPath, callback) {
  ffmpeg.ffprobe(videoPath, function (err, metadata) {
    if (err) return callback(err)

    return callback(null, Math.floor(metadata.format.duration))
  })
}

function getVideoState (video) {
  const exist = (video !== null)
  let owned = false
  if (exist === true) {
    owned = (video.namePath !== null)
  }

  return { exist: exist, owned: owned }
}

function createVideoThumbnail (videoPath, callback) {
  const filename = pathUtils.basename(videoPath) + '.jpg'
  ffmpeg(videoPath)
    .on('error', callback)
    .on('end', function () {
      callback(null, filename)
    })
    .thumbnail({
      count: 1,
      folder: thumbnailsDir,
      size: constants.THUMBNAILS_SIZE,
      filename: filename
    })
}

// Remove video datas from disk (video file, thumbnail...)
function removeVideosDataFromDisk (videos, callback) {
  async.each(videos, function (video, callbackEach) {
    fs.unlink(thumbnailsDir + video.thumbnail, function (err) {
      if (err) logger.error('Cannot remove the video thumbnail')

      if (getVideoState(video).owned === true) {
        fs.unlink(uploadDir + video.namePath, function (err) {
          if (err) {
            logger.error('Cannot remove this video file.')
            return callbackEach(err)
          }

          callbackEach(null)
        })
      } else {
        callbackEach(null)
      }
    })
  }, callback)
}

function removeRemoteVideos (videos, callback) {
  Videos.removeByIds(map(videos, '_id'), function (err) {
    if (err) return callback(err)

    removeVideosDataFromDisk(videos, callback)
  })
}

function seed (path, callback) {
  logger.info('Seeding %s...', path)

  webtorrent.seed(path, function (torrent) {
    logger.info('%s seeded (%s).', path, torrent.magnetURI)

    return callback(null, torrent)
  })
}

function seedAllExisting (callback) {
  Videos.listOwned(function (err, videosList) {
    if (err) {
      logger.error('Cannot get list of the videos to seed.')
      return callback(err)
    }

    async.each(videosList, function (video, callbackEach) {
      seed(uploadDir + video.namePath, function (err) {
        if (err) {
          logger.error('Cannot seed this video.')
          return callback(err)
        }

        callbackEach(null)
      })
    }, callback)
  })
}

// ---------------------------------------------------------------------------

module.exports = videos

// ---------------------------------------------------------------------------

function createRemoteVideoObjects (videos, callback) {
  const remoteVideos = []

  async.each(videos, function (video, callbackEach) {
    // Creating the thumbnail for this remote video
    utils.generateRandomString(16, function (err, randomString) {
      if (err) return callbackEach(err)

      const thumbnailName = randomString + '.jpg'
      createThumbnailFromBase64(thumbnailName, video.thumbnailBase64, function (err) {
        if (err) return callbackEach(err)

        const params = {
          name: video.name,
          description: video.description,
          magnetUri: video.magnetUri,
          podUrl: video.podUrl,
          duration: video.duration,
          thumbnail: thumbnailName,
          tags: video.tags,
          author: video.author
        }
        remoteVideos.push(params)

        callbackEach(null)
      })
    })
  },
  function (err) {
    if (err) return callback(err)

    callback(null, remoteVideos)
  })
}

function createThumbnailFromBase64 (thumbnailName, data, callback) {
  fs.writeFile(thumbnailsDir + thumbnailName, data, { encoding: 'base64' }, callback)
}