aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/api/video-playlist.ts8
-rw-r--r--server/controllers/api/videos/import.ts6
-rw-r--r--server/controllers/api/videos/live.ts4
-rw-r--r--server/controllers/api/videos/upload.ts4
-rw-r--r--server/controllers/download.ts4
-rw-r--r--server/controllers/lazy-static.ts100
6 files changed, 41 insertions, 85 deletions
diff --git a/server/controllers/api/video-playlist.ts b/server/controllers/api/video-playlist.ts
index fe00034ed..1568ee597 100644
--- a/server/controllers/api/video-playlist.ts
+++ b/server/controllers/api/video-playlist.ts
@@ -23,7 +23,7 @@ import { MIMETYPES, VIDEO_PLAYLIST_PRIVACIES } from '../../initializers/constant
23import { sequelizeTypescript } from '../../initializers/database' 23import { sequelizeTypescript } from '../../initializers/database'
24import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlaylist } from '../../lib/activitypub/send' 24import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlaylist } from '../../lib/activitypub/send'
25import { getLocalVideoPlaylistActivityPubUrl, getLocalVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url' 25import { getLocalVideoPlaylistActivityPubUrl, getLocalVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url'
26import { updatePlaylistMiniatureFromExisting } from '../../lib/thumbnail' 26import { updateLocalPlaylistMiniatureFromExisting } from '../../lib/thumbnail'
27import { 27import {
28 apiRateLimiter, 28 apiRateLimiter,
29 asyncMiddleware, 29 asyncMiddleware,
@@ -178,7 +178,7 @@ async function addVideoPlaylist (req: express.Request, res: express.Response) {
178 178
179 const thumbnailField = req.files['thumbnailfile'] 179 const thumbnailField = req.files['thumbnailfile']
180 const thumbnailModel = thumbnailField 180 const thumbnailModel = thumbnailField
181 ? await updatePlaylistMiniatureFromExisting({ 181 ? await updateLocalPlaylistMiniatureFromExisting({
182 inputPath: thumbnailField[0].path, 182 inputPath: thumbnailField[0].path,
183 playlist: videoPlaylist, 183 playlist: videoPlaylist,
184 automaticallyGenerated: false 184 automaticallyGenerated: false
@@ -220,7 +220,7 @@ async function updateVideoPlaylist (req: express.Request, res: express.Response)
220 220
221 const thumbnailField = req.files['thumbnailfile'] 221 const thumbnailField = req.files['thumbnailfile']
222 const thumbnailModel = thumbnailField 222 const thumbnailModel = thumbnailField
223 ? await updatePlaylistMiniatureFromExisting({ 223 ? await updateLocalPlaylistMiniatureFromExisting({
224 inputPath: thumbnailField[0].path, 224 inputPath: thumbnailField[0].path,
225 playlist: videoPlaylistInstance, 225 playlist: videoPlaylistInstance,
226 automaticallyGenerated: false 226 automaticallyGenerated: false
@@ -497,7 +497,7 @@ async function generateThumbnailForPlaylist (videoPlaylist: MVideoPlaylistThumbn
497 } 497 }
498 498
499 const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, videoMiniature.filename) 499 const inputPath = join(CONFIG.STORAGE.THUMBNAILS_DIR, videoMiniature.filename)
500 const thumbnailModel = await updatePlaylistMiniatureFromExisting({ 500 const thumbnailModel = await updateLocalPlaylistMiniatureFromExisting({
501 inputPath, 501 inputPath,
502 playlist: videoPlaylist, 502 playlist: videoPlaylist,
503 automaticallyGenerated: true, 503 automaticallyGenerated: true,
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts
index b8016140e..defe9efd4 100644
--- a/server/controllers/api/videos/import.ts
+++ b/server/controllers/api/videos/import.ts
@@ -14,7 +14,7 @@ import { getSecureTorrentName } from '../../../helpers/utils'
14import { CONFIG } from '../../../initializers/config' 14import { CONFIG } from '../../../initializers/config'
15import { MIMETYPES } from '../../../initializers/constants' 15import { MIMETYPES } from '../../../initializers/constants'
16import { JobQueue } from '../../../lib/job-queue/job-queue' 16import { JobQueue } from '../../../lib/job-queue/job-queue'
17import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' 17import { updateLocalVideoMiniatureFromExisting } from '../../../lib/thumbnail'
18import { 18import {
19 asyncMiddleware, 19 asyncMiddleware,
20 asyncRetryTransactionMiddleware, 20 asyncRetryTransactionMiddleware,
@@ -193,7 +193,7 @@ async function processThumbnail (req: express.Request, video: MVideoThumbnail) {
193 if (thumbnailField) { 193 if (thumbnailField) {
194 const thumbnailPhysicalFile = thumbnailField[0] 194 const thumbnailPhysicalFile = thumbnailField[0]
195 195
196 return updateVideoMiniatureFromExisting({ 196 return updateLocalVideoMiniatureFromExisting({
197 inputPath: thumbnailPhysicalFile.path, 197 inputPath: thumbnailPhysicalFile.path,
198 video, 198 video,
199 type: ThumbnailType.MINIATURE, 199 type: ThumbnailType.MINIATURE,
@@ -209,7 +209,7 @@ async function processPreview (req: express.Request, video: MVideoThumbnail): Pr
209 if (previewField) { 209 if (previewField) {
210 const previewPhysicalFile = previewField[0] 210 const previewPhysicalFile = previewField[0]
211 211
212 return updateVideoMiniatureFromExisting({ 212 return updateLocalVideoMiniatureFromExisting({
213 inputPath: previewPhysicalFile.path, 213 inputPath: previewPhysicalFile.path,
214 video, 214 video,
215 type: ThumbnailType.PREVIEW, 215 type: ThumbnailType.PREVIEW,
diff --git a/server/controllers/api/videos/live.ts b/server/controllers/api/videos/live.ts
index cf82c9791..e19e8c652 100644
--- a/server/controllers/api/videos/live.ts
+++ b/server/controllers/api/videos/live.ts
@@ -21,7 +21,7 @@ import { buildUUID, uuidToShort } from '@shared/extra-utils'
21import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoPrivacy, VideoState } from '@shared/models' 21import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoPrivacy, VideoState } from '@shared/models'
22import { logger } from '../../../helpers/logger' 22import { logger } from '../../../helpers/logger'
23import { sequelizeTypescript } from '../../../initializers/database' 23import { sequelizeTypescript } from '../../../initializers/database'
24import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' 24import { updateLocalVideoMiniatureFromExisting } from '../../../lib/thumbnail'
25import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares' 25import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares'
26import { VideoModel } from '../../../models/video/video' 26import { VideoModel } from '../../../models/video/video'
27import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' 27import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting'
@@ -166,7 +166,7 @@ async function addLiveVideo (req: express.Request, res: express.Response) {
166 video, 166 video,
167 files: req.files, 167 files: req.files,
168 fallback: type => { 168 fallback: type => {
169 return updateVideoMiniatureFromExisting({ 169 return updateLocalVideoMiniatureFromExisting({
170 inputPath: ASSETS_PATH.DEFAULT_LIVE_BACKGROUND, 170 inputPath: ASSETS_PATH.DEFAULT_LIVE_BACKGROUND,
171 video, 171 video,
172 type, 172 type,
diff --git a/server/controllers/api/videos/upload.ts b/server/controllers/api/videos/upload.ts
index 6c471ff90..0e07302d2 100644
--- a/server/controllers/api/videos/upload.ts
+++ b/server/controllers/api/videos/upload.ts
@@ -21,7 +21,7 @@ import { logger, loggerTagsFactory } from '../../../helpers/logger'
21import { MIMETYPES } from '../../../initializers/constants' 21import { MIMETYPES } from '../../../initializers/constants'
22import { sequelizeTypescript } from '../../../initializers/database' 22import { sequelizeTypescript } from '../../../initializers/database'
23import { Hooks } from '../../../lib/plugins/hooks' 23import { Hooks } from '../../../lib/plugins/hooks'
24import { generateVideoMiniature } from '../../../lib/thumbnail' 24import { generateLocalVideoMiniature } from '../../../lib/thumbnail'
25import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' 25import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist'
26import { 26import {
27 asyncMiddleware, 27 asyncMiddleware,
@@ -153,7 +153,7 @@ async function addVideo (options: {
153 const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({ 153 const [ thumbnailModel, previewModel ] = await buildVideoThumbnailsFromReq({
154 video, 154 video,
155 files, 155 files,
156 fallback: type => generateVideoMiniature({ video, videoFile, type }) 156 fallback: type => generateLocalVideoMiniature({ video, videoFile, type })
157 }) 157 })
158 158
159 const { videoCreated } = await sequelizeTypescript.transaction(async t => { 159 const { videoCreated } = await sequelizeTypescript.transaction(async t => {
diff --git a/server/controllers/download.ts b/server/controllers/download.ts
index 4c3ab0163..4b94e34bd 100644
--- a/server/controllers/download.ts
+++ b/server/controllers/download.ts
@@ -1,7 +1,7 @@
1import cors from 'cors' 1import cors from 'cors'
2import express from 'express' 2import express from 'express'
3import { logger } from '@server/helpers/logger' 3import { logger } from '@server/helpers/logger'
4import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' 4import { VideoTorrentsSimpleFileCache } from '@server/lib/files-cache'
5import { generateHLSFilePresignedUrl, generateWebVideoPresignedUrl } from '@server/lib/object-storage' 5import { generateHLSFilePresignedUrl, generateWebVideoPresignedUrl } from '@server/lib/object-storage'
6import { Hooks } from '@server/lib/plugins/hooks' 6import { Hooks } from '@server/lib/plugins/hooks'
7import { VideoPathManager } from '@server/lib/video-path-manager' 7import { VideoPathManager } from '@server/lib/video-path-manager'
@@ -43,7 +43,7 @@ export {
43// --------------------------------------------------------------------------- 43// ---------------------------------------------------------------------------
44 44
45async function downloadTorrent (req: express.Request, res: express.Response) { 45async function downloadTorrent (req: express.Request, res: express.Response) {
46 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename) 46 const result = await VideoTorrentsSimpleFileCache.Instance.getFilePath(req.params.filename)
47 if (!result) { 47 if (!result) {
48 return res.fail({ 48 return res.fail({
49 status: HttpStatusCode.NOT_FOUND_404, 49 status: HttpStatusCode.NOT_FOUND_404,
diff --git a/server/controllers/lazy-static.ts b/server/controllers/lazy-static.ts
index 6ffd39730..8e18b0642 100644
--- a/server/controllers/lazy-static.ts
+++ b/server/controllers/lazy-static.ts
@@ -1,14 +1,27 @@
1import cors from 'cors' 1import cors from 'cors'
2import express from 'express' 2import express from 'express'
3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' 3import { CONFIG } from '@server/initializers/config'
4import { MActorImage } from '@server/types/models'
5import { HttpStatusCode } from '../../shared/models/http/http-error-codes' 4import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
6import { logger } from '../helpers/logger' 5import { FILES_CACHE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants'
7import { ACTOR_IMAGES_SIZE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' 6import {
8import { VideosCaptionCache, VideosPreviewCache, VideosStoryboardCache } from '../lib/files-cache' 7 AvatarPermanentFileCache,
9import { actorImagePathUnsafeCache, downloadActorImageFromWorker } from '../lib/local-actor' 8 VideoCaptionsSimpleFileCache,
9 VideoPreviewsSimpleFileCache,
10 VideoStoryboardsSimpleFileCache,
11 VideoTorrentsSimpleFileCache
12} from '../lib/files-cache'
10import { asyncMiddleware, handleStaticError } from '../middlewares' 13import { asyncMiddleware, handleStaticError } from '../middlewares'
11import { ActorImageModel } from '../models/actor/actor-image' 14
15// ---------------------------------------------------------------------------
16// Cache initializations
17// ---------------------------------------------------------------------------
18
19VideoPreviewsSimpleFileCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, FILES_CACHE.PREVIEWS.MAX_AGE)
20VideoCaptionsSimpleFileCache.Instance.init(CONFIG.CACHE.VIDEO_CAPTIONS.SIZE, FILES_CACHE.VIDEO_CAPTIONS.MAX_AGE)
21VideoTorrentsSimpleFileCache.Instance.init(CONFIG.CACHE.TORRENTS.SIZE, FILES_CACHE.TORRENTS.MAX_AGE)
22VideoStoryboardsSimpleFileCache.Instance.init(CONFIG.CACHE.STORYBOARDS.SIZE, FILES_CACHE.STORYBOARDS.MAX_AGE)
23
24// ---------------------------------------------------------------------------
12 25
13const lazyStaticRouter = express.Router() 26const lazyStaticRouter = express.Router()
14 27
@@ -60,94 +73,37 @@ export {
60 73
61// --------------------------------------------------------------------------- 74// ---------------------------------------------------------------------------
62 75
63async function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { 76const avatarPermanentFileCache = new AvatarPermanentFileCache()
64 const filename = req.params.filename
65
66 if (actorImagePathUnsafeCache.has(filename)) {
67 return res.sendFile(actorImagePathUnsafeCache.get(filename), { maxAge: STATIC_MAX_AGE.SERVER })
68 }
69
70 const image = await ActorImageModel.loadByName(filename)
71 if (!image) return res.status(HttpStatusCode.NOT_FOUND_404).end()
72
73 if (image.onDisk === false) {
74 if (!image.fileUrl) return res.status(HttpStatusCode.NOT_FOUND_404).end()
75
76 logger.info('Lazy serve remote actor image %s.', image.fileUrl)
77 77
78 try { 78function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) {
79 await downloadActorImageFromWorker({ 79 const filename = req.params.filename
80 filename: image.filename,
81 fileUrl: image.fileUrl,
82 size: getActorImageSize(image),
83 type: image.type
84 })
85 } catch (err) {
86 logger.warn('Cannot process remote actor image %s.', image.fileUrl, { err })
87 return res.status(HttpStatusCode.NOT_FOUND_404).end()
88 }
89
90 image.onDisk = true
91 image.save()
92 .catch(err => logger.error('Cannot save new actor image disk state.', { err }))
93 }
94
95 const path = image.getPath()
96
97 actorImagePathUnsafeCache.set(filename, path)
98
99 return res.sendFile(path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }, (err: any) => {
100 if (!err) return
101
102 // It seems this actor image is not on the disk anymore
103 if (err.status === HttpStatusCode.NOT_FOUND_404 && !image.isOwned()) {
104 logger.error('Cannot lazy serve actor image %s.', filename, { err })
105
106 actorImagePathUnsafeCache.delete(filename)
107
108 image.onDisk = false
109 image.save()
110 .catch(err => logger.error('Cannot save new actor image disk state.', { err }))
111 }
112
113 return next(err)
114 })
115}
116
117function getActorImageSize (image: MActorImage): { width: number, height: number } {
118 if (image.width && image.height) {
119 return {
120 height: image.height,
121 width: image.width
122 }
123 }
124 80
125 return ACTOR_IMAGES_SIZE[image.type][0] 81 return avatarPermanentFileCache.lazyServe({ filename, res, next })
126} 82}
127 83
128async function getPreview (req: express.Request, res: express.Response) { 84async function getPreview (req: express.Request, res: express.Response) {
129 const result = await VideosPreviewCache.Instance.getFilePath(req.params.filename) 85 const result = await VideoPreviewsSimpleFileCache.Instance.getFilePath(req.params.filename)
130 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() 86 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end()
131 87
132 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) 88 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
133} 89}
134 90
135async function getStoryboard (req: express.Request, res: express.Response) { 91async function getStoryboard (req: express.Request, res: express.Response) {
136 const result = await VideosStoryboardCache.Instance.getFilePath(req.params.filename) 92 const result = await VideoStoryboardsSimpleFileCache.Instance.getFilePath(req.params.filename)
137 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() 93 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end()
138 94
139 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) 95 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
140} 96}
141 97
142async function getVideoCaption (req: express.Request, res: express.Response) { 98async function getVideoCaption (req: express.Request, res: express.Response) {
143 const result = await VideosCaptionCache.Instance.getFilePath(req.params.filename) 99 const result = await VideoCaptionsSimpleFileCache.Instance.getFilePath(req.params.filename)
144 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() 100 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end()
145 101
146 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER }) 102 return res.sendFile(result.path, { maxAge: STATIC_MAX_AGE.LAZY_SERVER })
147} 103}
148 104
149async function getTorrent (req: express.Request, res: express.Response) { 105async function getTorrent (req: express.Request, res: express.Response) {
150 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename) 106 const result = await VideoTorrentsSimpleFileCache.Instance.getFilePath(req.params.filename)
151 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end() 107 if (!result) return res.status(HttpStatusCode.NOT_FOUND_404).end()
152 108
153 // Torrents still use the old naming convention (video uuid + .torrent) 109 // Torrents still use the old naming convention (video uuid + .torrent)