aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/runners/jobs-files.ts6
-rw-r--r--server/controllers/api/runners/jobs.ts4
-rw-r--r--server/helpers/custom-validators/runners/jobs.ts16
-rw-r--r--server/lib/job-queue/handlers/video-studio-edition.ts6
-rw-r--r--server/lib/runners/job-handlers/abstract-job-handler.ts10
-rw-r--r--server/lib/runners/job-handlers/index.ts2
-rw-r--r--server/lib/runners/job-handlers/runner-job-handlers.ts4
-rw-r--r--server/lib/runners/job-handlers/video-studio-transcoding-job-handler.ts (renamed from server/lib/runners/job-handlers/video-edition-transcoding-job-handler.ts)24
-rw-r--r--server/lib/transcoding/default-transcoding-profiles.ts145
-rw-r--r--server/lib/video-studio.ts8
-rw-r--r--server/middlewares/validators/runners/job-files.ts4
-rw-r--r--server/tests/api/check-params/runners.ts10
-rw-r--r--server/tests/api/runners/runner-studio-transcoding.ts10
-rw-r--r--server/tests/api/transcoding/video-studio.ts4
14 files changed, 57 insertions, 196 deletions
diff --git a/server/controllers/api/runners/jobs-files.ts b/server/controllers/api/runners/jobs-files.ts
index 4efa40b3a..260d824a8 100644
--- a/server/controllers/api/runners/jobs-files.ts
+++ b/server/controllers/api/runners/jobs-files.ts
@@ -31,7 +31,7 @@ runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/studio/task-file
31 asyncMiddleware(jobOfRunnerGetValidator), 31 asyncMiddleware(jobOfRunnerGetValidator),
32 asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), 32 asyncMiddleware(runnerJobGetVideoTranscodingFileValidator),
33 runnerJobGetVideoStudioTaskFileValidator, 33 runnerJobGetVideoStudioTaskFileValidator,
34 getVideoEditionTaskFile 34 getVideoStudioTaskFile
35) 35)
36 36
37// --------------------------------------------------------------------------- 37// ---------------------------------------------------------------------------
@@ -94,14 +94,14 @@ function getMaxQualityVideoPreview (req: express.Request, res: express.Response)
94 return res.sendFile(file.getPath()) 94 return res.sendFile(file.getPath())
95} 95}
96 96
97function getVideoEditionTaskFile (req: express.Request, res: express.Response) { 97function getVideoStudioTaskFile (req: express.Request, res: express.Response) {
98 const runnerJob = res.locals.runnerJob 98 const runnerJob = res.locals.runnerJob
99 const runner = runnerJob.Runner 99 const runner = runnerJob.Runner
100 const video = res.locals.videoAll 100 const video = res.locals.videoAll
101 const filename = req.params.filename 101 const filename = req.params.filename
102 102
103 logger.info( 103 logger.info(
104 'Get video edition task file %s of video %s of job %s for runner %s', filename, video.uuid, runnerJob.uuid, runner.name, 104 'Get video studio task file %s of video %s of job %s for runner %s', filename, video.uuid, runnerJob.uuid, runner.name,
105 lTags(runner.name, runnerJob.id, runnerJob.type) 105 lTags(runner.name, runnerJob.id, runnerJob.type)
106 ) 106 )
107 107
diff --git a/server/controllers/api/runners/jobs.ts b/server/controllers/api/runners/jobs.ts
index 8e34c07a3..3f2a92182 100644
--- a/server/controllers/api/runners/jobs.ts
+++ b/server/controllers/api/runners/jobs.ts
@@ -42,7 +42,7 @@ import {
42 RunnerJobUpdateBody, 42 RunnerJobUpdateBody,
43 RunnerJobUpdatePayload, 43 RunnerJobUpdatePayload,
44 UserRight, 44 UserRight,
45 VideoEditionTranscodingSuccess, 45 VideoStudioTranscodingSuccess,
46 VODAudioMergeTranscodingSuccess, 46 VODAudioMergeTranscodingSuccess,
47 VODHLSTranscodingSuccess, 47 VODHLSTranscodingSuccess,
48 VODWebVideoTranscodingSuccess 48 VODWebVideoTranscodingSuccess
@@ -300,7 +300,7 @@ const jobSuccessPayloadBuilders: {
300 } 300 }
301 }, 301 },
302 302
303 'video-edition-transcoding': (payload: VideoEditionTranscodingSuccess, files) => { 303 'video-studio-transcoding': (payload: VideoStudioTranscodingSuccess, files) => {
304 return { 304 return {
305 ...payload, 305 ...payload,
306 306
diff --git a/server/helpers/custom-validators/runners/jobs.ts b/server/helpers/custom-validators/runners/jobs.ts
index 934bd37c9..725a7658f 100644
--- a/server/helpers/custom-validators/runners/jobs.ts
+++ b/server/helpers/custom-validators/runners/jobs.ts
@@ -6,7 +6,7 @@ import {
6 RunnerJobSuccessPayload, 6 RunnerJobSuccessPayload,
7 RunnerJobType, 7 RunnerJobType,
8 RunnerJobUpdatePayload, 8 RunnerJobUpdatePayload,
9 VideoEditionTranscodingSuccess, 9 VideoStudioTranscodingSuccess,
10 VODAudioMergeTranscodingSuccess, 10 VODAudioMergeTranscodingSuccess,
11 VODHLSTranscodingSuccess, 11 VODHLSTranscodingSuccess,
12 VODWebVideoTranscodingSuccess 12 VODWebVideoTranscodingSuccess
@@ -25,7 +25,7 @@ function isRunnerJobSuccessPayloadValid (value: RunnerJobSuccessPayload, type: R
25 isRunnerJobVODHLSResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) || 25 isRunnerJobVODHLSResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
26 isRunnerJobVODAudioMergeResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) || 26 isRunnerJobVODAudioMergeResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
27 isRunnerJobLiveRTMPHLSResultPayloadValid(value as LiveRTMPHLSTranscodingSuccess, type) || 27 isRunnerJobLiveRTMPHLSResultPayloadValid(value as LiveRTMPHLSTranscodingSuccess, type) ||
28 isRunnerJobVideoEditionResultPayloadValid(value as VideoEditionTranscodingSuccess, type, files) 28 isRunnerJobVideoStudioResultPayloadValid(value as VideoStudioTranscodingSuccess, type, files)
29} 29}
30 30
31// --------------------------------------------------------------------------- 31// ---------------------------------------------------------------------------
@@ -37,7 +37,7 @@ function isRunnerJobProgressValid (value: string) {
37function isRunnerJobUpdatePayloadValid (value: RunnerJobUpdatePayload, type: RunnerJobType, files: UploadFilesForCheck) { 37function isRunnerJobUpdatePayloadValid (value: RunnerJobUpdatePayload, type: RunnerJobType, files: UploadFilesForCheck) {
38 return isRunnerJobVODWebVideoUpdatePayloadValid(value, type, files) || 38 return isRunnerJobVODWebVideoUpdatePayloadValid(value, type, files) ||
39 isRunnerJobVODHLSUpdatePayloadValid(value, type, files) || 39 isRunnerJobVODHLSUpdatePayloadValid(value, type, files) ||
40 isRunnerJobVideoEditionUpdatePayloadValid(value, type, files) || 40 isRunnerJobVideoStudioUpdatePayloadValid(value, type, files) ||
41 isRunnerJobVODAudioMergeUpdatePayloadValid(value, type, files) || 41 isRunnerJobVODAudioMergeUpdatePayloadValid(value, type, files) ||
42 isRunnerJobLiveRTMPHLSUpdatePayloadValid(value, type, files) 42 isRunnerJobLiveRTMPHLSUpdatePayloadValid(value, type, files)
43} 43}
@@ -105,12 +105,12 @@ function isRunnerJobLiveRTMPHLSResultPayloadValid (
105 return type === 'live-rtmp-hls-transcoding' && (!value || (typeof value === 'object' && Object.keys(value).length === 0)) 105 return type === 'live-rtmp-hls-transcoding' && (!value || (typeof value === 'object' && Object.keys(value).length === 0))
106} 106}
107 107
108function isRunnerJobVideoEditionResultPayloadValid ( 108function isRunnerJobVideoStudioResultPayloadValid (
109 _value: VideoEditionTranscodingSuccess, 109 _value: VideoStudioTranscodingSuccess,
110 type: RunnerJobType, 110 type: RunnerJobType,
111 files: UploadFilesForCheck 111 files: UploadFilesForCheck
112) { 112) {
113 return type === 'video-edition-transcoding' && 113 return type === 'video-studio-transcoding' &&
114 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null }) 114 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null })
115} 115}
116 116
@@ -177,11 +177,11 @@ function isRunnerJobLiveRTMPHLSUpdatePayloadValid (
177 ) 177 )
178} 178}
179 179
180function isRunnerJobVideoEditionUpdatePayloadValid ( 180function isRunnerJobVideoStudioUpdatePayloadValid (
181 value: RunnerJobUpdatePayload, 181 value: RunnerJobUpdatePayload,
182 type: RunnerJobType, 182 type: RunnerJobType,
183 _files: UploadFilesForCheck 183 _files: UploadFilesForCheck
184) { 184) {
185 return type === 'video-edition-transcoding' && 185 return type === 'video-studio-transcoding' &&
186 (!value || (typeof value === 'object' && Object.keys(value).length === 0)) 186 (!value || (typeof value === 'object' && Object.keys(value).length === 0))
187} 187}
diff --git a/server/lib/job-queue/handlers/video-studio-edition.ts b/server/lib/job-queue/handlers/video-studio-edition.ts
index df73caf72..caf051bfa 100644
--- a/server/lib/job-queue/handlers/video-studio-edition.ts
+++ b/server/lib/job-queue/handlers/video-studio-edition.ts
@@ -6,7 +6,7 @@ import { CONFIG } from '@server/initializers/config'
6import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles' 6import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
7import { isAbleToUploadVideo } from '@server/lib/user' 7import { isAbleToUploadVideo } from '@server/lib/user'
8import { VideoPathManager } from '@server/lib/video-path-manager' 8import { VideoPathManager } from '@server/lib/video-path-manager'
9import { approximateIntroOutroAdditionalSize, onVideoEditionEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio' 9import { approximateIntroOutroAdditionalSize, onVideoStudioEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
10import { UserModel } from '@server/models/user/user' 10import { UserModel } from '@server/models/user/user'
11import { VideoModel } from '@server/models/video/video' 11import { VideoModel } from '@server/models/video/video'
12import { MVideo, MVideoFullLight } from '@server/types/models' 12import { MVideo, MVideoFullLight } from '@server/types/models'
@@ -24,7 +24,7 @@ import {
24} from '@shared/models' 24} from '@shared/models'
25import { logger, loggerTagsFactory } from '../../../helpers/logger' 25import { logger, loggerTagsFactory } from '../../../helpers/logger'
26 26
27const lTagsBase = loggerTagsFactory('video-edition') 27const lTagsBase = loggerTagsFactory('video-studio')
28 28
29async function processVideoStudioEdition (job: Job) { 29async function processVideoStudioEdition (job: Job) {
30 const payload = job.data as VideoStudioEditionPayload 30 const payload = job.data as VideoStudioEditionPayload
@@ -74,7 +74,7 @@ async function processVideoStudioEdition (job: Job) {
74 74
75 logger.info('Video edition ended for video %s.', video.uuid, lTags) 75 logger.info('Video edition ended for video %s.', video.uuid, lTags)
76 76
77 await onVideoEditionEnded({ video, editionResultPath, tasks: payload.tasks }) 77 await onVideoStudioEnded({ video, editionResultPath, tasks: payload.tasks })
78 } catch (err) { 78 } catch (err) {
79 await safeCleanupStudioTMPFiles(payload.tasks) 79 await safeCleanupStudioTMPFiles(payload.tasks)
80 80
diff --git a/server/lib/runners/job-handlers/abstract-job-handler.ts b/server/lib/runners/job-handlers/abstract-job-handler.ts
index 76fd1c5ac..28c3e1eda 100644
--- a/server/lib/runners/job-handlers/abstract-job-handler.ts
+++ b/server/lib/runners/job-handlers/abstract-job-handler.ts
@@ -15,8 +15,8 @@ import {
15 RunnerJobSuccessPayload, 15 RunnerJobSuccessPayload,
16 RunnerJobType, 16 RunnerJobType,
17 RunnerJobUpdatePayload, 17 RunnerJobUpdatePayload,
18 RunnerJobVideoEditionTranscodingPayload, 18 RunnerJobStudioTranscodingPayload,
19 RunnerJobVideoEditionTranscodingPrivatePayload, 19 RunnerJobVideoStudioTranscodingPrivatePayload,
20 RunnerJobVODAudioMergeTranscodingPayload, 20 RunnerJobVODAudioMergeTranscodingPayload,
21 RunnerJobVODAudioMergeTranscodingPrivatePayload, 21 RunnerJobVODAudioMergeTranscodingPrivatePayload,
22 RunnerJobVODHLSTranscodingPayload, 22 RunnerJobVODHLSTranscodingPayload,
@@ -47,9 +47,9 @@ type CreateRunnerJobArg =
47 privatePayload: RunnerJobLiveRTMPHLSTranscodingPrivatePayload 47 privatePayload: RunnerJobLiveRTMPHLSTranscodingPrivatePayload
48 } | 48 } |
49 { 49 {
50 type: Extract<RunnerJobType, 'video-edition-transcoding'> 50 type: Extract<RunnerJobType, 'video-studio-transcoding'>
51 payload: RunnerJobVideoEditionTranscodingPayload 51 payload: RunnerJobStudioTranscodingPayload
52 privatePayload: RunnerJobVideoEditionTranscodingPrivatePayload 52 privatePayload: RunnerJobVideoStudioTranscodingPrivatePayload
53 } 53 }
54 54
55export abstract class AbstractJobHandler <C, U extends RunnerJobUpdatePayload, S extends RunnerJobSuccessPayload> { 55export abstract class AbstractJobHandler <C, U extends RunnerJobUpdatePayload, S extends RunnerJobSuccessPayload> {
diff --git a/server/lib/runners/job-handlers/index.ts b/server/lib/runners/job-handlers/index.ts
index a40cee865..40ad2f97a 100644
--- a/server/lib/runners/job-handlers/index.ts
+++ b/server/lib/runners/job-handlers/index.ts
@@ -1,7 +1,7 @@
1export * from './abstract-job-handler' 1export * from './abstract-job-handler'
2export * from './live-rtmp-hls-transcoding-job-handler' 2export * from './live-rtmp-hls-transcoding-job-handler'
3export * from './runner-job-handlers' 3export * from './runner-job-handlers'
4export * from './video-edition-transcoding-job-handler' 4export * from './video-studio-transcoding-job-handler'
5export * from './vod-audio-merge-transcoding-job-handler' 5export * from './vod-audio-merge-transcoding-job-handler'
6export * from './vod-hls-transcoding-job-handler' 6export * from './vod-hls-transcoding-job-handler'
7export * from './vod-web-video-transcoding-job-handler' 7export * from './vod-web-video-transcoding-job-handler'
diff --git a/server/lib/runners/job-handlers/runner-job-handlers.ts b/server/lib/runners/job-handlers/runner-job-handlers.ts
index 4ea6684ea..85551c365 100644
--- a/server/lib/runners/job-handlers/runner-job-handlers.ts
+++ b/server/lib/runners/job-handlers/runner-job-handlers.ts
@@ -2,7 +2,7 @@ import { MRunnerJob } from '@server/types/models/runners'
2import { RunnerJobSuccessPayload, RunnerJobType, RunnerJobUpdatePayload } from '@shared/models' 2import { RunnerJobSuccessPayload, RunnerJobType, RunnerJobUpdatePayload } from '@shared/models'
3import { AbstractJobHandler } from './abstract-job-handler' 3import { AbstractJobHandler } from './abstract-job-handler'
4import { LiveRTMPHLSTranscodingJobHandler } from './live-rtmp-hls-transcoding-job-handler' 4import { LiveRTMPHLSTranscodingJobHandler } from './live-rtmp-hls-transcoding-job-handler'
5import { VideoEditionTranscodingJobHandler } from './video-edition-transcoding-job-handler' 5import { VideoStudioTranscodingJobHandler } from './video-studio-transcoding-job-handler'
6import { VODAudioMergeTranscodingJobHandler } from './vod-audio-merge-transcoding-job-handler' 6import { VODAudioMergeTranscodingJobHandler } from './vod-audio-merge-transcoding-job-handler'
7import { VODHLSTranscodingJobHandler } from './vod-hls-transcoding-job-handler' 7import { VODHLSTranscodingJobHandler } from './vod-hls-transcoding-job-handler'
8import { VODWebVideoTranscodingJobHandler } from './vod-web-video-transcoding-job-handler' 8import { VODWebVideoTranscodingJobHandler } from './vod-web-video-transcoding-job-handler'
@@ -12,7 +12,7 @@ const processors: Record<RunnerJobType, new() => AbstractJobHandler<unknown, Run
12 'vod-hls-transcoding': VODHLSTranscodingJobHandler, 12 'vod-hls-transcoding': VODHLSTranscodingJobHandler,
13 'vod-audio-merge-transcoding': VODAudioMergeTranscodingJobHandler, 13 'vod-audio-merge-transcoding': VODAudioMergeTranscodingJobHandler,
14 'live-rtmp-hls-transcoding': LiveRTMPHLSTranscodingJobHandler, 14 'live-rtmp-hls-transcoding': LiveRTMPHLSTranscodingJobHandler,
15 'video-edition-transcoding': VideoEditionTranscodingJobHandler 15 'video-studio-transcoding': VideoStudioTranscodingJobHandler
16} 16}
17 17
18export function getRunnerJobHandlerClass (job: MRunnerJob) { 18export function getRunnerJobHandlerClass (job: MRunnerJob) {
diff --git a/server/lib/runners/job-handlers/video-edition-transcoding-job-handler.ts b/server/lib/runners/job-handlers/video-studio-transcoding-job-handler.ts
index 39a755c48..f604382b7 100644
--- a/server/lib/runners/job-handlers/video-edition-transcoding-job-handler.ts
+++ b/server/lib/runners/job-handlers/video-studio-transcoding-job-handler.ts
@@ -1,7 +1,7 @@
1 1
2import { basename } from 'path' 2import { basename } from 'path'
3import { logger } from '@server/helpers/logger' 3import { logger } from '@server/helpers/logger'
4import { onVideoEditionEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio' 4import { onVideoStudioEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
5import { MVideo } from '@server/types/models' 5import { MVideo } from '@server/types/models'
6import { MRunnerJob } from '@server/types/models/runners' 6import { MRunnerJob } from '@server/types/models/runners'
7import { buildUUID } from '@shared/extra-utils' 7import { buildUUID } from '@shared/extra-utils'
@@ -11,9 +11,9 @@ import {
11 isVideoStudioTaskWatermark, 11 isVideoStudioTaskWatermark,
12 RunnerJobState, 12 RunnerJobState,
13 RunnerJobUpdatePayload, 13 RunnerJobUpdatePayload,
14 RunnerJobVideoEditionTranscodingPayload, 14 RunnerJobStudioTranscodingPayload,
15 RunnerJobVideoEditionTranscodingPrivatePayload, 15 RunnerJobVideoStudioTranscodingPrivatePayload,
16 VideoEditionTranscodingSuccess, 16 VideoStudioTranscodingSuccess,
17 VideoState, 17 VideoState,
18 VideoStudioTaskPayload 18 VideoStudioTaskPayload
19} from '@shared/models' 19} from '@shared/models'
@@ -28,13 +28,13 @@ type CreateOptions = {
28} 28}
29 29
30// eslint-disable-next-line max-len 30// eslint-disable-next-line max-len
31export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<CreateOptions, RunnerJobUpdatePayload, VideoEditionTranscodingSuccess> { 31export class VideoStudioTranscodingJobHandler extends AbstractJobHandler<CreateOptions, RunnerJobUpdatePayload, VideoStudioTranscodingSuccess> {
32 32
33 async create (options: CreateOptions) { 33 async create (options: CreateOptions) {
34 const { video, priority, tasks } = options 34 const { video, priority, tasks } = options
35 35
36 const jobUUID = buildUUID() 36 const jobUUID = buildUUID()
37 const payload: RunnerJobVideoEditionTranscodingPayload = { 37 const payload: RunnerJobStudioTranscodingPayload = {
38 input: { 38 input: {
39 videoFileUrl: generateRunnerTranscodingVideoInputFileUrl(jobUUID, video.uuid) 39 videoFileUrl: generateRunnerTranscodingVideoInputFileUrl(jobUUID, video.uuid)
40 }, 40 },
@@ -67,13 +67,13 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
67 }) 67 })
68 } 68 }
69 69
70 const privatePayload: RunnerJobVideoEditionTranscodingPrivatePayload = { 70 const privatePayload: RunnerJobVideoStudioTranscodingPrivatePayload = {
71 videoUUID: video.uuid, 71 videoUUID: video.uuid,
72 originalTasks: tasks 72 originalTasks: tasks
73 } 73 }
74 74
75 const job = await this.createRunnerJob({ 75 const job = await this.createRunnerJob({
76 type: 'video-edition-transcoding', 76 type: 'video-studio-transcoding',
77 jobUUID, 77 jobUUID,
78 payload, 78 payload,
79 privatePayload, 79 privatePayload,
@@ -103,10 +103,10 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
103 103
104 protected async specificComplete (options: { 104 protected async specificComplete (options: {
105 runnerJob: MRunnerJob 105 runnerJob: MRunnerJob
106 resultPayload: VideoEditionTranscodingSuccess 106 resultPayload: VideoStudioTranscodingSuccess
107 }) { 107 }) {
108 const { runnerJob, resultPayload } = options 108 const { runnerJob, resultPayload } = options
109 const privatePayload = runnerJob.privatePayload as RunnerJobVideoEditionTranscodingPrivatePayload 109 const privatePayload = runnerJob.privatePayload as RunnerJobVideoStudioTranscodingPrivatePayload
110 110
111 const video = await loadTranscodingRunnerVideo(runnerJob, this.lTags) 111 const video = await loadTranscodingRunnerVideo(runnerJob, this.lTags)
112 if (!video) { 112 if (!video) {
@@ -116,7 +116,7 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
116 116
117 const videoFilePath = resultPayload.videoFile as string 117 const videoFilePath = resultPayload.videoFile as string
118 118
119 await onVideoEditionEnded({ video, editionResultPath: videoFilePath, tasks: privatePayload.originalTasks }) 119 await onVideoStudioEnded({ video, editionResultPath: videoFilePath, tasks: privatePayload.originalTasks })
120 120
121 logger.info( 121 logger.info(
122 'Runner video edition transcoding job %s for %s ended.', 122 'Runner video edition transcoding job %s for %s ended.',
@@ -146,7 +146,7 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
146 }) { 146 }) {
147 const { runnerJob } = options 147 const { runnerJob } = options
148 148
149 const payload = runnerJob.privatePayload as RunnerJobVideoEditionTranscodingPrivatePayload 149 const payload = runnerJob.privatePayload as RunnerJobVideoStudioTranscodingPrivatePayload
150 await safeCleanupStudioTMPFiles(payload.originalTasks) 150 await safeCleanupStudioTMPFiles(payload.originalTasks)
151 151
152 const video = await loadTranscodingRunnerVideo(options.runnerJob, this.lTags) 152 const video = await loadTranscodingRunnerVideo(options.runnerJob, this.lTags)
diff --git a/server/lib/transcoding/default-transcoding-profiles.ts b/server/lib/transcoding/default-transcoding-profiles.ts
index 5251784ac..8f8fdd026 100644
--- a/server/lib/transcoding/default-transcoding-profiles.ts
+++ b/server/lib/transcoding/default-transcoding-profiles.ts
@@ -1,88 +1,7 @@
1 1
2import { logger } from '@server/helpers/logger' 2import { logger } from '@server/helpers/logger'
3import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils' 3import { FFmpegCommandWrapper, getDefaultAvailableEncoders } from '@shared/ffmpeg'
4import { buildStreamSuffix, FFmpegCommandWrapper, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg' 4import { AvailableEncoders, EncoderOptionsBuilder } from '@shared/models'
5import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models'
6import { canDoQuickAudioTranscode } from './transcoding-quick-transcode'
7
8/**
9 *
10 * Available encoders and profiles for the transcoding jobs
11 * These functions are used by ffmpeg-utils that will get the encoders and options depending on the chosen profile
12 *
13 * Resources:
14 * * https://slhck.info/video/2017/03/01/rate-control.html
15 * * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
16 */
17
18// ---------------------------------------------------------------------------
19// Default builders
20// ---------------------------------------------------------------------------
21
22const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
23 const { fps, inputRatio, inputBitrate, resolution } = options
24
25 // TODO: remove in 4.2, fps is not optional anymore
26 if (!fps) return { outputOptions: [ ] }
27
28 const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
29
30 return {
31 outputOptions: [
32 ...getCommonOutputOptions(targetBitrate),
33
34 `-r ${fps}`
35 ]
36 }
37}
38
39const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
40 const { streamNum, fps, inputBitrate, inputRatio, resolution } = options
41
42 const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
43
44 return {
45 outputOptions: [
46 ...getCommonOutputOptions(targetBitrate, streamNum),
47
48 `${buildStreamSuffix('-r:v', streamNum)} ${fps}`,
49 `${buildStreamSuffix('-b:v', streamNum)} ${targetBitrate}`
50 ]
51 }
52}
53
54const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => {
55 const probe = await ffprobePromise(input)
56
57 if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) {
58 logger.debug('Copy audio stream %s by AAC encoder.', input)
59 return { copy: true, outputOptions: [ ] }
60 }
61
62 const parsedAudio = await getAudioStream(input, probe)
63
64 // We try to reduce the ceiling bitrate by making rough matches of bitrates
65 // Of course this is far from perfect, but it might save some space in the end
66
67 const audioCodecName = parsedAudio.audioStream['codec_name']
68
69 const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate)
70
71 logger.debug('Calculating audio bitrate of %s by AAC encoder.', input, { bitrate: parsedAudio.bitrate, audioCodecName })
72
73 // Force stereo as it causes some issues with HLS playback in Chrome
74 const base = [ '-channel_layout', 'stereo' ]
75
76 if (bitrate !== -1) {
77 return { outputOptions: base.concat([ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ]) }
78 }
79
80 return { outputOptions: base }
81}
82
83const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) => {
84 return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] }
85}
86 5
87// --------------------------------------------------------------------------- 6// ---------------------------------------------------------------------------
88// Profile manager to get and change default profiles 7// Profile manager to get and change default profiles
@@ -97,27 +16,7 @@ class VideoTranscodingProfilesManager {
97 live: this.buildDefaultEncodersPriorities() 16 live: this.buildDefaultEncodersPriorities()
98 } 17 }
99 18
100 private readonly availableEncoders = { 19 private readonly availableEncoders = getDefaultAvailableEncoders()
101 vod: {
102 libx264: {
103 default: defaultX264VODOptionsBuilder
104 },
105 aac: {
106 default: defaultAACOptionsBuilder
107 },
108 libfdk_aac: {
109 default: defaultLibFDKAACVODOptionsBuilder
110 }
111 },
112 live: {
113 libx264: {
114 default: defaultX264LiveOptionsBuilder
115 },
116 aac: {
117 default: defaultAACOptionsBuilder
118 }
119 }
120 }
121 20
122 private availableProfiles = { 21 private availableProfiles = {
123 vod: [] as string[], 22 vod: [] as string[],
@@ -242,41 +141,3 @@ class VideoTranscodingProfilesManager {
242export { 141export {
243 VideoTranscodingProfilesManager 142 VideoTranscodingProfilesManager
244} 143}
245
246// ---------------------------------------------------------------------------
247
248function getTargetBitrate (options: {
249 inputBitrate: number
250 resolution: VideoResolution
251 ratio: number
252 fps: number
253}) {
254 const { inputBitrate, resolution, ratio, fps } = options
255
256 const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio }))
257 const limit = getMinLimitBitrate({ resolution, fps, ratio })
258
259 return Math.max(limit, capped)
260}
261
262function capBitrate (inputBitrate: number, targetBitrate: number) {
263 if (!inputBitrate) return targetBitrate
264
265 // Add 30% margin to input bitrate
266 const inputBitrateWithMargin = inputBitrate + (inputBitrate * 0.3)
267
268 return Math.min(targetBitrate, inputBitrateWithMargin)
269}
270
271function getCommonOutputOptions (targetBitrate: number, streamNum?: number) {
272 return [
273 `-preset veryfast`,
274 `${buildStreamSuffix('-maxrate:v', streamNum)} ${targetBitrate}`,
275 `${buildStreamSuffix('-bufsize:v', streamNum)} ${targetBitrate * 2}`,
276
277 // NOTE: b-strategy 1 - heuristic algorithm, 16 is optimal B-frames for it
278 `-b_strategy 1`,
279 // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16
280 `-bf 16`
281 ]
282}
diff --git a/server/lib/video-studio.ts b/server/lib/video-studio.ts
index 2c993faeb..0d3db8f60 100644
--- a/server/lib/video-studio.ts
+++ b/server/lib/video-studio.ts
@@ -9,13 +9,13 @@ import { getVideoStreamDuration } from '@shared/ffmpeg'
9import { VideoStudioEditionPayload, VideoStudioTask, VideoStudioTaskPayload } from '@shared/models' 9import { VideoStudioEditionPayload, VideoStudioTask, VideoStudioTaskPayload } from '@shared/models'
10import { federateVideoIfNeeded } from './activitypub/videos' 10import { federateVideoIfNeeded } from './activitypub/videos'
11import { JobQueue } from './job-queue' 11import { JobQueue } from './job-queue'
12import { VideoEditionTranscodingJobHandler } from './runners' 12import { VideoStudioTranscodingJobHandler } from './runners'
13import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job' 13import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job'
14import { getTranscodingJobPriority } from './transcoding/transcoding-priority' 14import { getTranscodingJobPriority } from './transcoding/transcoding-priority'
15import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file' 15import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file'
16import { VideoPathManager } from './video-path-manager' 16import { VideoPathManager } from './video-path-manager'
17 17
18const lTags = loggerTagsFactory('video-edition') 18const lTags = loggerTagsFactory('video-studio')
19 19
20export function buildTaskFileFieldname (indice: number, fieldName = 'file') { 20export function buildTaskFileFieldname (indice: number, fieldName = 'file') {
21 return `tasks[${indice}][options][${fieldName}]` 21 return `tasks[${indice}][options][${fieldName}]`
@@ -78,14 +78,14 @@ export async function createVideoStudioJob (options: {
78 const priority = await getTranscodingJobPriority({ user, type: 'studio', fallback: 0 }) 78 const priority = await getTranscodingJobPriority({ user, type: 'studio', fallback: 0 })
79 79
80 if (CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED) { 80 if (CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED) {
81 await new VideoEditionTranscodingJobHandler().create({ video, tasks: payload.tasks, priority }) 81 await new VideoStudioTranscodingJobHandler().create({ video, tasks: payload.tasks, priority })
82 return 82 return
83 } 83 }
84 84
85 await JobQueue.Instance.createJob({ type: 'video-studio-edition', payload, priority }) 85 await JobQueue.Instance.createJob({ type: 'video-studio-edition', payload, priority })
86} 86}
87 87
88export async function onVideoEditionEnded (options: { 88export async function onVideoStudioEnded (options: {
89 editionResultPath: string 89 editionResultPath: string
90 tasks: VideoStudioTaskPayload[] 90 tasks: VideoStudioTaskPayload[]
91 video: MVideoFullLight 91 video: MVideoFullLight
diff --git a/server/middlewares/validators/runners/job-files.ts b/server/middlewares/validators/runners/job-files.ts
index e5afff0e5..57c27fcfe 100644
--- a/server/middlewares/validators/runners/job-files.ts
+++ b/server/middlewares/validators/runners/job-files.ts
@@ -2,7 +2,7 @@ import express from 'express'
2import { param } from 'express-validator' 2import { param } from 'express-validator'
3import { basename } from 'path' 3import { basename } from 'path'
4import { isSafeFilename } from '@server/helpers/custom-validators/misc' 4import { isSafeFilename } from '@server/helpers/custom-validators/misc'
5import { hasVideoStudioTaskFile, HttpStatusCode, RunnerJobVideoEditionTranscodingPayload } from '@shared/models' 5import { hasVideoStudioTaskFile, HttpStatusCode, RunnerJobStudioTranscodingPayload } from '@shared/models'
6import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared' 6import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared'
7 7
8const tags = [ 'runner' ] 8const tags = [ 'runner' ]
@@ -37,7 +37,7 @@ export const runnerJobGetVideoStudioTaskFileValidator = [
37 37
38 const filename = req.params.filename 38 const filename = req.params.filename
39 39
40 const payload = res.locals.runnerJob.payload as RunnerJobVideoEditionTranscodingPayload 40 const payload = res.locals.runnerJob.payload as RunnerJobStudioTranscodingPayload
41 41
42 const found = Array.isArray(payload?.tasks) && payload.tasks.some(t => { 42 const found = Array.isArray(payload?.tasks) && payload.tasks.some(t => {
43 if (hasVideoStudioTaskFile(t)) { 43 if (hasVideoStudioTaskFile(t)) {
diff --git a/server/tests/api/check-params/runners.ts b/server/tests/api/check-params/runners.ts
index 90a301392..cee1993e6 100644
--- a/server/tests/api/check-params/runners.ts
+++ b/server/tests/api/check-params/runners.ts
@@ -8,7 +8,7 @@ import {
8 RunnerJobState, 8 RunnerJobState,
9 RunnerJobSuccessPayload, 9 RunnerJobSuccessPayload,
10 RunnerJobUpdatePayload, 10 RunnerJobUpdatePayload,
11 RunnerJobVideoEditionTranscodingPayload, 11 RunnerJobStudioTranscodingPayload,
12 VideoPrivacy, 12 VideoPrivacy,
13 VideoStudioTaskIntro 13 VideoStudioTaskIntro
14} from '@shared/models' 14} from '@shared/models'
@@ -404,10 +404,10 @@ describe('Test managing runners', function () {
404 tasks: VideoStudioCommand.getComplexTask() 404 tasks: VideoStudioCommand.getComplexTask()
405 }) 405 })
406 406
407 const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'video-edition-transcoding' }) 407 const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'video-studio-transcoding' })
408 studioAcceptedJob = job 408 studioAcceptedJob = job
409 409
410 const tasks = (job.payload as RunnerJobVideoEditionTranscodingPayload).tasks 410 const tasks = (job.payload as RunnerJobStudioTranscodingPayload).tasks
411 const fileUrl = (tasks.find(t => isVideoStudioTaskIntro(t)) as VideoStudioTaskIntro).options.file as string 411 const fileUrl = (tasks.find(t => isVideoStudioTaskIntro(t)) as VideoStudioTaskIntro).options.file as string
412 studioFile = basename(fileUrl) 412 studioFile = basename(fileUrl)
413 } 413 }
@@ -787,7 +787,7 @@ describe('Test managing runners', function () {
787 787
788 describe('Video studio', function () { 788 describe('Video studio', function () {
789 789
790 it('Should fail with an invalid video edition transcoding payload', async function () { 790 it('Should fail with an invalid video studio transcoding payload', async function () {
791 await server.runnerJobs.success({ 791 await server.runnerJobs.success({
792 jobUUID: studioAcceptedJob.uuid, 792 jobUUID: studioAcceptedJob.uuid,
793 jobToken: studioAcceptedJob.jobToken, 793 jobToken: studioAcceptedJob.jobToken,
@@ -849,7 +849,7 @@ describe('Test managing runners', function () {
849 }) 849 })
850 }) 850 })
851 851
852 describe('Video edition tasks file routes', function () { 852 describe('Video studio tasks file routes', function () {
853 853
854 it('Should fail with an invalid studio filename', async function () { 854 it('Should fail with an invalid studio filename', async function () {
855 await fetchStudioFiles({ 855 await fetchStudioFiles({
diff --git a/server/tests/api/runners/runner-studio-transcoding.ts b/server/tests/api/runners/runner-studio-transcoding.ts
index 9ae629be6..41c556775 100644
--- a/server/tests/api/runners/runner-studio-transcoding.ts
+++ b/server/tests/api/runners/runner-studio-transcoding.ts
@@ -5,8 +5,8 @@ import { readFile } from 'fs-extra'
5import { checkPersistentTmpIsEmpty, checkVideoDuration } from '@server/tests/shared' 5import { checkPersistentTmpIsEmpty, checkVideoDuration } from '@server/tests/shared'
6import { buildAbsoluteFixturePath } from '@shared/core-utils' 6import { buildAbsoluteFixturePath } from '@shared/core-utils'
7import { 7import {
8 RunnerJobVideoEditionTranscodingPayload, 8 RunnerJobStudioTranscodingPayload,
9 VideoEditionTranscodingSuccess, 9 VideoStudioTranscodingSuccess,
10 VideoState, 10 VideoState,
11 VideoStudioTask, 11 VideoStudioTask,
12 VideoStudioTaskIntro 12 VideoStudioTaskIntro
@@ -121,10 +121,10 @@ describe('Test runner video studio transcoding', function () {
121 await checkVideoDuration(server, videoUUID, 5) 121 await checkVideoDuration(server, videoUUID, 5)
122 } 122 }
123 123
124 const { job } = await servers[0].runnerJobs.accept<RunnerJobVideoEditionTranscodingPayload>({ runnerToken, jobUUID }) 124 const { job } = await servers[0].runnerJobs.accept<RunnerJobStudioTranscodingPayload>({ runnerToken, jobUUID })
125 const jobToken = job.jobToken 125 const jobToken = job.jobToken
126 126
127 expect(job.type === 'video-edition-transcoding') 127 expect(job.type === 'video-studio-transcoding')
128 expect(job.payload.input.videoFileUrl).to.exist 128 expect(job.payload.input.videoFileUrl).to.exist
129 129
130 // Check video input file 130 // Check video input file
@@ -150,7 +150,7 @@ describe('Test runner video studio transcoding', function () {
150 expect(body).to.deep.equal(inputFile) 150 expect(body).to.deep.equal(inputFile)
151 } 151 }
152 152
153 const payload: VideoEditionTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' } 153 const payload: VideoStudioTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' }
154 await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload }) 154 await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
155 155
156 await waitJobs(servers) 156 await waitJobs(servers)
diff --git a/server/tests/api/transcoding/video-studio.ts b/server/tests/api/transcoding/video-studio.ts
index 2f64ef6bd..d22cfff4a 100644
--- a/server/tests/api/transcoding/video-studio.ts
+++ b/server/tests/api/transcoding/video-studio.ts
@@ -270,7 +270,7 @@ describe('Test video studio', function () {
270 }) 270 })
271 }) 271 })
272 272
273 describe('HLS only video edition', function () { 273 describe('HLS only studio edition', function () {
274 274
275 before(async function () { 275 before(async function () {
276 // Disable webtorrent 276 // Disable webtorrent
@@ -300,7 +300,7 @@ describe('Test video studio', function () {
300 }) 300 })
301 }) 301 })
302 302
303 describe('Object storage video edition', function () { 303 describe('Object storage studio edition', function () {
304 if (areMockObjectStorageTestsDisabled()) return 304 if (areMockObjectStorageTestsDisabled()) return
305 305
306 before(async function () { 306 before(async function () {