diff options
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/api/video-playlist.ts | 8 | ||||
-rw-r--r-- | server/controllers/api/videos/import.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/videos/live.ts | 4 | ||||
-rw-r--r-- | server/controllers/api/videos/upload.ts | 4 | ||||
-rw-r--r-- | server/controllers/download.ts | 4 | ||||
-rw-r--r-- | server/controllers/lazy-static.ts | 100 |
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 | |||
23 | import { sequelizeTypescript } from '../../initializers/database' | 23 | import { sequelizeTypescript } from '../../initializers/database' |
24 | import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlaylist } from '../../lib/activitypub/send' | 24 | import { sendCreateVideoPlaylist, sendDeleteVideoPlaylist, sendUpdateVideoPlaylist } from '../../lib/activitypub/send' |
25 | import { getLocalVideoPlaylistActivityPubUrl, getLocalVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url' | 25 | import { getLocalVideoPlaylistActivityPubUrl, getLocalVideoPlaylistElementActivityPubUrl } from '../../lib/activitypub/url' |
26 | import { updatePlaylistMiniatureFromExisting } from '../../lib/thumbnail' | 26 | import { updateLocalPlaylistMiniatureFromExisting } from '../../lib/thumbnail' |
27 | import { | 27 | import { |
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' | |||
14 | import { CONFIG } from '../../../initializers/config' | 14 | import { CONFIG } from '../../../initializers/config' |
15 | import { MIMETYPES } from '../../../initializers/constants' | 15 | import { MIMETYPES } from '../../../initializers/constants' |
16 | import { JobQueue } from '../../../lib/job-queue/job-queue' | 16 | import { JobQueue } from '../../../lib/job-queue/job-queue' |
17 | import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' | 17 | import { updateLocalVideoMiniatureFromExisting } from '../../../lib/thumbnail' |
18 | import { | 18 | import { |
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' | |||
21 | import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoPrivacy, VideoState } from '@shared/models' | 21 | import { HttpStatusCode, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, UserRight, VideoPrivacy, VideoState } from '@shared/models' |
22 | import { logger } from '../../../helpers/logger' | 22 | import { logger } from '../../../helpers/logger' |
23 | import { sequelizeTypescript } from '../../../initializers/database' | 23 | import { sequelizeTypescript } from '../../../initializers/database' |
24 | import { updateVideoMiniatureFromExisting } from '../../../lib/thumbnail' | 24 | import { updateLocalVideoMiniatureFromExisting } from '../../../lib/thumbnail' |
25 | import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares' | 25 | import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, optionalAuthenticate } from '../../../middlewares' |
26 | import { VideoModel } from '../../../models/video/video' | 26 | import { VideoModel } from '../../../models/video/video' |
27 | import { VideoLiveReplaySettingModel } from '@server/models/video/video-live-replay-setting' | 27 | import { 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' | |||
21 | import { MIMETYPES } from '../../../initializers/constants' | 21 | import { MIMETYPES } from '../../../initializers/constants' |
22 | import { sequelizeTypescript } from '../../../initializers/database' | 22 | import { sequelizeTypescript } from '../../../initializers/database' |
23 | import { Hooks } from '../../../lib/plugins/hooks' | 23 | import { Hooks } from '../../../lib/plugins/hooks' |
24 | import { generateVideoMiniature } from '../../../lib/thumbnail' | 24 | import { generateLocalVideoMiniature } from '../../../lib/thumbnail' |
25 | import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' | 25 | import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist' |
26 | import { | 26 | import { |
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 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { logger } from '@server/helpers/logger' | 3 | import { logger } from '@server/helpers/logger' |
4 | import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' | 4 | import { VideoTorrentsSimpleFileCache } from '@server/lib/files-cache' |
5 | import { generateHLSFilePresignedUrl, generateWebVideoPresignedUrl } from '@server/lib/object-storage' | 5 | import { generateHLSFilePresignedUrl, generateWebVideoPresignedUrl } from '@server/lib/object-storage' |
6 | import { Hooks } from '@server/lib/plugins/hooks' | 6 | import { Hooks } from '@server/lib/plugins/hooks' |
7 | import { VideoPathManager } from '@server/lib/video-path-manager' | 7 | import { VideoPathManager } from '@server/lib/video-path-manager' |
@@ -43,7 +43,7 @@ export { | |||
43 | // --------------------------------------------------------------------------- | 43 | // --------------------------------------------------------------------------- |
44 | 44 | ||
45 | async function downloadTorrent (req: express.Request, res: express.Response) { | 45 | async 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 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' | 3 | import { CONFIG } from '@server/initializers/config' |
4 | import { MActorImage } from '@server/types/models' | ||
5 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' | 4 | import { HttpStatusCode } from '../../shared/models/http/http-error-codes' |
6 | import { logger } from '../helpers/logger' | 5 | import { FILES_CACHE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' |
7 | import { ACTOR_IMAGES_SIZE, LAZY_STATIC_PATHS, STATIC_MAX_AGE } from '../initializers/constants' | 6 | import { |
8 | import { VideosCaptionCache, VideosPreviewCache, VideosStoryboardCache } from '../lib/files-cache' | 7 | AvatarPermanentFileCache, |
9 | import { actorImagePathUnsafeCache, downloadActorImageFromWorker } from '../lib/local-actor' | 8 | VideoCaptionsSimpleFileCache, |
9 | VideoPreviewsSimpleFileCache, | ||
10 | VideoStoryboardsSimpleFileCache, | ||
11 | VideoTorrentsSimpleFileCache | ||
12 | } from '../lib/files-cache' | ||
10 | import { asyncMiddleware, handleStaticError } from '../middlewares' | 13 | import { asyncMiddleware, handleStaticError } from '../middlewares' |
11 | import { ActorImageModel } from '../models/actor/actor-image' | 14 | |
15 | // --------------------------------------------------------------------------- | ||
16 | // Cache initializations | ||
17 | // --------------------------------------------------------------------------- | ||
18 | |||
19 | VideoPreviewsSimpleFileCache.Instance.init(CONFIG.CACHE.PREVIEWS.SIZE, FILES_CACHE.PREVIEWS.MAX_AGE) | ||
20 | VideoCaptionsSimpleFileCache.Instance.init(CONFIG.CACHE.VIDEO_CAPTIONS.SIZE, FILES_CACHE.VIDEO_CAPTIONS.MAX_AGE) | ||
21 | VideoTorrentsSimpleFileCache.Instance.init(CONFIG.CACHE.TORRENTS.SIZE, FILES_CACHE.TORRENTS.MAX_AGE) | ||
22 | VideoStoryboardsSimpleFileCache.Instance.init(CONFIG.CACHE.STORYBOARDS.SIZE, FILES_CACHE.STORYBOARDS.MAX_AGE) | ||
23 | |||
24 | // --------------------------------------------------------------------------- | ||
12 | 25 | ||
13 | const lazyStaticRouter = express.Router() | 26 | const lazyStaticRouter = express.Router() |
14 | 27 | ||
@@ -60,94 +73,37 @@ export { | |||
60 | 73 | ||
61 | // --------------------------------------------------------------------------- | 74 | // --------------------------------------------------------------------------- |
62 | 75 | ||
63 | async function getActorImage (req: express.Request, res: express.Response, next: express.NextFunction) { | 76 | const 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 { | 78 | function 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 | |||
117 | function 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 | ||
128 | async function getPreview (req: express.Request, res: express.Response) { | 84 | async 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 | ||
135 | async function getStoryboard (req: express.Request, res: express.Response) { | 91 | async 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 | ||
142 | async function getVideoCaption (req: express.Request, res: express.Response) { | 98 | async 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 | ||
149 | async function getTorrent (req: express.Request, res: express.Response) { | 105 | async 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) |