diff options
Diffstat (limited to 'server/lib/jobs/transcoding-job-scheduler')
4 files changed, 152 insertions, 0 deletions
diff --git a/server/lib/jobs/transcoding-job-scheduler/index.ts b/server/lib/jobs/transcoding-job-scheduler/index.ts new file mode 100644 index 000000000..73152a1be --- /dev/null +++ b/server/lib/jobs/transcoding-job-scheduler/index.ts | |||
@@ -0,0 +1 @@ | |||
export * from './transcoding-job-scheduler' | |||
diff --git a/server/lib/jobs/transcoding-job-scheduler/transcoding-job-scheduler.ts b/server/lib/jobs/transcoding-job-scheduler/transcoding-job-scheduler.ts new file mode 100644 index 000000000..d7c614fb8 --- /dev/null +++ b/server/lib/jobs/transcoding-job-scheduler/transcoding-job-scheduler.ts | |||
@@ -0,0 +1,17 @@ | |||
1 | import { JobScheduler, JobHandler } from '../job-scheduler' | ||
2 | |||
3 | import * as videoFileOptimizer from './video-file-optimizer-handler' | ||
4 | import * as videoFileTranscoder from './video-file-transcoder-handler' | ||
5 | import { JobCategory } from '../../../../shared' | ||
6 | |||
7 | const jobHandlers: { [ handlerName: string ]: JobHandler<any> } = { | ||
8 | videoFileOptimizer, | ||
9 | videoFileTranscoder | ||
10 | } | ||
11 | const jobCategory: JobCategory = 'transcoding' | ||
12 | |||
13 | const transcodingJobScheduler = new JobScheduler(jobCategory, jobHandlers) | ||
14 | |||
15 | export { | ||
16 | transcodingJobScheduler | ||
17 | } | ||
diff --git a/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts new file mode 100644 index 000000000..ccded4721 --- /dev/null +++ b/server/lib/jobs/transcoding-job-scheduler/video-file-optimizer-handler.ts | |||
@@ -0,0 +1,85 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
2 | |||
3 | import { database as db } from '../../../initializers/database' | ||
4 | import { logger, computeResolutionsToTranscode } from '../../../helpers' | ||
5 | import { VideoInstance } from '../../../models' | ||
6 | import { addVideoToFriends } from '../../friends' | ||
7 | import { JobScheduler } from '../job-scheduler' | ||
8 | |||
9 | async function process (data: { videoUUID: string }, jobId: number) { | ||
10 | const video = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(data.videoUUID) | ||
11 | // No video, maybe deleted? | ||
12 | if (!video) { | ||
13 | logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) | ||
14 | return undefined | ||
15 | } | ||
16 | |||
17 | await video.optimizeOriginalVideofile() | ||
18 | |||
19 | return video | ||
20 | } | ||
21 | |||
22 | function onError (err: Error, jobId: number) { | ||
23 | logger.error('Error when optimized video file in job %d.', jobId, err) | ||
24 | return Promise.resolve() | ||
25 | } | ||
26 | |||
27 | async function onSuccess (jobId: number, video: VideoInstance) { | ||
28 | if (video === undefined) return undefined | ||
29 | |||
30 | logger.info('Job %d is a success.', jobId) | ||
31 | |||
32 | // Maybe the video changed in database, refresh it | ||
33 | const videoDatabase = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(video.uuid) | ||
34 | // Video does not exist anymore | ||
35 | if (!videoDatabase) return undefined | ||
36 | |||
37 | const remoteVideo = await videoDatabase.toAddRemoteJSON() | ||
38 | |||
39 | // Now we'll add the video's meta data to our friends | ||
40 | await addVideoToFriends(remoteVideo, null) | ||
41 | |||
42 | const originalFileHeight = await videoDatabase.getOriginalFileHeight() | ||
43 | // Create transcoding jobs if there are enabled resolutions | ||
44 | |||
45 | const resolutionsEnabled = computeResolutionsToTranscode(originalFileHeight) | ||
46 | logger.info( | ||
47 | 'Resolutions computed for video %s and origin file height of %d.', videoDatabase.uuid, originalFileHeight, | ||
48 | { resolutions: resolutionsEnabled } | ||
49 | ) | ||
50 | |||
51 | if (resolutionsEnabled.length !== 0) { | ||
52 | try { | ||
53 | await db.sequelize.transaction(async t => { | ||
54 | const tasks: Bluebird<any>[] = [] | ||
55 | |||
56 | for (const resolution of resolutionsEnabled) { | ||
57 | const dataInput = { | ||
58 | videoUUID: videoDatabase.uuid, | ||
59 | resolution | ||
60 | } | ||
61 | |||
62 | const p = JobScheduler.Instance.createJob(t, 'videoFileTranscoder', dataInput) | ||
63 | tasks.push(p) | ||
64 | } | ||
65 | |||
66 | await Promise.all(tasks) | ||
67 | }) | ||
68 | |||
69 | logger.info('Transcoding jobs created for uuid %s.', videoDatabase.uuid, { resolutionsEnabled }) | ||
70 | } catch (err) { | ||
71 | logger.warn('Cannot transcode the video.', err) | ||
72 | } | ||
73 | } else { | ||
74 | logger.info('No transcoding jobs created for video %s (no resolutions enabled).') | ||
75 | return undefined | ||
76 | } | ||
77 | } | ||
78 | |||
79 | // --------------------------------------------------------------------------- | ||
80 | |||
81 | export { | ||
82 | process, | ||
83 | onError, | ||
84 | onSuccess | ||
85 | } | ||
diff --git a/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts b/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts new file mode 100644 index 000000000..853645510 --- /dev/null +++ b/server/lib/jobs/transcoding-job-scheduler/video-file-transcoder-handler.ts | |||
@@ -0,0 +1,49 @@ | |||
1 | import { database as db } from '../../../initializers/database' | ||
2 | import { updateVideoToFriends } from '../../friends' | ||
3 | import { logger } from '../../../helpers' | ||
4 | import { VideoInstance } from '../../../models' | ||
5 | import { VideoResolution } from '../../../../shared' | ||
6 | |||
7 | async function process (data: { videoUUID: string, resolution: VideoResolution }, jobId: number) { | ||
8 | const video = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(data.videoUUID) | ||
9 | // No video, maybe deleted? | ||
10 | if (!video) { | ||
11 | logger.info('Do not process job %d, video does not exist.', jobId, { videoUUID: video.uuid }) | ||
12 | return undefined | ||
13 | } | ||
14 | |||
15 | await video.transcodeOriginalVideofile(data.resolution) | ||
16 | |||
17 | return video | ||
18 | } | ||
19 | |||
20 | function onError (err: Error, jobId: number) { | ||
21 | logger.error('Error when transcoding video file in job %d.', jobId, err) | ||
22 | return Promise.resolve() | ||
23 | } | ||
24 | |||
25 | async function onSuccess (jobId: number, video: VideoInstance) { | ||
26 | if (video === undefined) return undefined | ||
27 | |||
28 | logger.info('Job %d is a success.', jobId) | ||
29 | |||
30 | // Maybe the video changed in database, refresh it | ||
31 | const videoDatabase = await db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(video.uuid) | ||
32 | // Video does not exist anymore | ||
33 | if (!videoDatabase) return undefined | ||
34 | |||
35 | const remoteVideo = videoDatabase.toUpdateRemoteJSON() | ||
36 | |||
37 | // Now we'll add the video's meta data to our friends | ||
38 | await updateVideoToFriends(remoteVideo, null) | ||
39 | |||
40 | return undefined | ||
41 | } | ||
42 | |||
43 | // --------------------------------------------------------------------------- | ||
44 | |||
45 | export { | ||
46 | process, | ||
47 | onError, | ||
48 | onSuccess | ||
49 | } | ||