Create redundancy endpoint
This commit is contained in:
parent
6040f87d14
commit
b9fffa297f
|
@ -37,12 +37,12 @@ staticRouter.use(
|
||||||
staticRouter.use(
|
staticRouter.use(
|
||||||
STATIC_PATHS.WEBSEED,
|
STATIC_PATHS.WEBSEED,
|
||||||
cors(),
|
cors(),
|
||||||
express.static(CONFIG.STORAGE.VIDEOS_DIR)
|
express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video
|
||||||
)
|
)
|
||||||
staticRouter.use(
|
staticRouter.use(
|
||||||
STATIC_PATHS.WEBSEED,
|
STATIC_PATHS.REDUNDANCY,
|
||||||
cors(),
|
cors(),
|
||||||
express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404, because we don't have this video
|
express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video
|
||||||
)
|
)
|
||||||
|
|
||||||
staticRouter.use(
|
staticRouter.use(
|
||||||
|
|
|
@ -571,6 +571,7 @@ const STATIC_PATHS = {
|
||||||
THUMBNAILS: '/static/thumbnails/',
|
THUMBNAILS: '/static/thumbnails/',
|
||||||
TORRENTS: '/static/torrents/',
|
TORRENTS: '/static/torrents/',
|
||||||
WEBSEED: '/static/webseed/',
|
WEBSEED: '/static/webseed/',
|
||||||
|
REDUNDANCY: '/static/redundancy/',
|
||||||
AVATARS: '/static/avatars/',
|
AVATARS: '/static/avatars/',
|
||||||
VIDEO_CAPTIONS: '/static/video-captions/'
|
VIDEO_CAPTIONS: '/static/video-captions/'
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,13 +145,13 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
|
||||||
|
|
||||||
const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT)
|
const tmpPath = await downloadWebTorrentVideo({ magnetUri }, VIDEO_IMPORT_TIMEOUT)
|
||||||
|
|
||||||
const destPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename(file))
|
const destPath = join(CONFIG.STORAGE.REDUNDANCY_DIR, video.getVideoFilename(file))
|
||||||
await rename(tmpPath, destPath)
|
await rename(tmpPath, destPath)
|
||||||
|
|
||||||
const createdModel = await VideoRedundancyModel.create({
|
const createdModel = await VideoRedundancyModel.create({
|
||||||
expiresOn: this.buildNewExpiration(redundancy.minLifetime),
|
expiresOn: this.buildNewExpiration(redundancy.minLifetime),
|
||||||
url: getVideoCacheFileActivityPubUrl(file),
|
url: getVideoCacheFileActivityPubUrl(file),
|
||||||
fileUrl: video.getVideoFileUrl(file, CONFIG.WEBSERVER.URL),
|
fileUrl: video.getVideoRedundancyUrl(file, CONFIG.WEBSERVER.URL),
|
||||||
strategy: redundancy.strategy,
|
strategy: redundancy.strategy,
|
||||||
videoFileId: file.id,
|
videoFileId: file.id,
|
||||||
actorId: serverActor.id
|
actorId: serverActor.id
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import { ActorModel } from '../activitypub/actor'
|
import { ActorModel } from '../activitypub/actor'
|
||||||
import { getVideoSort, throwIfNotValid } from '../utils'
|
import { getVideoSort, throwIfNotValid } from '../utils'
|
||||||
import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||||
import { CONFIG, CONSTRAINTS_FIELDS, VIDEO_EXT_MIMETYPE } from '../../initializers'
|
import { CONFIG, CONSTRAINTS_FIELDS, STATIC_PATHS, VIDEO_EXT_MIMETYPE } from '../../initializers'
|
||||||
import { VideoFileModel } from '../video/video-file'
|
import { VideoFileModel } from '../video/video-file'
|
||||||
import { getServerActor } from '../../helpers/utils'
|
import { getServerActor } from '../../helpers/utils'
|
||||||
import { VideoModel } from '../video/video'
|
import { VideoModel } from '../video/video'
|
||||||
|
@ -124,7 +124,7 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
|
||||||
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
|
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
|
||||||
logger.info('Removing duplicated video file %s.', logIdentifier)
|
logger.info('Removing duplicated video file %s.', logIdentifier)
|
||||||
|
|
||||||
videoFile.Video.removeFile(videoFile)
|
videoFile.Video.removeFile(videoFile, true)
|
||||||
.catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
|
.catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -1538,8 +1538,10 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
.catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err }))
|
.catch(err => logger.warn('Cannot delete preview %s.', previewPath, { err }))
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFile (videoFile: VideoFileModel) {
|
removeFile (videoFile: VideoFileModel, isRedundancy = false) {
|
||||||
const filePath = join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile))
|
const baseDir = isRedundancy ? CONFIG.STORAGE.REDUNDANCY_DIR : CONFIG.STORAGE.VIDEOS_DIR
|
||||||
|
|
||||||
|
const filePath = join(baseDir, this.getVideoFilename(videoFile))
|
||||||
return remove(filePath)
|
return remove(filePath)
|
||||||
.catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
|
.catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
|
||||||
}
|
}
|
||||||
|
@ -1617,6 +1619,10 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile)
|
return baseUrlHttp + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getVideoRedundancyUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
|
||||||
|
return baseUrlHttp + STATIC_PATHS.REDUNDANCY + this.getVideoFilename(videoFile)
|
||||||
|
}
|
||||||
|
|
||||||
getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
|
getVideoFileDownloadUrl (videoFile: VideoFileModel, baseUrlHttp: string) {
|
||||||
return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile)
|
return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + this.getVideoFilename(videoFile)
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st
|
||||||
if (!videoUUID) videoUUID = video1Server2UUID
|
if (!videoUUID) videoUUID = video1Server2UUID
|
||||||
|
|
||||||
const webseeds = [
|
const webseeds = [
|
||||||
'http://localhost:9001/static/webseed/' + videoUUID,
|
'http://localhost:9001/static/redundancy/' + videoUUID,
|
||||||
'http://localhost:9002/static/webseed/' + videoUUID
|
'http://localhost:9002/static/webseed/' + videoUUID
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -148,20 +148,23 @@ async function check2Webseeds (strategy: VideoRedundancyStrategy, videoUUID?: st
|
||||||
for (const file of video.files) {
|
for (const file of video.files) {
|
||||||
checkMagnetWebseeds(file, webseeds, server)
|
checkMagnetWebseeds(file, webseeds, server)
|
||||||
|
|
||||||
// Only servers 1 and 2 have the video
|
|
||||||
if (server.serverNumber !== 3) {
|
|
||||||
await makeGetRequest({
|
await makeGetRequest({
|
||||||
url: server.url,
|
url: servers[0].url,
|
||||||
|
statusCodeExpected: 200,
|
||||||
|
path: '/static/redundancy/' + `${videoUUID}-${file.resolution.id}.mp4`,
|
||||||
|
contentType: null
|
||||||
|
})
|
||||||
|
await makeGetRequest({
|
||||||
|
url: servers[1].url,
|
||||||
statusCodeExpected: 200,
|
statusCodeExpected: 200,
|
||||||
path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`,
|
path: '/static/webseed/' + `${videoUUID}-${file.resolution.id}.mp4`,
|
||||||
contentType: null
|
contentType: null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (const directory of [ 'test1', 'test2' ]) {
|
for (const directory of [ 'test1/redundancy', 'test2/videos' ]) {
|
||||||
const files = await readdir(join(root(), directory, 'videos'))
|
const files = await readdir(join(root(), directory))
|
||||||
expect(files).to.have.length.at.least(4)
|
expect(files).to.have.length.at.least(4)
|
||||||
|
|
||||||
for (const resolution of [ 240, 360, 480, 720 ]) {
|
for (const resolution of [ 240, 360, 480, 720 ]) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ server {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Bypass PeerTube for performance reasons. Could be removed
|
# Bypass PeerTube for performance reasons. Could be removed
|
||||||
location /static/webseed {
|
location ~ ^/static/(webseed|redundancy)/ {
|
||||||
# Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
|
# Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
|
||||||
limit_rate 800k;
|
limit_rate 800k;
|
||||||
|
|
||||||
|
@ -128,7 +128,12 @@ server {
|
||||||
access_log off;
|
access_log off;
|
||||||
}
|
}
|
||||||
|
|
||||||
alias /var/www/peertube/storage/videos;
|
root /var/www/peertube/storage;
|
||||||
|
|
||||||
|
rewrite ^/static/webseed/(.*)$ /videos/$1 break;
|
||||||
|
rewrite ^/static/redundancy/(.*)$ /redundancy/$1 break;
|
||||||
|
|
||||||
|
try_files $uri /;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Websocket tracker
|
# Websocket tracker
|
||||||
|
|
Loading…
Reference in New Issue