aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/video-path-manager.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/video-path-manager.ts')
-rw-r--r--server/lib/video-path-manager.ts174
1 files changed, 0 insertions, 174 deletions
diff --git a/server/lib/video-path-manager.ts b/server/lib/video-path-manager.ts
deleted file mode 100644
index 133544bb2..000000000
--- a/server/lib/video-path-manager.ts
+++ /dev/null
@@ -1,174 +0,0 @@
1import { Mutex } from 'async-mutex'
2import { remove } from 'fs-extra'
3import { extname, join } from 'path'
4import { logger, loggerTagsFactory } from '@server/helpers/logger'
5import { extractVideo } from '@server/helpers/video'
6import { CONFIG } from '@server/initializers/config'
7import { DIRECTORIES } from '@server/initializers/constants'
8import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '@server/types/models'
9import { buildUUID } from '@shared/extra-utils'
10import { VideoStorage } from '@shared/models'
11import { makeHLSFileAvailable, makeWebVideoFileAvailable } from './object-storage'
12import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
13import { isVideoInPrivateDirectory } from './video-privacy'
14
15type MakeAvailableCB <T> = (path: string) => Promise<T> | T
16
17const lTags = loggerTagsFactory('video-path-manager')
18
19class VideoPathManager {
20
21 private static instance: VideoPathManager
22
23 // Key is a video UUID
24 private readonly videoFileMutexStore = new Map<string, Mutex>()
25
26 private constructor () {}
27
28 getFSHLSOutputPath (video: MVideo, filename?: string) {
29 const base = getHLSDirectory(video)
30 if (!filename) return base
31
32 return join(base, filename)
33 }
34
35 getFSRedundancyVideoFilePath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
36 if (videoFile.isHLS()) {
37 const video = extractVideo(videoOrPlaylist)
38
39 return join(getHLSRedundancyDirectory(video), videoFile.filename)
40 }
41
42 return join(CONFIG.STORAGE.REDUNDANCY_DIR, videoFile.filename)
43 }
44
45 getFSVideoFileOutputPath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
46 const video = extractVideo(videoOrPlaylist)
47
48 if (videoFile.isHLS()) {
49 return join(getHLSDirectory(video), videoFile.filename)
50 }
51
52 if (isVideoInPrivateDirectory(video.privacy)) {
53 return join(DIRECTORIES.VIDEOS.PRIVATE, videoFile.filename)
54 }
55
56 return join(DIRECTORIES.VIDEOS.PUBLIC, videoFile.filename)
57 }
58
59 async makeAvailableVideoFile <T> (videoFile: MVideoFileVideo | MVideoFileStreamingPlaylistVideo, cb: MakeAvailableCB<T>) {
60 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
61 return this.makeAvailableFactory(
62 () => this.getFSVideoFileOutputPath(videoFile.getVideoOrStreamingPlaylist(), videoFile),
63 false,
64 cb
65 )
66 }
67
68 const destination = this.buildTMPDestination(videoFile.filename)
69
70 if (videoFile.isHLS()) {
71 const playlist = (videoFile as MVideoFileStreamingPlaylistVideo).VideoStreamingPlaylist
72
73 return this.makeAvailableFactory(
74 () => makeHLSFileAvailable(playlist, videoFile.filename, destination),
75 true,
76 cb
77 )
78 }
79
80 return this.makeAvailableFactory(
81 () => makeWebVideoFileAvailable(videoFile.filename, destination),
82 true,
83 cb
84 )
85 }
86
87 async makeAvailableResolutionPlaylistFile <T> (videoFile: MVideoFileStreamingPlaylistVideo, cb: MakeAvailableCB<T>) {
88 const filename = getHlsResolutionPlaylistFilename(videoFile.filename)
89
90 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
91 return this.makeAvailableFactory(
92 () => join(getHLSDirectory(videoFile.getVideo()), filename),
93 false,
94 cb
95 )
96 }
97
98 const playlist = videoFile.VideoStreamingPlaylist
99 return this.makeAvailableFactory(
100 () => makeHLSFileAvailable(playlist, filename, this.buildTMPDestination(filename)),
101 true,
102 cb
103 )
104 }
105
106 async makeAvailablePlaylistFile <T> (playlist: MStreamingPlaylistVideo, filename: string, cb: MakeAvailableCB<T>) {
107 if (playlist.storage === VideoStorage.FILE_SYSTEM) {
108 return this.makeAvailableFactory(
109 () => join(getHLSDirectory(playlist.Video), filename),
110 false,
111 cb
112 )
113 }
114
115 return this.makeAvailableFactory(
116 () => makeHLSFileAvailable(playlist, filename, this.buildTMPDestination(filename)),
117 true,
118 cb
119 )
120 }
121
122 async lockFiles (videoUUID: string) {
123 if (!this.videoFileMutexStore.has(videoUUID)) {
124 this.videoFileMutexStore.set(videoUUID, new Mutex())
125 }
126
127 const mutex = this.videoFileMutexStore.get(videoUUID)
128 const releaser = await mutex.acquire()
129
130 logger.debug('Locked files of %s.', videoUUID, lTags(videoUUID))
131
132 return releaser
133 }
134
135 unlockFiles (videoUUID: string) {
136 const mutex = this.videoFileMutexStore.get(videoUUID)
137
138 mutex.release()
139
140 logger.debug('Released lockfiles of %s.', videoUUID, lTags(videoUUID))
141 }
142
143 private async makeAvailableFactory <T> (method: () => Promise<string> | string, clean: boolean, cb: MakeAvailableCB<T>) {
144 let result: T
145
146 const destination = await method()
147
148 try {
149 result = await cb(destination)
150 } catch (err) {
151 if (destination && clean) await remove(destination)
152 throw err
153 }
154
155 if (clean) await remove(destination)
156
157 return result
158 }
159
160 private buildTMPDestination (filename: string) {
161 return join(CONFIG.STORAGE.TMP_DIR, buildUUID() + extname(filename))
162
163 }
164
165 static get Instance () {
166 return this.instance || (this.instance = new this())
167 }
168}
169
170// ---------------------------------------------------------------------------
171
172export {
173 VideoPathManager
174}