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