]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/video-path-manager.ts
chore(refactor): remove shared folder dependencies to the server
[github/Chocobozzz/PeerTube.git] / server / lib / video-path-manager.ts
1 import { remove } from 'fs-extra'
2 import { extname, join } from 'path'
3 import { buildUUID } from '@shared/core-utils/uuid'
4 import { extractVideo } from '@server/helpers/video'
5 import { CONFIG } from '@server/initializers/config'
6 import {
7 MStreamingPlaylistVideo,
8 MVideo,
9 MVideoFile,
10 MVideoFileStreamingPlaylistVideo,
11 MVideoFileVideo,
12 MVideoUUID
13 } from '@server/types/models'
14 import { VideoStorage } from '@shared/models'
15 import { makeHLSFileAvailable, makeWebTorrentFileAvailable } from './object-storage'
16 import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
17
18 type MakeAvailableCB <T> = (path: string) => Promise<T> | T
19
20 class 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
53 async makeAvailableVideoFile <T> (videoFile: MVideoFileVideo | MVideoFileStreamingPlaylistVideo, cb: MakeAvailableCB<T>) {
54 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
55 return this.makeAvailableFactory(
56 () => this.getFSVideoFileOutputPath(videoFile.getVideoOrStreamingPlaylist(), videoFile),
57 false,
58 cb
59 )
60 }
61
62 const destination = this.buildTMPDestination(videoFile.filename)
63
64 if (videoFile.isHLS()) {
65 const playlist = (videoFile as MVideoFileStreamingPlaylistVideo).VideoStreamingPlaylist
66
67 return this.makeAvailableFactory(
68 () => makeHLSFileAvailable(playlist, videoFile.filename, destination),
69 true,
70 cb
71 )
72 }
73
74 return this.makeAvailableFactory(
75 () => makeWebTorrentFileAvailable(videoFile.filename, destination),
76 true,
77 cb
78 )
79 }
80
81 async makeAvailableResolutionPlaylistFile <T> (videoFile: MVideoFileStreamingPlaylistVideo, cb: MakeAvailableCB<T>) {
82 const filename = getHlsResolutionPlaylistFilename(videoFile.filename)
83
84 if (videoFile.storage === VideoStorage.FILE_SYSTEM) {
85 return this.makeAvailableFactory(
86 () => join(getHLSDirectory(videoFile.getVideo()), filename),
87 false,
88 cb
89 )
90 }
91
92 const playlist = videoFile.VideoStreamingPlaylist
93 return this.makeAvailableFactory(
94 () => makeHLSFileAvailable(playlist, filename, this.buildTMPDestination(filename)),
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(
110 () => makeHLSFileAvailable(playlist, filename, this.buildTMPDestination(filename)),
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
145 export {
146 VideoPathManager
147 }