aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/job-queue
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/job-queue')
-rw-r--r--server/lib/job-queue/handlers/manage-video-torrent.ts2
-rw-r--r--server/lib/job-queue/handlers/move-to-object-storage.ts6
-rw-r--r--server/lib/job-queue/handlers/video-live-ending.ts22
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts95
4 files changed, 75 insertions, 50 deletions
diff --git a/server/lib/job-queue/handlers/manage-video-torrent.ts b/server/lib/job-queue/handlers/manage-video-torrent.ts
index 03aa414c9..425915c96 100644
--- a/server/lib/job-queue/handlers/manage-video-torrent.ts
+++ b/server/lib/job-queue/handlers/manage-video-torrent.ts
@@ -82,7 +82,7 @@ async function loadStreamingPlaylistOrLog (streamingPlaylistId: number) {
82async function loadFileOrLog (videoFileId: number) { 82async function loadFileOrLog (videoFileId: number) {
83 if (!videoFileId) return undefined 83 if (!videoFileId) return undefined
84 84
85 const file = await VideoFileModel.loadWithVideo(videoFileId) 85 const file = await VideoFileModel.load(videoFileId)
86 86
87 if (!file) { 87 if (!file) {
88 logger.debug('Do not process torrent for file %d: does not exist anymore.', videoFileId) 88 logger.debug('Do not process torrent for file %d: does not exist anymore.', videoFileId)
diff --git a/server/lib/job-queue/handlers/move-to-object-storage.ts b/server/lib/job-queue/handlers/move-to-object-storage.ts
index 28c3d325d..0b68555d1 100644
--- a/server/lib/job-queue/handlers/move-to-object-storage.ts
+++ b/server/lib/job-queue/handlers/move-to-object-storage.ts
@@ -3,10 +3,10 @@ import { remove } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import { logger, loggerTagsFactory } from '@server/helpers/logger' 4import { logger, loggerTagsFactory } from '@server/helpers/logger'
5import { updateTorrentMetadata } from '@server/helpers/webtorrent' 5import { updateTorrentMetadata } from '@server/helpers/webtorrent'
6import { CONFIG } from '@server/initializers/config'
7import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants' 6import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
8import { storeHLSFileFromFilename, storeWebTorrentFile } from '@server/lib/object-storage' 7import { storeHLSFileFromFilename, storeWebTorrentFile } from '@server/lib/object-storage'
9import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' 8import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
9import { VideoPathManager } from '@server/lib/video-path-manager'
10import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state' 10import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state'
11import { VideoModel } from '@server/models/video/video' 11import { VideoModel } from '@server/models/video/video'
12import { VideoJobInfoModel } from '@server/models/video/video-job-info' 12import { VideoJobInfoModel } from '@server/models/video/video-job-info'
@@ -72,9 +72,9 @@ async function moveWebTorrentFiles (video: MVideoWithAllFiles) {
72 for (const file of video.VideoFiles) { 72 for (const file of video.VideoFiles) {
73 if (file.storage !== VideoStorage.FILE_SYSTEM) continue 73 if (file.storage !== VideoStorage.FILE_SYSTEM) continue
74 74
75 const fileUrl = await storeWebTorrentFile(file.filename) 75 const fileUrl = await storeWebTorrentFile(video, file)
76 76
77 const oldPath = join(CONFIG.STORAGE.VIDEOS_DIR, file.filename) 77 const oldPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, file)
78 await onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath }) 78 await onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath })
79 } 79 }
80} 80}
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts
index 7dbffc955..c6263f55a 100644
--- a/server/lib/job-queue/handlers/video-live-ending.ts
+++ b/server/lib/job-queue/handlers/video-live-ending.ts
@@ -18,6 +18,7 @@ import { VideoStreamingPlaylistModel } from '@server/models/video/video-streamin
18import { MVideo, MVideoLive, MVideoLiveSession, MVideoWithAllFiles } from '@server/types/models' 18import { MVideo, MVideoLive, MVideoLiveSession, MVideoWithAllFiles } from '@server/types/models'
19import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models' 19import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
20import { logger, loggerTagsFactory } from '../../../helpers/logger' 20import { logger, loggerTagsFactory } from '../../../helpers/logger'
21import { VideoPathManager } from '@server/lib/video-path-manager'
21 22
22const lTags = loggerTagsFactory('live', 'job') 23const lTags = loggerTagsFactory('live', 'job')
23 24
@@ -205,18 +206,27 @@ async function assignReplayFilesToVideo (options: {
205 const concatenatedTsFiles = await readdir(replayDirectory) 206 const concatenatedTsFiles = await readdir(replayDirectory)
206 207
207 for (const concatenatedTsFile of concatenatedTsFiles) { 208 for (const concatenatedTsFile of concatenatedTsFiles) {
209 const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
210
208 const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile) 211 const concatenatedTsFilePath = join(replayDirectory, concatenatedTsFile)
209 212
210 const probe = await ffprobePromise(concatenatedTsFilePath) 213 const probe = await ffprobePromise(concatenatedTsFilePath)
211 const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe) 214 const { audioStream } = await getAudioStream(concatenatedTsFilePath, probe)
212 const { resolution } = await getVideoStreamDimensionsInfo(concatenatedTsFilePath, probe) 215 const { resolution } = await getVideoStreamDimensionsInfo(concatenatedTsFilePath, probe)
213 216
214 await generateHlsPlaylistResolutionFromTS({ 217 try {
215 video, 218 await generateHlsPlaylistResolutionFromTS({
216 concatenatedTsFilePath, 219 video,
217 resolution, 220 inputFileMutexReleaser,
218 isAAC: audioStream?.codec_name === 'aac' 221 concatenatedTsFilePath,
219 }) 222 resolution,
223 isAAC: audioStream?.codec_name === 'aac'
224 })
225 } catch (err) {
226 logger.error('Cannot generate HLS playlist resolution from TS files.', { err })
227 }
228
229 inputFileMutexReleaser()
220 } 230 }
221 231
222 return video 232 return video
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
index b0e92acf7..48c675678 100644
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ b/server/lib/job-queue/handlers/video-transcoding.ts
@@ -94,15 +94,24 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, video: MV
94 94
95 const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist() 95 const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist()
96 96
97 await VideoPathManager.Instance.makeAvailableVideoFile(videoFileInput.withVideoOrPlaylist(videoOrStreamingPlaylist), videoInputPath => { 97 const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
98 return generateHlsPlaylistResolution({ 98
99 video, 99 try {
100 videoInputPath, 100 await videoFileInput.getVideo().reload()
101 resolution: payload.resolution, 101
102 copyCodecs: payload.copyCodecs, 102 await VideoPathManager.Instance.makeAvailableVideoFile(videoFileInput.withVideoOrPlaylist(videoOrStreamingPlaylist), videoInputPath => {
103 job 103 return generateHlsPlaylistResolution({
104 video,
105 videoInputPath,
106 inputFileMutexReleaser,
107 resolution: payload.resolution,
108 copyCodecs: payload.copyCodecs,
109 job
110 })
104 }) 111 })
105 }) 112 } finally {
113 inputFileMutexReleaser()
114 }
106 115
107 logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid)) 116 logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid))
108 117
@@ -177,38 +186,44 @@ async function onVideoFirstWebTorrentTranscoding (
177 transcodeType: TranscodeVODOptionsType, 186 transcodeType: TranscodeVODOptionsType,
178 user: MUserId 187 user: MUserId
179) { 188) {
180 const { resolution, audioStream } = await videoArg.probeMaxQualityFile() 189 const mutexReleaser = await VideoPathManager.Instance.lockFiles(videoArg.uuid)
181 190
182 // Maybe the video changed in database, refresh it 191 try {
183 const videoDatabase = await VideoModel.loadFull(videoArg.uuid) 192 // Maybe the video changed in database, refresh it
184 // Video does not exist anymore 193 const videoDatabase = await VideoModel.loadFull(videoArg.uuid)
185 if (!videoDatabase) return undefined 194 // Video does not exist anymore
186 195 if (!videoDatabase) return undefined
187 // Generate HLS version of the original file 196
188 const originalFileHLSPayload = { 197 const { resolution, audioStream } = await videoDatabase.probeMaxQualityFile()
189 ...payload, 198
190 199 // Generate HLS version of the original file
191 hasAudio: !!audioStream, 200 const originalFileHLSPayload = {
192 resolution: videoDatabase.getMaxQualityFile().resolution, 201 ...payload,
193 // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues 202
194 copyCodecs: transcodeType !== 'quick-transcode', 203 hasAudio: !!audioStream,
195 isMaxQuality: true 204 resolution: videoDatabase.getMaxQualityFile().resolution,
196 } 205 // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues
197 const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload) 206 copyCodecs: transcodeType !== 'quick-transcode',
198 const hasNewResolutions = await createLowerResolutionsJobs({ 207 isMaxQuality: true
199 video: videoDatabase, 208 }
200 user, 209 const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload)
201 videoFileResolution: resolution, 210 const hasNewResolutions = await createLowerResolutionsJobs({
202 hasAudio: !!audioStream, 211 video: videoDatabase,
203 type: 'webtorrent', 212 user,
204 isNewVideo: payload.isNewVideo ?? true 213 videoFileResolution: resolution,
205 }) 214 hasAudio: !!audioStream,
206 215 type: 'webtorrent',
207 await VideoJobInfoModel.decrease(videoDatabase.uuid, 'pendingTranscode') 216 isNewVideo: payload.isNewVideo ?? true
208 217 })
209 // Move to next state if there are no other resolutions to generate 218
210 if (!hasHls && !hasNewResolutions) { 219 await VideoJobInfoModel.decrease(videoDatabase.uuid, 'pendingTranscode')
211 await retryTransactionWrapper(moveToNextState, { video: videoDatabase, isNewVideo: payload.isNewVideo }) 220
221 // Move to next state if there are no other resolutions to generate
222 if (!hasHls && !hasNewResolutions) {
223 await retryTransactionWrapper(moveToNextState, { video: videoDatabase, isNewVideo: payload.isNewVideo })
224 }
225 } finally {
226 mutexReleaser()
212 } 227 }
213} 228}
214 229