diff options
author | Chocobozzz <me@florianbigard.com> | 2019-01-29 08:37:25 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-02-11 09:13:02 +0100 |
commit | 092092969633bbcf6d4891a083ea497a7d5c3154 (patch) | |
tree | 69e82fe4f60c444cca216830e96afe143a9dac71 /server/controllers | |
parent | 4348a27d252a3349bafa7ef4859c0e2cf060c255 (diff) | |
download | PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.tar.gz PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.tar.zst PeerTube-092092969633bbcf6d4891a083ea497a7d5c3154.zip |
Add hls support on server
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/activitypub/client.ts | 15 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 8 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 19 | ||||
-rw-r--r-- | server/controllers/static.ts | 9 | ||||
-rw-r--r-- | server/controllers/tracker.ts | 25 |
5 files changed, 52 insertions, 24 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 1a4e28dc8..32a83aa5f 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts | |||
@@ -37,7 +37,7 @@ import { | |||
37 | getVideoSharesActivityPubUrl | 37 | getVideoSharesActivityPubUrl |
38 | } from '../../lib/activitypub' | 38 | } from '../../lib/activitypub' |
39 | import { VideoCaptionModel } from '../../models/video/video-caption' | 39 | import { VideoCaptionModel } from '../../models/video/video-caption' |
40 | import { videoRedundancyGetValidator } from '../../middlewares/validators/redundancy' | 40 | import { videoFileRedundancyGetValidator, videoPlaylistRedundancyGetValidator } from '../../middlewares/validators/redundancy' |
41 | import { getServerActor } from '../../helpers/utils' | 41 | import { getServerActor } from '../../helpers/utils' |
42 | import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy' | 42 | import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy' |
43 | 43 | ||
@@ -66,11 +66,11 @@ activityPubClientRouter.get('/accounts?/:name/dislikes/:videoId', | |||
66 | 66 | ||
67 | activityPubClientRouter.get('/videos/watch/:id', | 67 | activityPubClientRouter.get('/videos/watch/:id', |
68 | executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))), | 68 | executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))), |
69 | executeIfActivityPub(asyncMiddleware(videosGetValidator)), | 69 | executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video-with-rights'))), |
70 | executeIfActivityPub(asyncMiddleware(videoController)) | 70 | executeIfActivityPub(asyncMiddleware(videoController)) |
71 | ) | 71 | ) |
72 | activityPubClientRouter.get('/videos/watch/:id/activity', | 72 | activityPubClientRouter.get('/videos/watch/:id/activity', |
73 | executeIfActivityPub(asyncMiddleware(videosGetValidator)), | 73 | executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video-with-rights'))), |
74 | executeIfActivityPub(asyncMiddleware(videoController)) | 74 | executeIfActivityPub(asyncMiddleware(videoController)) |
75 | ) | 75 | ) |
76 | activityPubClientRouter.get('/videos/watch/:id/announces', | 76 | activityPubClientRouter.get('/videos/watch/:id/announces', |
@@ -116,7 +116,11 @@ activityPubClientRouter.get('/video-channels/:name/following', | |||
116 | ) | 116 | ) |
117 | 117 | ||
118 | activityPubClientRouter.get('/redundancy/videos/:videoId/:resolution([0-9]+)(-:fps([0-9]+))?', | 118 | activityPubClientRouter.get('/redundancy/videos/:videoId/:resolution([0-9]+)(-:fps([0-9]+))?', |
119 | executeIfActivityPub(asyncMiddleware(videoRedundancyGetValidator)), | 119 | executeIfActivityPub(asyncMiddleware(videoFileRedundancyGetValidator)), |
120 | executeIfActivityPub(asyncMiddleware(videoRedundancyController)) | ||
121 | ) | ||
122 | activityPubClientRouter.get('/redundancy/video-playlists/:streamingPlaylistType/:videoId', | ||
123 | executeIfActivityPub(asyncMiddleware(videoPlaylistRedundancyGetValidator)), | ||
120 | executeIfActivityPub(asyncMiddleware(videoRedundancyController)) | 124 | executeIfActivityPub(asyncMiddleware(videoRedundancyController)) |
121 | ) | 125 | ) |
122 | 126 | ||
@@ -163,7 +167,8 @@ function getAccountVideoRate (rateType: VideoRateType) { | |||
163 | } | 167 | } |
164 | 168 | ||
165 | async function videoController (req: express.Request, res: express.Response) { | 169 | async function videoController (req: express.Request, res: express.Response) { |
166 | const video: VideoModel = res.locals.video | 170 | // We need more attributes |
171 | const video: VideoModel = await VideoModel.loadForGetAPI(res.locals.video.id) | ||
167 | 172 | ||
168 | if (video.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(video.url) | 173 | if (video.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(video.url) |
169 | 174 | ||
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 255026f46..1f3341bc0 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { omit, snakeCase } from 'lodash' | 2 | import { snakeCase } from 'lodash' |
3 | import { ServerConfig, UserRight } from '../../../shared' | 3 | import { ServerConfig, UserRight } from '../../../shared' |
4 | import { About } from '../../../shared/models/server/about.model' | 4 | import { About } from '../../../shared/models/server/about.model' |
5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' | 5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' |
@@ -78,6 +78,9 @@ async function getConfig (req: express.Request, res: express.Response) { | |||
78 | requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION | 78 | requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION |
79 | }, | 79 | }, |
80 | transcoding: { | 80 | transcoding: { |
81 | hls: { | ||
82 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
83 | }, | ||
81 | enabledResolutions | 84 | enabledResolutions |
82 | }, | 85 | }, |
83 | import: { | 86 | import: { |
@@ -246,6 +249,9 @@ function customConfig (): CustomConfig { | |||
246 | '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ], | 249 | '480p': CONFIG.TRANSCODING.RESOLUTIONS[ '480p' ], |
247 | '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ], | 250 | '720p': CONFIG.TRANSCODING.RESOLUTIONS[ '720p' ], |
248 | '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ] | 251 | '1080p': CONFIG.TRANSCODING.RESOLUTIONS[ '1080p' ] |
252 | }, | ||
253 | hls: { | ||
254 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
249 | } | 255 | } |
250 | }, | 256 | }, |
251 | import: { | 257 | import: { |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 2b2dfa7ca..e04fc8186 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -37,6 +37,7 @@ import { | |||
37 | setDefaultPagination, | 37 | setDefaultPagination, |
38 | setDefaultSort, | 38 | setDefaultSort, |
39 | videosAddValidator, | 39 | videosAddValidator, |
40 | videosCustomGetValidator, | ||
40 | videosGetValidator, | 41 | videosGetValidator, |
41 | videosRemoveValidator, | 42 | videosRemoveValidator, |
42 | videosSortValidator, | 43 | videosSortValidator, |
@@ -123,9 +124,9 @@ videosRouter.get('/:id/description', | |||
123 | ) | 124 | ) |
124 | videosRouter.get('/:id', | 125 | videosRouter.get('/:id', |
125 | optionalAuthenticate, | 126 | optionalAuthenticate, |
126 | asyncMiddleware(videosGetValidator), | 127 | asyncMiddleware(videosCustomGetValidator('only-video-with-rights')), |
127 | asyncMiddleware(checkVideoFollowConstraints), | 128 | asyncMiddleware(checkVideoFollowConstraints), |
128 | getVideo | 129 | asyncMiddleware(getVideo) |
129 | ) | 130 | ) |
130 | videosRouter.post('/:id/views', | 131 | videosRouter.post('/:id/views', |
131 | asyncMiddleware(videosGetValidator), | 132 | asyncMiddleware(videosGetValidator), |
@@ -395,15 +396,17 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
395 | return res.type('json').status(204).end() | 396 | return res.type('json').status(204).end() |
396 | } | 397 | } |
397 | 398 | ||
398 | function getVideo (req: express.Request, res: express.Response) { | 399 | async function getVideo (req: express.Request, res: express.Response) { |
399 | const videoInstance = res.locals.video | 400 | // We need more attributes |
401 | const userId: number = res.locals.oauth ? res.locals.oauth.token.User.id : null | ||
402 | const video: VideoModel = await VideoModel.loadForGetAPI(res.locals.video.id, undefined, userId) | ||
400 | 403 | ||
401 | if (videoInstance.isOutdated()) { | 404 | if (video.isOutdated()) { |
402 | JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: videoInstance.url } }) | 405 | JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: video.url } }) |
403 | .catch(err => logger.error('Cannot create AP refresher job for video %s.', videoInstance.url, { err })) | 406 | .catch(err => logger.error('Cannot create AP refresher job for video %s.', video.url, { err })) |
404 | } | 407 | } |
405 | 408 | ||
406 | return res.json(videoInstance.toFormattedDetailsJSON()) | 409 | return res.json(video.toFormattedDetailsJSON()) |
407 | } | 410 | } |
408 | 411 | ||
409 | async function viewVideo (req: express.Request, res: express.Response) { | 412 | async function viewVideo (req: express.Request, res: express.Response) { |
diff --git a/server/controllers/static.ts b/server/controllers/static.ts index 4fd58f70c..b21f9da00 100644 --- a/server/controllers/static.ts +++ b/server/controllers/static.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as cors from 'cors' | 1 | import * as cors from 'cors' |
2 | import * as express from 'express' | 2 | import * as express from 'express' |
3 | import { CONFIG, ROUTE_CACHE_LIFETIME, STATIC_DOWNLOAD_PATHS, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers' | 3 | import { CONFIG, HLS_PLAYLIST_DIRECTORY, ROUTE_CACHE_LIFETIME, STATIC_DOWNLOAD_PATHS, STATIC_MAX_AGE, STATIC_PATHS } from '../initializers' |
4 | import { VideosPreviewCache } from '../lib/cache' | 4 | import { VideosPreviewCache } from '../lib/cache' |
5 | import { cacheRoute } from '../middlewares/cache' | 5 | import { cacheRoute } from '../middlewares/cache' |
6 | import { asyncMiddleware, videosGetValidator } from '../middlewares' | 6 | import { asyncMiddleware, videosGetValidator } from '../middlewares' |
@@ -51,6 +51,13 @@ staticRouter.use( | |||
51 | asyncMiddleware(downloadVideoFile) | 51 | asyncMiddleware(downloadVideoFile) |
52 | ) | 52 | ) |
53 | 53 | ||
54 | // HLS | ||
55 | staticRouter.use( | ||
56 | STATIC_PATHS.PLAYLISTS.HLS, | ||
57 | cors(), | ||
58 | express.static(HLS_PLAYLIST_DIRECTORY, { fallthrough: false }) // 404 if the file does not exist | ||
59 | ) | ||
60 | |||
54 | // Thumbnails path for express | 61 | // Thumbnails path for express |
55 | const thumbnailsPhysicalPath = CONFIG.STORAGE.THUMBNAILS_DIR | 62 | const thumbnailsPhysicalPath = CONFIG.STORAGE.THUMBNAILS_DIR |
56 | staticRouter.use( | 63 | staticRouter.use( |
diff --git a/server/controllers/tracker.ts b/server/controllers/tracker.ts index 1deb8c402..8b77d9de7 100644 --- a/server/controllers/tracker.ts +++ b/server/controllers/tracker.ts | |||
@@ -7,6 +7,7 @@ import { Server as WebSocketServer } from 'ws' | |||
7 | import { CONFIG, TRACKER_RATE_LIMITS } from '../initializers/constants' | 7 | import { CONFIG, TRACKER_RATE_LIMITS } from '../initializers/constants' |
8 | import { VideoFileModel } from '../models/video/video-file' | 8 | import { VideoFileModel } from '../models/video/video-file' |
9 | import { parse } from 'url' | 9 | import { parse } from 'url' |
10 | import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' | ||
10 | 11 | ||
11 | const TrackerServer = bitTorrentTracker.Server | 12 | const TrackerServer = bitTorrentTracker.Server |
12 | 13 | ||
@@ -21,7 +22,7 @@ const trackerServer = new TrackerServer({ | |||
21 | udp: false, | 22 | udp: false, |
22 | ws: false, | 23 | ws: false, |
23 | dht: false, | 24 | dht: false, |
24 | filter: function (infoHash, params, cb) { | 25 | filter: async function (infoHash, params, cb) { |
25 | let ip: string | 26 | let ip: string |
26 | 27 | ||
27 | if (params.type === 'ws') { | 28 | if (params.type === 'ws') { |
@@ -32,19 +33,25 @@ const trackerServer = new TrackerServer({ | |||
32 | 33 | ||
33 | const key = ip + '-' + infoHash | 34 | const key = ip + '-' + infoHash |
34 | 35 | ||
35 | peersIps[ip] = peersIps[ip] ? peersIps[ip] + 1 : 1 | 36 | peersIps[ ip ] = peersIps[ ip ] ? peersIps[ ip ] + 1 : 1 |
36 | peersIpInfoHash[key] = peersIpInfoHash[key] ? peersIpInfoHash[key] + 1 : 1 | 37 | peersIpInfoHash[ key ] = peersIpInfoHash[ key ] ? peersIpInfoHash[ key ] + 1 : 1 |
37 | 38 | ||
38 | if (peersIpInfoHash[key] > TRACKER_RATE_LIMITS.ANNOUNCES_PER_IP_PER_INFOHASH) { | 39 | if (peersIpInfoHash[ key ] > TRACKER_RATE_LIMITS.ANNOUNCES_PER_IP_PER_INFOHASH) { |
39 | return cb(new Error(`Too many requests (${peersIpInfoHash[ key ]} of ip ${ip} for torrent ${infoHash}`)) | 40 | return cb(new Error(`Too many requests (${peersIpInfoHash[ key ]} of ip ${ip} for torrent ${infoHash}`)) |
40 | } | 41 | } |
41 | 42 | ||
42 | VideoFileModel.isInfohashExists(infoHash) | 43 | try { |
43 | .then(exists => { | 44 | const videoFileExists = await VideoFileModel.doesInfohashExist(infoHash) |
44 | if (exists === false) return cb(new Error(`Unknown infoHash ${infoHash}`)) | 45 | if (videoFileExists === true) return cb() |
45 | 46 | ||
46 | return cb() | 47 | const playlistExists = await VideoStreamingPlaylistModel.doesInfohashExist(infoHash) |
47 | }) | 48 | if (playlistExists === true) return cb() |
49 | |||
50 | return cb(new Error(`Unknown infoHash ${infoHash}`)) | ||
51 | } catch (err) { | ||
52 | logger.error('Error in tracker filter.', { err }) | ||
53 | return cb(err) | ||
54 | } | ||
48 | } | 55 | } |
49 | }) | 56 | }) |
50 | 57 | ||