aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video.js
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2016-11-11 15:20:03 +0100
committerChocobozzz <florian.bigard@gmail.com>2016-11-16 20:29:26 +0100
commitf285faa04e84b45e62bd05e7050dc500113b0356 (patch)
treebae907d0714e435e92137347e0b892b806c5302c /server/models/video.js
parent558d7c2385d8a152a94140eed753f511e90986d7 (diff)
downloadPeerTube-f285faa04e84b45e62bd05e7050dc500113b0356.tar.gz
PeerTube-f285faa04e84b45e62bd05e7050dc500113b0356.tar.zst
PeerTube-f285faa04e84b45e62bd05e7050dc500113b0356.zip
Server: generate magnet uri on the fly
Diffstat (limited to 'server/models/video.js')
-rw-r--r--server/models/video.js102
1 files changed, 72 insertions, 30 deletions
diff --git a/server/models/video.js b/server/models/video.js
index 6cffa87af..19136ba25 100644
--- a/server/models/video.js
+++ b/server/models/video.js
@@ -3,10 +3,10 @@
3const createTorrent = require('create-torrent') 3const createTorrent = require('create-torrent')
4const ffmpeg = require('fluent-ffmpeg') 4const ffmpeg = require('fluent-ffmpeg')
5const fs = require('fs') 5const fs = require('fs')
6const magnetUtil = require('magnet-uri')
6const parallel = require('async/parallel') 7const parallel = require('async/parallel')
7const parseTorrent = require('parse-torrent') 8const parseTorrent = require('parse-torrent')
8const pathUtils = require('path') 9const pathUtils = require('path')
9const magnet = require('magnet-uri')
10const mongoose = require('mongoose') 10const mongoose = require('mongoose')
11 11
12const constants = require('../initializers/constants') 12const constants = require('../initializers/constants')
@@ -25,7 +25,9 @@ const VideoSchema = mongoose.Schema({
25 }, 25 },
26 remoteId: mongoose.Schema.Types.ObjectId, 26 remoteId: mongoose.Schema.Types.ObjectId,
27 description: String, 27 description: String,
28 magnetUri: String, 28 magnet: {
29 infoHash: String
30 },
29 podUrl: String, 31 podUrl: String,
30 author: String, 32 author: String,
31 duration: Number, 33 duration: Number,
@@ -39,7 +41,6 @@ const VideoSchema = mongoose.Schema({
39 41
40VideoSchema.path('name').validate(customVideosValidators.isVideoNameValid) 42VideoSchema.path('name').validate(customVideosValidators.isVideoNameValid)
41VideoSchema.path('description').validate(customVideosValidators.isVideoDescriptionValid) 43VideoSchema.path('description').validate(customVideosValidators.isVideoDescriptionValid)
42VideoSchema.path('magnetUri').validate(customVideosValidators.isVideoMagnetUriValid)
43VideoSchema.path('podUrl').validate(customVideosValidators.isVideoPodUrlValid) 44VideoSchema.path('podUrl').validate(customVideosValidators.isVideoPodUrlValid)
44VideoSchema.path('author').validate(customVideosValidators.isVideoAuthorValid) 45VideoSchema.path('author').validate(customVideosValidators.isVideoAuthorValid)
45VideoSchema.path('duration').validate(customVideosValidators.isVideoDurationValid) 46VideoSchema.path('duration').validate(customVideosValidators.isVideoDurationValid)
@@ -51,8 +52,10 @@ VideoSchema.path('thumbnail').validate(function (value) {
51VideoSchema.path('tags').validate(customVideosValidators.isVideoTagsValid) 52VideoSchema.path('tags').validate(customVideosValidators.isVideoTagsValid)
52 53
53VideoSchema.methods = { 54VideoSchema.methods = {
54 getFilename, 55 generateMagnetUri,
55 getJPEGName, 56 getVideoFilename,
57 getThumbnailName,
58 getPreviewName,
56 getTorrentName, 59 getTorrentName,
57 isOwned, 60 isOwned,
58 toFormatedJSON, 61 toFormatedJSON,
@@ -103,8 +106,8 @@ VideoSchema.pre('save', function (next) {
103 const tasks = [] 106 const tasks = []
104 107
105 if (video.isOwned()) { 108 if (video.isOwned()) {
106 const videoPath = pathUtils.join(constants.CONFIG.STORAGE.VIDEOS_DIR, video.getFilename()) 109 const videoPath = pathUtils.join(constants.CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename())
107 this.podUrl = constants.CONFIG.WEBSERVER.URL 110 this.podUrl = constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT
108 111
109 tasks.push( 112 tasks.push(
110 // TODO: refractoring 113 // TODO: refractoring
@@ -114,7 +117,7 @@ VideoSchema.pre('save', function (next) {
114 [ constants.CONFIG.WEBSERVER.WS + '://' + constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT + '/tracker/socket' ] 117 [ constants.CONFIG.WEBSERVER.WS + '://' + constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT + '/tracker/socket' ]
115 ], 118 ],
116 urlList: [ 119 urlList: [
117 constants.CONFIG.WEBSERVER.URL + constants.STATIC_PATHS.WEBSEED + video.getFilename() 120 constants.CONFIG.WEBSERVER.URL + constants.STATIC_PATHS.WEBSEED + video.getVideoFilename()
118 ] 121 ]
119 } 122 }
120 123
@@ -125,9 +128,9 @@ VideoSchema.pre('save', function (next) {
125 if (err) return callback(err) 128 if (err) return callback(err)
126 129
127 const parsedTorrent = parseTorrent(torrent) 130 const parsedTorrent = parseTorrent(torrent)
128 parsedTorrent.xs = video.podUrl + constants.STATIC_PATHS.TORRENTS + video.getTorrentName() 131 video.magnet.infoHash = parsedTorrent.infoHash
129 video.magnetUri = magnet.encode(parsedTorrent)
130 132
133 console.log(parsedTorrent)
131 callback(null) 134 callback(null)
132 }) 135 })
133 }) 136 })
@@ -150,16 +153,57 @@ mongoose.model('Video', VideoSchema)
150 153
151// ------------------------------ METHODS ------------------------------ 154// ------------------------------ METHODS ------------------------------
152 155
153function getFilename () { 156function generateMagnetUri () {
154 return this._id + this.extname 157 let baseUrlHttp, baseUrlWs
158
159 if (this.isOwned()) {
160 baseUrlHttp = constants.CONFIG.WEBSERVER.URL
161 baseUrlWs = constants.CONFIG.WEBSERVER.WS + '://' + constants.CONFIG.WEBSERVER.HOSTNAME + ':' + constants.CONFIG.WEBSERVER.PORT
162 } else {
163 baseUrlHttp = constants.REMOTE_SCHEME.HTTP + this.podUrl
164 baseUrlWs = constants.REMOTE_SCHEME.WS + this.podUrl
165 }
166
167 const xs = baseUrlHttp + constants.STATIC_PATHS.TORRENTS + this.getTorrentName()
168 const announce = baseUrlWs + '/tracker/socket'
169 const urlList = [ baseUrlHttp + constants.STATIC_PATHS.WEBSEED + this.getVideoFilename() ]
170
171 const magnetHash = {
172 xs,
173 announce,
174 urlList,
175 infoHash: this.magnet.infoHash,
176 name: this.name
177 }
178
179 return magnetUtil.encode(magnetHash)
155} 180}
156 181
157function getJPEGName () { 182function getVideoFilename () {
183 if (this.isOwned()) return this._id + this.extname
184
185 return this.remoteId + this.extname
186}
187
188function getThumbnailName () {
189 // We always have a copy of the thumbnail
158 return this._id + '.jpg' 190 return this._id + '.jpg'
159} 191}
160 192
193function getPreviewName () {
194 const extension = '.jpg'
195
196 if (this.isOwned()) return this._id + extension
197
198 return this.remoteId + extension
199}
200
161function getTorrentName () { 201function getTorrentName () {
162 return this._id + '.torrent' 202 const extension = '.torrent'
203
204 if (this.isOwned()) return this._id + extension
205
206 return this.remoteId + extension
163} 207}
164 208
165function isOwned () { 209function isOwned () {
@@ -171,13 +215,13 @@ function toFormatedJSON () {
171 id: this._id, 215 id: this._id,
172 name: this.name, 216 name: this.name,
173 description: this.description, 217 description: this.description,
174 podUrl: this.podUrl.replace(/^https?:\/\//, ''), 218 podUrl: this.podUrl,
175 isLocal: this.isOwned(), 219 isLocal: this.isOwned(),
176 magnetUri: this.magnetUri, 220 magnetUri: this.generateMagnetUri(),
177 author: this.author, 221 author: this.author,
178 duration: this.duration, 222 duration: this.duration,
179 tags: this.tags, 223 tags: this.tags,
180 thumbnailPath: constants.STATIC_PATHS.THUMBNAILS + '/' + this.getJPEGName(), 224 thumbnailPath: constants.STATIC_PATHS.THUMBNAILS + '/' + this.getThumbnailName(),
181 createdDate: this.createdDate 225 createdDate: this.createdDate
182 } 226 }
183 227
@@ -188,7 +232,7 @@ function toRemoteJSON (callback) {
188 const self = this 232 const self = this
189 233
190 // Convert thumbnail to base64 234 // Convert thumbnail to base64
191 const thumbnailPath = pathUtils.join(constants.CONFIG.STORAGE.THUMBNAILS_DIR, this.getJPEGName()) 235 const thumbnailPath = pathUtils.join(constants.CONFIG.STORAGE.THUMBNAILS_DIR, this.getThumbnailName())
192 fs.readFile(thumbnailPath, function (err, thumbnailData) { 236 fs.readFile(thumbnailPath, function (err, thumbnailData) {
193 if (err) { 237 if (err) {
194 logger.error('Cannot read the thumbnail of the video') 238 logger.error('Cannot read the thumbnail of the video')
@@ -198,7 +242,7 @@ function toRemoteJSON (callback) {
198 const remoteVideo = { 242 const remoteVideo = {
199 name: self.name, 243 name: self.name,
200 description: self.description, 244 description: self.description,
201 magnetUri: self.magnetUri, 245 magnet: self.magnet,
202 remoteId: self._id, 246 remoteId: self._id,
203 author: self.author, 247 author: self.author,
204 duration: self.duration, 248 duration: self.duration,
@@ -267,11 +311,11 @@ function search (value, field, start, count, sort, callback) {
267// --------------------------------------------------------------------------- 311// ---------------------------------------------------------------------------
268 312
269function removeThumbnail (video, callback) { 313function removeThumbnail (video, callback) {
270 fs.unlink(constants.CONFIG.STORAGE.THUMBNAILS_DIR + video.getJPEGName(), callback) 314 fs.unlink(constants.CONFIG.STORAGE.THUMBNAILS_DIR + video.getThumbnailName(), callback)
271} 315}
272 316
273function removeFile (video, callback) { 317function removeFile (video, callback) {
274 fs.unlink(constants.CONFIG.STORAGE.VIDEOS_DIR + video.getFilename(), callback) 318 fs.unlink(constants.CONFIG.STORAGE.VIDEOS_DIR + video.getVideoFilename(), callback)
275} 319}
276 320
277function removeTorrent (video, callback) { 321function removeTorrent (video, callback) {
@@ -280,22 +324,21 @@ function removeTorrent (video, callback) {
280 324
281function removePreview (video, callback) { 325function removePreview (video, callback) {
282 // Same name than video thumnail 326 // Same name than video thumnail
283 // TODO: refractoring 327 fs.unlink(constants.CONFIG.STORAGE.PREVIEWS_DIR + video.getPreviewName(), callback)
284 fs.unlink(constants.CONFIG.STORAGE.PREVIEWS_DIR + video.getJPEGName(), callback)
285} 328}
286 329
287function createPreview (video, videoPath, callback) { 330function createPreview (video, videoPath, callback) {
288 generateImage(video, videoPath, constants.CONFIG.STORAGE.PREVIEWS_DIR, callback) 331 generateImage(video, videoPath, constants.CONFIG.STORAGE.PREVIEWS_DIR, video.getPreviewName(), callback)
289} 332}
290 333
291function createThumbnail (video, videoPath, callback) { 334function createThumbnail (video, videoPath, callback) {
292 generateImage(video, videoPath, constants.CONFIG.STORAGE.THUMBNAILS_DIR, constants.THUMBNAILS_SIZE, callback) 335 generateImage(video, videoPath, constants.CONFIG.STORAGE.THUMBNAILS_DIR, video.getThumbnailName(), constants.THUMBNAILS_SIZE, callback)
293} 336}
294 337
295function generateThumbnailFromBase64 (video, thumbnailData, callback) { 338function generateThumbnailFromBase64 (video, thumbnailData, callback) {
296 // Creating the thumbnail for this remote video) 339 // Creating the thumbnail for this remote video)
297 340
298 const thumbnailName = video.getJPEGName() 341 const thumbnailName = video.getThumbnailName()
299 const thumbnailPath = constants.CONFIG.STORAGE.THUMBNAILS_DIR + thumbnailName 342 const thumbnailPath = constants.CONFIG.STORAGE.THUMBNAILS_DIR + thumbnailName
300 fs.writeFile(thumbnailPath, thumbnailData, { encoding: 'base64' }, function (err) { 343 fs.writeFile(thumbnailPath, thumbnailData, { encoding: 'base64' }, function (err) {
301 if (err) return callback(err) 344 if (err) return callback(err)
@@ -304,10 +347,9 @@ function generateThumbnailFromBase64 (video, thumbnailData, callback) {
304 }) 347 })
305} 348}
306 349
307function generateImage (video, videoPath, folder, size, callback) { 350function generateImage (video, videoPath, folder, imageName, size, callback) {
308 const filename = video.getJPEGName()
309 const options = { 351 const options = {
310 filename, 352 filename: imageName,
311 count: 1, 353 count: 1,
312 folder 354 folder
313 } 355 }
@@ -321,7 +363,7 @@ function generateImage (video, videoPath, folder, size, callback) {
321 ffmpeg(videoPath) 363 ffmpeg(videoPath)
322 .on('error', callback) 364 .on('error', callback)
323 .on('end', function () { 365 .on('end', function () {
324 callback(null, filename) 366 callback(null, imageName)
325 }) 367 })
326 .thumbnail(options) 368 .thumbnail(options)
327} 369}