diff options
Diffstat (limited to 'server/lib/job-queue/handlers/video-transcoding.ts')
-rw-r--r-- | server/lib/job-queue/handlers/video-transcoding.ts | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 48cac517e..e9b84ecd6 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -8,18 +8,39 @@ import { retryTransactionWrapper } from '../../../helpers/database-utils' | |||
8 | import { sequelizeTypescript } from '../../../initializers' | 8 | import { sequelizeTypescript } from '../../../initializers' |
9 | import * as Bluebird from 'bluebird' | 9 | import * as Bluebird from 'bluebird' |
10 | import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' | 10 | import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' |
11 | import { generateHlsPlaylist, optimizeVideofile, transcodeOriginalVideofile } from '../../video-transcoding' | 11 | import { generateHlsPlaylist, optimizeVideofile, transcodeOriginalVideofile, mergeAudioVideofile } from '../../video-transcoding' |
12 | import { Notifier } from '../../notifier' | 12 | import { Notifier } from '../../notifier' |
13 | import { CONFIG } from '../../../initializers/config' | 13 | import { CONFIG } from '../../../initializers/config' |
14 | 14 | ||
15 | export type VideoTranscodingPayload = { | 15 | interface BaseTranscodingPayload { |
16 | videoUUID: string | 16 | videoUUID: string |
17 | resolution?: VideoResolution | ||
18 | isNewVideo?: boolean | 17 | isNewVideo?: boolean |
18 | } | ||
19 | |||
20 | interface HLSTranscodingPayload extends BaseTranscodingPayload { | ||
21 | type: 'hls' | ||
22 | isPortraitMode?: boolean | ||
23 | resolution: VideoResolution | ||
24 | } | ||
25 | |||
26 | interface NewResolutionTranscodingPayload extends BaseTranscodingPayload { | ||
27 | type: 'new-resolution' | ||
19 | isPortraitMode?: boolean | 28 | isPortraitMode?: boolean |
20 | generateHlsPlaylist?: boolean | 29 | resolution: VideoResolution |
30 | } | ||
31 | |||
32 | interface MergeAudioTranscodingPayload extends BaseTranscodingPayload { | ||
33 | type: 'merge-audio' | ||
34 | resolution: VideoResolution | ||
35 | } | ||
36 | |||
37 | interface OptimizeTranscodingPayload extends BaseTranscodingPayload { | ||
38 | type: 'optimize' | ||
21 | } | 39 | } |
22 | 40 | ||
41 | export type VideoTranscodingPayload = HLSTranscodingPayload | NewResolutionTranscodingPayload | ||
42 | | OptimizeTranscodingPayload | MergeAudioTranscodingPayload | ||
43 | |||
23 | async function processVideoTranscoding (job: Bull.Job) { | 44 | async function processVideoTranscoding (job: Bull.Job) { |
24 | const payload = job.data as VideoTranscodingPayload | 45 | const payload = job.data as VideoTranscodingPayload |
25 | logger.info('Processing video file in job %d.', job.id) | 46 | logger.info('Processing video file in job %d.', job.id) |
@@ -31,14 +52,18 @@ async function processVideoTranscoding (job: Bull.Job) { | |||
31 | return undefined | 52 | return undefined |
32 | } | 53 | } |
33 | 54 | ||
34 | if (payload.generateHlsPlaylist) { | 55 | if (payload.type === 'hls') { |
35 | await generateHlsPlaylist(video, payload.resolution, payload.isPortraitMode || false) | 56 | await generateHlsPlaylist(video, payload.resolution, payload.isPortraitMode || false) |
36 | 57 | ||
37 | await retryTransactionWrapper(onHlsPlaylistGenerationSuccess, video) | 58 | await retryTransactionWrapper(onHlsPlaylistGenerationSuccess, video) |
38 | } else if (payload.resolution) { // Transcoding in other resolution | 59 | } else if (payload.type === 'new-resolution') { |
39 | await transcodeOriginalVideofile(video, payload.resolution, payload.isPortraitMode || false) | 60 | await transcodeOriginalVideofile(video, payload.resolution, payload.isPortraitMode || false) |
40 | 61 | ||
41 | await retryTransactionWrapper(publishVideoIfNeeded, video, payload) | 62 | await retryTransactionWrapper(publishNewResolutionIfNeeded, video, payload) |
63 | } else if (payload.type === 'merge-audio') { | ||
64 | await mergeAudioVideofile(video, payload.resolution) | ||
65 | |||
66 | await retryTransactionWrapper(publishNewResolutionIfNeeded, video, payload) | ||
42 | } else { | 67 | } else { |
43 | await optimizeVideofile(video) | 68 | await optimizeVideofile(video) |
44 | 69 | ||
@@ -62,7 +87,7 @@ async function onHlsPlaylistGenerationSuccess (video: VideoModel) { | |||
62 | }) | 87 | }) |
63 | } | 88 | } |
64 | 89 | ||
65 | async function publishVideoIfNeeded (video: VideoModel, payload?: VideoTranscodingPayload) { | 90 | async function publishNewResolutionIfNeeded (video: VideoModel, payload?: NewResolutionTranscodingPayload | MergeAudioTranscodingPayload) { |
66 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { | 91 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { |
67 | // Maybe the video changed in database, refresh it | 92 | // Maybe the video changed in database, refresh it |
68 | let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) | 93 | let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.uuid, t) |
@@ -94,7 +119,7 @@ async function publishVideoIfNeeded (video: VideoModel, payload?: VideoTranscodi | |||
94 | await createHlsJobIfEnabled(payload) | 119 | await createHlsJobIfEnabled(payload) |
95 | } | 120 | } |
96 | 121 | ||
97 | async function onVideoFileOptimizerSuccess (videoArg: VideoModel, payload: VideoTranscodingPayload) { | 122 | async function onVideoFileOptimizerSuccess (videoArg: VideoModel, payload: OptimizeTranscodingPayload) { |
98 | if (videoArg === undefined) return undefined | 123 | if (videoArg === undefined) return undefined |
99 | 124 | ||
100 | // Outside the transaction (IO on disk) | 125 | // Outside the transaction (IO on disk) |
@@ -120,6 +145,7 @@ async function onVideoFileOptimizerSuccess (videoArg: VideoModel, payload: Video | |||
120 | 145 | ||
121 | for (const resolution of resolutionsEnabled) { | 146 | for (const resolution of resolutionsEnabled) { |
122 | const dataInput = { | 147 | const dataInput = { |
148 | type: 'new-resolution' as 'new-resolution', | ||
123 | videoUUID: videoDatabase.uuid, | 149 | videoUUID: videoDatabase.uuid, |
124 | resolution | 150 | resolution |
125 | } | 151 | } |
@@ -149,27 +175,27 @@ async function onVideoFileOptimizerSuccess (videoArg: VideoModel, payload: Video | |||
149 | if (payload.isNewVideo) Notifier.Instance.notifyOnNewVideo(videoDatabase) | 175 | if (payload.isNewVideo) Notifier.Instance.notifyOnNewVideo(videoDatabase) |
150 | if (videoPublished) Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) | 176 | if (videoPublished) Notifier.Instance.notifyOnVideoPublishedAfterTranscoding(videoDatabase) |
151 | 177 | ||
152 | await createHlsJobIfEnabled(Object.assign({}, payload, { resolution: videoDatabase.getOriginalFile().resolution })) | 178 | const hlsPayload = Object.assign({}, payload, { resolution: videoDatabase.getOriginalFile().resolution }) |
179 | await createHlsJobIfEnabled(hlsPayload) | ||
153 | } | 180 | } |
154 | 181 | ||
155 | // --------------------------------------------------------------------------- | 182 | // --------------------------------------------------------------------------- |
156 | 183 | ||
157 | export { | 184 | export { |
158 | processVideoTranscoding, | 185 | processVideoTranscoding, |
159 | publishVideoIfNeeded | 186 | publishNewResolutionIfNeeded |
160 | } | 187 | } |
161 | 188 | ||
162 | // --------------------------------------------------------------------------- | 189 | // --------------------------------------------------------------------------- |
163 | 190 | ||
164 | function createHlsJobIfEnabled (payload?: VideoTranscodingPayload) { | 191 | function createHlsJobIfEnabled (payload?: { videoUUID: string, resolution: number, isPortraitMode?: boolean }) { |
165 | // Generate HLS playlist? | 192 | // Generate HLS playlist? |
166 | if (payload && CONFIG.TRANSCODING.HLS.ENABLED) { | 193 | if (payload && CONFIG.TRANSCODING.HLS.ENABLED) { |
167 | const hlsTranscodingPayload = { | 194 | const hlsTranscodingPayload = { |
195 | type: 'hls' as 'hls', | ||
168 | videoUUID: payload.videoUUID, | 196 | videoUUID: payload.videoUUID, |
169 | resolution: payload.resolution, | 197 | resolution: payload.resolution, |
170 | isPortraitMode: payload.isPortraitMode, | 198 | isPortraitMode: payload.isPortraitMode |
171 | |||
172 | generateHlsPlaylist: true | ||
173 | } | 199 | } |
174 | 200 | ||
175 | return JobQueue.Instance.createJob({ type: 'video-transcoding', payload: hlsTranscodingPayload }) | 201 | return JobQueue.Instance.createJob({ type: 'video-transcoding', payload: hlsTranscodingPayload }) |