diff options
Diffstat (limited to 'server/lib/job-queue/handlers/video-transcoding.ts')
-rw-r--r-- | server/lib/job-queue/handlers/video-transcoding.ts | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index b0e92acf7..3e6d23363 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -13,7 +13,6 @@ import { | |||
13 | MergeAudioTranscodingPayload, | 13 | MergeAudioTranscodingPayload, |
14 | NewWebTorrentResolutionTranscodingPayload, | 14 | NewWebTorrentResolutionTranscodingPayload, |
15 | OptimizeTranscodingPayload, | 15 | OptimizeTranscodingPayload, |
16 | VideoResolution, | ||
17 | VideoTranscodingPayload | 16 | VideoTranscodingPayload |
18 | } from '@shared/models' | 17 | } from '@shared/models' |
19 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 18 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
@@ -94,15 +93,24 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, video: MV | |||
94 | 93 | ||
95 | const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist() | 94 | const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist() |
96 | 95 | ||
97 | await VideoPathManager.Instance.makeAvailableVideoFile(videoFileInput.withVideoOrPlaylist(videoOrStreamingPlaylist), videoInputPath => { | 96 | const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid) |
98 | return generateHlsPlaylistResolution({ | 97 | |
99 | video, | 98 | try { |
100 | videoInputPath, | 99 | await videoFileInput.getVideo().reload() |
101 | resolution: payload.resolution, | 100 | |
102 | copyCodecs: payload.copyCodecs, | 101 | await VideoPathManager.Instance.makeAvailableVideoFile(videoFileInput.withVideoOrPlaylist(videoOrStreamingPlaylist), videoInputPath => { |
103 | job | 102 | return generateHlsPlaylistResolution({ |
103 | video, | ||
104 | videoInputPath, | ||
105 | inputFileMutexReleaser, | ||
106 | resolution: payload.resolution, | ||
107 | copyCodecs: payload.copyCodecs, | ||
108 | job | ||
109 | }) | ||
104 | }) | 110 | }) |
105 | }) | 111 | } finally { |
112 | inputFileMutexReleaser() | ||
113 | } | ||
106 | 114 | ||
107 | logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid)) | 115 | logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid)) |
108 | 116 | ||
@@ -177,38 +185,44 @@ async function onVideoFirstWebTorrentTranscoding ( | |||
177 | transcodeType: TranscodeVODOptionsType, | 185 | transcodeType: TranscodeVODOptionsType, |
178 | user: MUserId | 186 | user: MUserId |
179 | ) { | 187 | ) { |
180 | const { resolution, audioStream } = await videoArg.probeMaxQualityFile() | 188 | const mutexReleaser = await VideoPathManager.Instance.lockFiles(videoArg.uuid) |
181 | 189 | ||
182 | // Maybe the video changed in database, refresh it | 190 | try { |
183 | const videoDatabase = await VideoModel.loadFull(videoArg.uuid) | 191 | // Maybe the video changed in database, refresh it |
184 | // Video does not exist anymore | 192 | const videoDatabase = await VideoModel.loadFull(videoArg.uuid) |
185 | if (!videoDatabase) return undefined | 193 | // Video does not exist anymore |
186 | 194 | if (!videoDatabase) return undefined | |
187 | // Generate HLS version of the original file | 195 | |
188 | const originalFileHLSPayload = { | 196 | const { resolution, audioStream } = await videoDatabase.probeMaxQualityFile() |
189 | ...payload, | 197 | |
190 | 198 | // Generate HLS version of the original file | |
191 | hasAudio: !!audioStream, | 199 | const originalFileHLSPayload = { |
192 | resolution: videoDatabase.getMaxQualityFile().resolution, | 200 | ...payload, |
193 | // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues | 201 | |
194 | copyCodecs: transcodeType !== 'quick-transcode', | 202 | hasAudio: !!audioStream, |
195 | isMaxQuality: true | 203 | resolution: videoDatabase.getMaxQualityFile().resolution, |
196 | } | 204 | // If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues |
197 | const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload) | 205 | copyCodecs: transcodeType !== 'quick-transcode', |
198 | const hasNewResolutions = await createLowerResolutionsJobs({ | 206 | isMaxQuality: true |
199 | video: videoDatabase, | 207 | } |
200 | user, | 208 | const hasHls = await createHlsJobIfEnabled(user, originalFileHLSPayload) |
201 | videoFileResolution: resolution, | 209 | const hasNewResolutions = await createLowerResolutionsJobs({ |
202 | hasAudio: !!audioStream, | 210 | video: videoDatabase, |
203 | type: 'webtorrent', | 211 | user, |
204 | isNewVideo: payload.isNewVideo ?? true | 212 | videoFileResolution: resolution, |
205 | }) | 213 | hasAudio: !!audioStream, |
206 | 214 | type: 'webtorrent', | |
207 | await VideoJobInfoModel.decrease(videoDatabase.uuid, 'pendingTranscode') | 215 | isNewVideo: payload.isNewVideo ?? true |
208 | 216 | }) | |
209 | // Move to next state if there are no other resolutions to generate | 217 | |
210 | if (!hasHls && !hasNewResolutions) { | 218 | await VideoJobInfoModel.decrease(videoDatabase.uuid, 'pendingTranscode') |
211 | await retryTransactionWrapper(moveToNextState, { video: videoDatabase, isNewVideo: payload.isNewVideo }) | 219 | |
220 | // Move to next state if there are no other resolutions to generate | ||
221 | if (!hasHls && !hasNewResolutions) { | ||
222 | await retryTransactionWrapper(moveToNextState, { video: videoDatabase, isNewVideo: payload.isNewVideo }) | ||
223 | } | ||
224 | } finally { | ||
225 | mutexReleaser() | ||
212 | } | 226 | } |
213 | } | 227 | } |
214 | 228 | ||
@@ -266,7 +280,7 @@ async function createLowerResolutionsJobs (options: { | |||
266 | 280 | ||
267 | // Create transcoding jobs if there are enabled resolutions | 281 | // Create transcoding jobs if there are enabled resolutions |
268 | const resolutionsEnabled = await Hooks.wrapObject( | 282 | const resolutionsEnabled = await Hooks.wrapObject( |
269 | computeResolutionsToTranscode({ input: videoFileResolution, type: 'vod', includeInput: false, strictLower: true }), | 283 | computeResolutionsToTranscode({ input: videoFileResolution, type: 'vod', includeInput: false, strictLower: true, hasAudio }), |
270 | 'filter:transcoding.auto.resolutions-to-transcode.result', | 284 | 'filter:transcoding.auto.resolutions-to-transcode.result', |
271 | options | 285 | options |
272 | ) | 286 | ) |
@@ -274,8 +288,6 @@ async function createLowerResolutionsJobs (options: { | |||
274 | const resolutionCreated: string[] = [] | 288 | const resolutionCreated: string[] = [] |
275 | 289 | ||
276 | for (const resolution of resolutionsEnabled) { | 290 | for (const resolution of resolutionsEnabled) { |
277 | if (resolution === VideoResolution.H_NOVIDEO && hasAudio === false) continue | ||
278 | |||
279 | let dataInput: VideoTranscodingPayload | 291 | let dataInput: VideoTranscodingPayload |
280 | 292 | ||
281 | if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED && type === 'webtorrent') { | 293 | if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED && type === 'webtorrent') { |