3 const async = require('async')
4 const config = require('config')
5 const ffmpeg = require('fluent-ffmpeg')
6 const fs = require('fs')
7 const map = require('lodash/map')
8 const pathUtils = require('path')
10 const constants = require('../initializers/constants')
11 const logger = require('../helpers/logger')
12 const utils = require('../helpers/utils')
13 const Videos = require('../models/videos')
14 const webtorrent = require('../lib/webtorrent')
16 const uploadDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads'))
17 const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails'))
20 createRemoteVideos: createRemoteVideos,
21 getVideoDuration: getVideoDuration,
22 getVideoState: getVideoState,
23 getVideoThumbnail: getVideoThumbnail,
24 removeVideosDataFromDisk: removeVideosDataFromDisk,
25 removeRemoteVideos: removeRemoteVideos,
27 seedAllExisting: seedAllExisting
30 function createRemoteVideos (videos, callback) {
31 // Create the remote videos from the new pod
32 createRemoteVideoObjects(videos, function (err, remote_videos) {
33 if (err) return callback(err)
35 Videos.addRemotes(remote_videos, callback)
39 function getVideoDuration (video_path, callback) {
40 ffmpeg.ffprobe(video_path, function (err, metadata) {
41 if (err) return callback(err)
43 return callback(null, Math.floor(metadata.format.duration))
47 function getVideoState (video) {
48 const exist = (video !== null)
51 owned = (video.namePath !== null)
54 return { exist: exist, owned: owned }
57 function getVideoThumbnail (video_path, callback) {
58 const filename = pathUtils.basename(video_path) + '.jpg'
60 .on('error', callback)
61 .on('end', function () {
62 callback(null, filename)
66 folder: thumbnailsDir,
67 size: constants.THUMBNAILS_SIZE,
72 // Remove video datas from disk (video file, thumbnail...)
73 function removeVideosDataFromDisk (videos, callback) {
74 async.each(videos, function (video, callback_each) {
75 fs.unlink(thumbnailsDir + video.thumbnail, function (err) {
76 if (err) logger.error('Cannot remove the video thumbnail')
78 if (getVideoState(video).owned === true) {
79 fs.unlink(uploadDir + video.namePath, function (err) {
81 logger.error('Cannot remove this video file.')
82 return callback_each(err)
94 function removeRemoteVideos (videos, callback) {
95 Videos.removeByIds(map(videos, '_id'), function (err) {
96 if (err) return callback(err)
98 removeVideosDataFromDisk(videos, callback)
102 function seed (path, callback) {
103 logger.info('Seeding %s...', path)
105 webtorrent.seed(path, function (torrent) {
106 logger.info('%s seeded (%s).', path, torrent.magnetURI)
108 return callback(null, torrent)
112 function seedAllExisting (callback) {
113 Videos.listOwned(function (err, videos_list) {
115 logger.error('Cannot get list of the videos to seed.')
119 async.each(videos_list, function (video, each_callback) {
120 seed(uploadDir + video.namePath, function (err) {
122 logger.error('Cannot seed this video.')
132 // ---------------------------------------------------------------------------
134 module.exports = videos
136 // ---------------------------------------------------------------------------
138 function createRemoteVideoObjects (videos, callback) {
139 const remote_videos = []
141 async.each(videos, function (video, callback_each) {
142 // Creating the thumbnail for this remote video
143 utils.generateRandomString(16, function (err, random_string) {
144 if (err) return callback_each(err)
146 const thumbnail_name = random_string + '.jpg'
147 createThumbnailFromBase64(thumbnail_name, video.thumbnail_base64, function (err) {
148 if (err) return callback_each(err)
152 description: video.description,
153 magnetUri: video.magnetUri,
154 podUrl: video.podUrl,
155 duration: video.duration,
156 thumbnail: thumbnail_name
158 remote_videos.push(params)
165 if (err) return callback(err)
167 callback(null, remote_videos)
171 function createThumbnailFromBase64 (thumbnail_name, data, callback) {
172 fs.writeFile(thumbnailsDir + thumbnail_name, data, { encoding: 'base64' }, callback)