diff options
-rw-r--r-- | server/controllers/static.ts | 6 | ||||
-rw-r--r-- | server/initializers/constants.ts | 1 | ||||
-rw-r--r-- | server/lib/schedulers/videos-redundancy-scheduler.ts | 4 | ||||
-rw-r--r-- | server/models/redundancy/video-redundancy.ts | 4 | ||||
-rw-r--r-- | server/models/video/video.ts | 10 | ||||
-rw-r--r-- | server/tests/api/redundancy/redundancy.ts | 27 | ||||
-rw-r--r-- | support/nginx/peertube | 9 |
7 files changed, 38 insertions, 23 deletions
diff --git a/server/controllers/static.ts b/server/controllers/static.ts index f16a7d72b..55e7392a1 100644 --- a/server/controllers/static.ts +++ b/server/controllers/static.ts | |||
@@ -37,12 +37,12 @@ staticRouter.use( | |||
37 | staticRouter.use( | 37 | staticRouter.use( |
38 | STATIC_PATHS.WEBSEED, | 38 | STATIC_PATHS.WEBSEED, |
39 | cors(), | 39 | cors(), |
40 | express.static(CONFIG.STORAGE.VIDEOS_DIR) | 40 | express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video |
41 | ) | 41 | ) |
42 | staticRouter.use( | 42 | staticRouter.use( |
43 | STATIC_PATHS.WEBSEED, | 43 | STATIC_PATHS.REDUNDANCY, |
44 | cors(), | 44 | cors(), |
45 | express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404, because we don't have this video | 45 | express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video |
46 | ) | 46 | ) |
47 | 47 | ||
48 | staticRouter.use( | 48 | staticRouter.use( |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 876aa1cf5..7195ae6c5 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -571,6 +571,7 @@ const STATIC_PATHS = { | |||
571 | THUMBNAILS: '/static/thumbnails/', | 571 | THUMBNAILS: '/static/thumbnails/', |
572 | TORRENTS: '/static/torrents/', | 572 | TORRENTS: '/static/torrents/', |
573 | WEBSEED: '/static/webseed/', | 573 | WEBSEED: '/static/webseed/', |
574 | REDUNDANCY: '/static/redundancy/', | ||
574 | AVATARS: '/static/avatars/', | 575 | AVATARS: '/static/avatars/', |
575 | VIDEO_CAPTIONS: '/static/video-captions/' | 576 | VIDEO_CAPTIONS: '/static/video-captions/' |
576 | } | 577 | } |
diff --git a/server/lib/schedulers/videos-redundancy-scheduler.ts b/server/lib/schedulers/videos-redundancy-scheduler.ts index 8b7f33539..2a99a665d 100644 --- a/server/lib/schedulers/videos-redundancy-scheduler.ts +++ b/server/lib/schedulers/videos-redundancy-scheduler.ts | |||
@@ -145,13 +145,13 @@ export class VideosRedundancyScheduler extends AbstractScheduler { | |||
145 | 145 | ||
146 | const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT) | 146 | const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT) |
147 | 147 | ||
148 | const destPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename(file)) | 148 | const destPath = join(CONFIG.STORAGE.REDUNDANCY_DIR, video.getVideoFilename(file)) |
149 | await rename(tmpPath, destPath) | 149 | await rename(tmpPath, destPath) |
150 | 150 | ||
151 | const createdModel = await VideoRedundancyModel.create({ | 151 | const createdModel = await VideoRedundancyModel.create({ |
152 | expiresOn: this.buildNewExpiration(redundancy.minLifetime), | 152 | expiresOn: this.buildNewExpiration(redundancy.minLifetime), |
153 | url: getVideoCacheFileActivityPubUrl(file), | 153 | url: getVideoCacheFileActivityPubUrl(file), |
154 | fileUrl: video.getVideoFileUrl(file, CONFIG.WEBSERVER.URL), | 154 | fileUrl: video.getVideoRedundancyUrl(file, CONFIG.WEBSERVER.URL), |
155 | strategy: redundancy.strategy, | 155 | strategy: redundancy.strategy, |
156 | videoFileId: file.id, | 156 | videoFileId: file.id, |
157 | actorId: serverActor.id | 157 | actorId: serverActor.id |
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts index 9de4356b4..dd37dad22 100644 --- a/server/models/redundancy/video-redundancy.ts +++ b/server/models/redundancy/video-redundancy.ts | |||
@@ -15,7 +15,7 @@ import { | |||
15 | import { ActorModel } from '../activitypub/actor' | 15 | import { ActorModel } from '../activitypub/actor' |
16 | import { getVideoSort, throwIfNotValid } from '../utils' | 16 | import { getVideoSort, throwIfNotValid } from '../utils' |
17 | import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 17 | import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
18 | import { CONFIG, CONSTRAINTS_FIELDS, VIDEO_EXT_MIMETYPE } from '../../initializers' | 18 | import { CONFIG, CONSTRAINTS_FIELDS, STATIC_PATHS, VIDEO_EXT_MIMETYPE } from '../../initializers' |
19 | import { VideoFileModel } from '../video/video-file' | 19 | import { VideoFileModel } from '../video/video-file' |
20 | import { getServerActor } from '../../helpers/utils' | 20 | import { getServerActor } from '../../helpers/utils' |
21 | import { VideoModel } from '../video/video' | 21 | import { VideoModel } from '../video/video' |
@@ -124,7 +124,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> { | |||
124 | const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` | 124 | const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` |
125 | logger.info('Removing duplicated video file %s.', logIdentifier) | 125 | logger.info('Removing duplicated video file %s.', logIdentifier) |
126 | 126 | ||
127 | videoFile.Video.removeFile(videoFile) | 127 | videoFile.Video.removeFile(videoFile, true) |
128 | .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) | 128 | .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) |
129 | 129 | ||
130 | return undefined | 130 | return undefined |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 0f18d9f0c..e8cb5aa88 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -1538,8 +1538,10 @@ export class VideoModel extends Model<VideoModel> { | |||
1538 | .catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err })) | 1538 | .catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err })) |
1539 | } | 1539 | } |
1540 | 1540 | ||
1541 | removeFile (videoFile: VideoFileModel) { | 1541 | removeFile (videoFile: VideoFileModel, isRedundancy = false) { |
1542 | const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile)) | 1542 | const baseDir = isRedundancy ? CONFIG.STORAGE.REDUNDANCY_DIR : CONFIG.STORAGE.VIDEOS_DIR |
1543 | |||
1544 | const filePath = join(baseDir, this.getVideoFilename(videoFile)) | ||
1543 | return remove(filePath) | 1545 | return remove(filePath) |
1544 | .catch(err => logger.warn('Cannot delete file %s.', filePath, { err })) | 1546 | .catch(err => logger.warn('Cannot delete file %s.', filePath, { err })) |
1545 | } | 1547 | } |
@@ -1617,6 +1619,10 @@ export class VideoModel extends Model<VideoModel> { | |||
1617 | return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile) | 1619 | return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile) |
1618 | } | 1620 | } |
1619 | 1621 | ||
1622 | getVideoRedundancyUrl (videoFile: VideoFileModel, baseUrlHttp: string) { | ||
1623 | return baseUrlHttp + STATIC_PATHS.REDUNDANCY + this.getVideoFilename(videoFile) | ||
1624 | } | ||
1625 | |||
1620 | getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) { | 1626 | getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) { |
1621 | return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile) | 1627 | return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile) |
1622 | } | 1628 | } |
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts index a8a2f305f..5b29a503a 100644 --- a/server/tests/api/redundancy/redundancy.ts +++ b/server/tests/api/redundancy/redundancy.ts | |||
@@ -136,7 +136,7 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st | |||
136 | if (!videoUUID) videoUUID = video1Server2UUID | 136 | if (!videoUUID) videoUUID = video1Server2UUID |
137 | 137 | ||
138 | const webseeds = [ | 138 | const webseeds = [ |
139 | 'http://localhost:9001/static/webseed/' + videoUUID, | 139 | 'http://localhost:9001/static/redundancy/' + videoUUID, |
140 | 'http://localhost:9002/static/webseed/' + videoUUID | 140 | 'http://localhost:9002/static/webseed/' + videoUUID |
141 | ] | 141 | ] |
142 | 142 | ||
@@ -148,20 +148,23 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st | |||
148 | for (const file of video.files) { | 148 | for (const file of video.files) { |
149 | checkMagnetWebseeds(file, webseeds, server) | 149 | checkMagnetWebseeds(file, webseeds, server) |
150 | 150 | ||
151 | // Only servers 1 and 2 have the video | 151 | await makeGetRequest({ |
152 | if (server.serverNumber !== 3) { | 152 | url: servers[0].url, |
153 | await makeGetRequest({ | 153 | statusCodeExpected: 200, |
154 | url: server.url, | 154 | path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`, |
155 | statusCodeExpected: 200, | 155 | contentType: null |
156 | path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, | 156 | }) |
157 | contentType: null | 157 | await makeGetRequest({ |
158 | }) | 158 | url: servers[1].url, |
159 | } | 159 | statusCodeExpected: 200, |
160 | path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`, | ||
161 | contentType: null | ||
162 | }) | ||
160 | } | 163 | } |
161 | } | 164 | } |
162 | 165 | ||
163 | for (const directory of [ 'test1', 'test2' ]) { | 166 | for (const directory of [ 'test1/redundancy', 'test2/videos' ]) { |
164 | const files = await readdir(join(root(), directory, 'videos')) | 167 | const files = await readdir(join(root(), directory)) |
165 | expect(files).to.have.length.at.least(4) | 168 | expect(files).to.have.length.at.least(4) |
166 | 169 | ||
167 | for (const resolution of [ 240, 360, 480, 720 ]) { | 170 | for (const resolution of [ 240, 360, 480, 720 ]) { |
diff --git a/support/nginx/peertube b/support/nginx/peertube index b00031133..e0b006088 100644 --- a/support/nginx/peertube +++ b/support/nginx/peertube | |||
@@ -105,7 +105,7 @@ server { | |||
105 | } | 105 | } |
106 | 106 | ||
107 | # Bypass PeerTube for performance reasons. Could be removed | 107 | # Bypass PeerTube for performance reasons. Could be removed |
108 | location /static/webseed { | 108 | location ~ ^/static/(webseed|redundancy)/ { |
109 | # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client | 109 | # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client |
110 | limit_rate 800k; | 110 | limit_rate 800k; |
111 | 111 | ||
@@ -128,7 +128,12 @@ server { | |||
128 | access_log off; | 128 | access_log off; |
129 | } | 129 | } |
130 | 130 | ||
131 | alias /var/www/peertube/storage/videos; | 131 | root /var/www/peertube/storage; |
132 | |||
133 | rewrite ^/static/webseed/(.*)$ /videos/$1 break; | ||
134 | rewrite ^/static/redundancy/(.*)$ /redundancy/$1 break; | ||
135 | |||
136 | try_files $uri /; | ||
132 | } | 137 | } |
133 | 138 | ||
134 | # Websocket tracker | 139 | # Websocket tracker |