]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/videos.js
Update to standard 7. Goodbye snake_case, I used to love you
[github/Chocobozzz/PeerTube.git] / server / lib / videos.js
CommitLineData
9f10b292
C
1'use strict'
2
f0f5567b
C
3const async = require('async')
4const config = require('config')
0ae6a09d 5const ffmpeg = require('fluent-ffmpeg')
cbe2f7c3
C
6const fs = require('fs')
7const map = require('lodash/map')
f0f5567b 8const pathUtils = require('path')
9f10b292 9
cbe2f7c3 10const constants = require('../initializers/constants')
f0f5567b 11const logger = require('../helpers/logger')
cbe2f7c3 12const utils = require('../helpers/utils')
f0f5567b 13const Videos = require('../models/videos')
cbe2f7c3 14const webtorrent = require('../lib/webtorrent')
9f10b292 15
f0f5567b 16const uploadDir = pathUtils.join(__dirname, '..', '..', config.get('storage.uploads'))
cbe2f7c3 17const thumbnailsDir = pathUtils.join(__dirname, '..', '..', config.get('storage.thumbnails'))
9f10b292 18
f0f5567b 19const videos = {
cbe2f7c3 20 createRemoteVideos: createRemoteVideos,
0ae6a09d 21 getVideoDuration: getVideoDuration,
5101105e 22 getVideoState: getVideoState,
cbe2f7c3
C
23 getVideoThumbnail: getVideoThumbnail,
24 removeVideosDataFromDisk: removeVideosDataFromDisk,
25 removeRemoteVideos: removeRemoteVideos,
9f10b292
C
26 seed: seed,
27 seedAllExisting: seedAllExisting
28}
29
cbe2f7c3
C
30function createRemoteVideos (videos, callback) {
31 // Create the remote videos from the new pod
bc503c2a 32 createRemoteVideoObjects(videos, function (err, remoteVideos) {
cbe2f7c3
C
33 if (err) return callback(err)
34
bc503c2a 35 Videos.addRemotes(remoteVideos, callback)
cbe2f7c3
C
36 })
37}
38
bc503c2a
C
39function getVideoDuration (videoPath, callback) {
40 ffmpeg.ffprobe(videoPath, function (err, metadata) {
0ae6a09d
C
41 if (err) return callback(err)
42
43 return callback(null, Math.floor(metadata.format.duration))
44 })
45}
46
2df82d42 47function getVideoState (video) {
f0f5567b
C
48 const exist = (video !== null)
49 let owned = false
5101105e
C
50 if (exist === true) {
51 owned = (video.namePath !== null)
52 }
53
2df82d42 54 return { exist: exist, owned: owned }
5101105e
C
55}
56
bc503c2a
C
57function getVideoThumbnail (videoPath, callback) {
58 const filename = pathUtils.basename(videoPath) + '.jpg'
59 ffmpeg(videoPath)
cbe2f7c3
C
60 .on('error', callback)
61 .on('end', function () {
62 callback(null, filename)
63 })
64 .thumbnail({
65 count: 1,
66 folder: thumbnailsDir,
67 size: constants.THUMBNAILS_SIZE,
68 filename: filename
69 })
70}
71
72// Remove video datas from disk (video file, thumbnail...)
73function removeVideosDataFromDisk (videos, callback) {
bc503c2a 74 async.each(videos, function (video, callbackEach) {
cbe2f7c3
C
75 fs.unlink(thumbnailsDir + video.thumbnail, function (err) {
76 if (err) logger.error('Cannot remove the video thumbnail')
77
78 if (getVideoState(video).owned === true) {
79 fs.unlink(uploadDir + video.namePath, function (err) {
80 if (err) {
81 logger.error('Cannot remove this video file.')
bc503c2a 82 return callbackEach(err)
cbe2f7c3
C
83 }
84
bc503c2a 85 callbackEach(null)
cbe2f7c3
C
86 })
87 } else {
bc503c2a 88 callbackEach(null)
cbe2f7c3
C
89 }
90 })
91 }, callback)
92}
93
94function removeRemoteVideos (videos, callback) {
95 Videos.removeByIds(map(videos, '_id'), function (err) {
96 if (err) return callback(err)
97
98 removeVideosDataFromDisk(videos, callback)
99 })
100}
101
9f10b292
C
102function seed (path, callback) {
103 logger.info('Seeding %s...', path)
104
105 webtorrent.seed(path, function (torrent) {
106 logger.info('%s seeded (%s).', path, torrent.magnetURI)
107
108 return callback(null, torrent)
109 })
110}
111
112function seedAllExisting (callback) {
bc503c2a 113 Videos.listOwned(function (err, videosList) {
9f10b292
C
114 if (err) {
115 logger.error('Cannot get list of the videos to seed.')
116 return callback(err)
117 }
118
bc503c2a 119 async.each(videosList, function (video, callbackEach) {
9f10b292
C
120 seed(uploadDir + video.namePath, function (err) {
121 if (err) {
122 logger.error('Cannot seed this video.')
123 return callback(err)
124 }
125
bc503c2a 126 callbackEach(null)
9f10b292
C
127 })
128 }, callback)
129 })
130}
131
132// ---------------------------------------------------------------------------
133
134module.exports = videos
cbe2f7c3
C
135
136// ---------------------------------------------------------------------------
137
138function createRemoteVideoObjects (videos, callback) {
bc503c2a 139 const remoteVideos = []
cbe2f7c3 140
bc503c2a 141 async.each(videos, function (video, callbackEach) {
cbe2f7c3 142 // Creating the thumbnail for this remote video
bc503c2a
C
143 utils.generateRandomString(16, function (err, randomString) {
144 if (err) return callbackEach(err)
cbe2f7c3 145
bc503c2a
C
146 const thumbnailName = randomString + '.jpg'
147 createThumbnailFromBase64(thumbnailName, video.thumbnailBase64, function (err) {
148 if (err) return callbackEach(err)
cbe2f7c3
C
149
150 const params = {
151 name: video.name,
152 description: video.description,
153 magnetUri: video.magnetUri,
154 podUrl: video.podUrl,
155 duration: video.duration,
bc503c2a 156 thumbnail: thumbnailName
cbe2f7c3 157 }
bc503c2a 158 remoteVideos.push(params)
cbe2f7c3 159
bc503c2a 160 callbackEach(null)
cbe2f7c3
C
161 })
162 })
163 },
164 function (err) {
165 if (err) return callback(err)
166
bc503c2a 167 callback(null, remoteVideos)
cbe2f7c3
C
168 })
169}
170
bc503c2a
C
171function createThumbnailFromBase64 (thumbnailName, data, callback) {
172 fs.writeFile(thumbnailsDir + thumbnailName, data, { encoding: 'base64' }, callback)
cbe2f7c3 173}