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.ts139
1 files changed, 139 insertions, 0 deletions
diff --git a/server/lib/video-path-manager.ts b/server/lib/video-path-manager.ts
new file mode 100644
index 000000000..4c5d0c89d
--- /dev/null
+++ b/server/lib/video-path-manager.ts
@@ -0,0 +1,139 @@
1import { remove } from 'fs-extra'
2import { extname, join } from 'path'
3import { buildUUID } from '@server/helpers/uuid'
4import { extractVideo } from '@server/helpers/video'
5import { CONFIG } from '@server/initializers/config'
6import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoUUID } from '@server/types/models'
7import { VideoStorage } from '@shared/models'
8import { makeHLSFileAvailable, makeWebTorrentFileAvailable } from './object-storage'
9import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
10
11type MakeAvailableCB <T> = (path: string) => Promise<T> | T
12
13class VideoPathManager {
14
15 private static instance: VideoPathManager
16
17 private constructor () {}
18
19 getFSHLSOutputPath (video: MVideoUUID, filename?: string) {
20 const base = getHLSDirectory(video)
21 if (!filename) return base
22
23 return join(base, filename)
24 }
25
26 getFSRedundancyVideoFilePath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
27 if (videoFile.isHLS()) {
28 const video = extractVideo(videoOrPlaylist)
29
30 return join(getHLSRedundancyDirectory(video), videoFile.filename)
31 }
32
33 return join(CONFIG.STORAGE.REDUNDANCY_DIR, videoFile.filename)
34 }
35
36 getFSVideoFileOutputPath (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) {
37 if (videoFile.isHLS()) {
38 const video = extractVideo(videoOrPlaylist)
39
40 return join(getHLSDirectory(video), videoFile.filename)
41 }
42
43 return join(CONFIG.STORAGE.VIDEOS_DIR, videoFile.filename)
44 }
45
46 async makeAvailableVideoFile <T> (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile, cb: MakeAvailableCB<T>) {
47 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
48 return this.makeAvailableFactory(
49 () => this.getFSVideoFileOutputPath(videoOrPlaylist, videoFile),
50 false,
51 cb
52 )
53 }
54
55 const destination = this.buildTMPDestination(videoFile.filename)
56
57 if (videoFile.isHLS()) {
58 const video = extractVideo(videoOrPlaylist)
59
60 return this.makeAvailableFactory(
61 () => makeHLSFileAvailable(videoOrPlaylist as MStreamingPlaylistVideo, video, videoFile.filename, destination),
62 true,
63 cb
64 )
65 }
66
67 return this.makeAvailableFactory(
68 () => makeWebTorrentFileAvailable(videoFile.filename, destination),
69 true,
70 cb
71 )
72 }
73
74 async makeAvailableResolutionPlaylistFile <T> (playlist: MStreamingPlaylistVideo, videoFile: MVideoFile, cb: MakeAvailableCB<T>) {
75 const filename = getHlsResolutionPlaylistFilename(videoFile.filename)
76
77 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
78 return this.makeAvailableFactory(
79 () => join(getHLSDirectory(playlist.Video), filename),
80 false,
81 cb
82 )
83 }
84
85 return this.makeAvailableFactory(
86 () => makeHLSFileAvailable(playlist, playlist.Video, filename, this.buildTMPDestination(filename)),
87 true,
88 cb
89 )
90 }
91
92 async makeAvailablePlaylistFile <T> (playlist: MStreamingPlaylistVideo, filename: string, cb: MakeAvailableCB<T>) {
93 if (playlist.storage === VideoStorage.FILE_SYSTEM) {
94 return this.makeAvailableFactory(
95 () => join(getHLSDirectory(playlist.Video), filename),
96 false,
97 cb
98 )
99 }
100
101 return this.makeAvailableFactory(
102 () => makeHLSFileAvailable(playlist, playlist.Video, filename, this.buildTMPDestination(filename)),
103 true,
104 cb
105 )
106 }
107
108 private async makeAvailableFactory <T> (method: () => Promise<string> | string, clean: boolean, cb: MakeAvailableCB<T>) {
109 let result: T
110
111 const destination = await method()
112
113 try {
114 result = await cb(destination)
115 } catch (err) {
116 if (destination && clean) await remove(destination)
117 throw err
118 }
119
120 if (clean) await remove(destination)
121
122 return result
123 }
124
125 private buildTMPDestination (filename: string) {
126 return join(CONFIG.STORAGE.TMP_DIR, buildUUID() + extname(filename))
127
128 }
129
130 static get Instance () {
131 return this.instance || (this.instance = new this())
132 }
133}
134
135// ---------------------------------------------------------------------------
136
137export {
138 VideoPathManager
139}