aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/job-queue/handlers/video-transcoding.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/lib/job-queue/handlers/video-transcoding.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/lib/job-queue/handlers/video-transcoding.ts')
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts150
1 files changed, 0 insertions, 150 deletions
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
deleted file mode 100644
index 1c8f4fd9f..000000000
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ /dev/null
@@ -1,150 +0,0 @@
1import { Job } from 'bullmq'
2import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
3import { generateHlsPlaylistResolution } from '@server/lib/transcoding/hls-transcoding'
4import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebVideoResolution } from '@server/lib/transcoding/web-transcoding'
5import { removeAllWebVideoFiles } from '@server/lib/video-file'
6import { VideoPathManager } from '@server/lib/video-path-manager'
7import { moveToFailedTranscodingState } from '@server/lib/video-state'
8import { UserModel } from '@server/models/user/user'
9import { VideoJobInfoModel } from '@server/models/video/video-job-info'
10import { MUser, MUserId, MVideoFullLight } from '@server/types/models'
11import {
12 HLSTranscodingPayload,
13 MergeAudioTranscodingPayload,
14 NewWebVideoResolutionTranscodingPayload,
15 OptimizeTranscodingPayload,
16 VideoTranscodingPayload
17} from '@shared/models'
18import { logger, loggerTagsFactory } from '../../../helpers/logger'
19import { VideoModel } from '../../../models/video/video'
20
21type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<void>
22
23const handlers: { [ id in VideoTranscodingPayload['type'] ]: HandlerFunction } = {
24 'new-resolution-to-hls': handleHLSJob,
25 'new-resolution-to-web-video': handleNewWebVideoResolutionJob,
26 'merge-audio-to-web-video': handleWebVideoMergeAudioJob,
27 'optimize-to-web-video': handleWebVideoOptimizeJob
28}
29
30const lTags = loggerTagsFactory('transcoding')
31
32async function processVideoTranscoding (job: Job) {
33 const payload = job.data as VideoTranscodingPayload
34 logger.info('Processing transcoding job %s.', job.id, lTags(payload.videoUUID))
35
36 const video = await VideoModel.loadFull(payload.videoUUID)
37 // No video, maybe deleted?
38 if (!video) {
39 logger.info('Do not process job %d, video does not exist.', job.id, lTags(payload.videoUUID))
40 return undefined
41 }
42
43 const user = await UserModel.loadByChannelActorId(video.VideoChannel.actorId)
44
45 const handler = handlers[payload.type]
46
47 if (!handler) {
48 await moveToFailedTranscodingState(video)
49 await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
50
51 throw new Error('Cannot find transcoding handler for ' + payload.type)
52 }
53
54 try {
55 await handler(job, payload, video, user)
56 } catch (error) {
57 await moveToFailedTranscodingState(video)
58
59 await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
60
61 throw error
62 }
63
64 return video
65}
66
67// ---------------------------------------------------------------------------
68
69export {
70 processVideoTranscoding
71}
72
73// ---------------------------------------------------------------------------
74// Job handlers
75// ---------------------------------------------------------------------------
76
77async function handleWebVideoMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
78 logger.info('Handling merge audio transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
79
80 await mergeAudioVideofile({ video, resolution: payload.resolution, fps: payload.fps, job })
81
82 logger.info('Merge audio transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
83
84 await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video })
85}
86
87async function handleWebVideoOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
88 logger.info('Handling optimize transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
89
90 await optimizeOriginalVideofile({ video, inputVideoFile: video.getMaxQualityFile(), quickTranscode: payload.quickTranscode, job })
91
92 logger.info('Optimize transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
93
94 await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video })
95}
96
97// ---------------------------------------------------------------------------
98
99async function handleNewWebVideoResolutionJob (job: Job, payload: NewWebVideoResolutionTranscodingPayload, video: MVideoFullLight) {
100 logger.info('Handling Web Video transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
101
102 await transcodeNewWebVideoResolution({ video, resolution: payload.resolution, fps: payload.fps, job })
103
104 logger.info('Web Video transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
105
106 await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })
107}
108
109// ---------------------------------------------------------------------------
110
111async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg: MVideoFullLight) {
112 logger.info('Handling HLS transcoding job for %s.', videoArg.uuid, lTags(videoArg.uuid), { payload })
113
114 const inputFileMutexReleaser = await VideoPathManager.Instance.lockFiles(videoArg.uuid)
115 let video: MVideoFullLight
116
117 try {
118 video = await VideoModel.loadFull(videoArg.uuid)
119
120 const videoFileInput = payload.copyCodecs
121 ? video.getWebVideoFile(payload.resolution)
122 : video.getMaxQualityFile()
123
124 const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist()
125
126 await VideoPathManager.Instance.makeAvailableVideoFile(videoFileInput.withVideoOrPlaylist(videoOrStreamingPlaylist), videoInputPath => {
127 return generateHlsPlaylistResolution({
128 video,
129 videoInputPath,
130 inputFileMutexReleaser,
131 resolution: payload.resolution,
132 fps: payload.fps,
133 copyCodecs: payload.copyCodecs,
134 job
135 })
136 })
137 } finally {
138 inputFileMutexReleaser()
139 }
140
141 logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
142
143 if (payload.deleteWebVideoFiles === true) {
144 logger.info('Removing Web Video files of %s now we have a HLS version of it.', video.uuid, lTags(video.uuid))
145
146 await removeAllWebVideoFiles(video)
147 }
148
149 await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })
150}