]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Prefer video studio instead of video edition
authorChocobozzz <me@florianbigard.com>
Thu, 4 May 2023 13:55:51 +0000 (15:55 +0200)
committerChocobozzz <chocobozzz@cpy.re>
Tue, 9 May 2023 06:57:34 +0000 (08:57 +0200)
Clearer and easier to find in the project

26 files changed:
packages/peertube-runner/server/process/process.ts
packages/peertube-runner/server/process/shared/common.ts
packages/peertube-runner/server/process/shared/index.ts
packages/peertube-runner/server/process/shared/process-studio.ts
packages/peertube-runner/server/process/shared/process-vod.ts
packages/peertube-runner/server/shared/supported-job.ts
server/controllers/api/runners/jobs-files.ts
server/controllers/api/runners/jobs.ts
server/helpers/custom-validators/runners/jobs.ts
server/lib/job-queue/handlers/video-studio-edition.ts
server/lib/runners/job-handlers/abstract-job-handler.ts
server/lib/runners/job-handlers/index.ts
server/lib/runners/job-handlers/runner-job-handlers.ts
server/lib/runners/job-handlers/video-studio-transcoding-job-handler.ts [moved from server/lib/runners/job-handlers/video-edition-transcoding-job-handler.ts with 80% similarity]
server/lib/transcoding/default-transcoding-profiles.ts
server/lib/video-studio.ts
server/middlewares/validators/runners/job-files.ts
server/tests/api/check-params/runners.ts
server/tests/api/runners/runner-studio-transcoding.ts
server/tests/api/transcoding/video-studio.ts
shared/ffmpeg/ffmpeg-default-transcoding-profile.ts [moved from packages/peertube-runner/server/process/shared/transcoding-profiles.ts with 97% similarity]
shared/ffmpeg/index.ts
shared/models/runners/runner-job-payload.model.ts
shared/models/runners/runner-job-private-payload.model.ts
shared/models/runners/runner-job-success-body.model.ts
shared/models/runners/runner-job-type.type.ts

index ef231cb38fff54ee2496812e3ca427eb744388bb..1caafda8ce6b468b3ac64fbf80fe82a715267dea 100644 (file)
@@ -1,7 +1,7 @@
 import { logger } from 'packages/peertube-runner/shared/logger'
 import {
   RunnerJobLiveRTMPHLSTranscodingPayload,
-  RunnerJobVideoEditionTranscodingPayload,
+  RunnerJobStudioTranscodingPayload,
   RunnerJobVODAudioMergeTranscodingPayload,
   RunnerJobVODHLSTranscodingPayload,
   RunnerJobVODWebVideoTranscodingPayload
@@ -23,8 +23,8 @@ export async function processJob (options: ProcessOptions) {
     await processHLSTranscoding(options as ProcessOptions<RunnerJobVODHLSTranscodingPayload>)
   } else if (job.type === 'live-rtmp-hls-transcoding') {
     await new ProcessLiveRTMPHLSTranscoding(options as ProcessOptions<RunnerJobLiveRTMPHLSTranscodingPayload>).process()
-  } else if (job.type === 'video-edition-transcoding') {
-    await processStudioTranscoding(options as ProcessOptions<RunnerJobVideoEditionTranscodingPayload>)
+  } else if (job.type === 'video-studio-transcoding') {
+    await processStudioTranscoding(options as ProcessOptions<RunnerJobStudioTranscodingPayload>)
   } else {
     logger.error(`Unknown job ${job.type} to process`)
     return
index 3cac983884becedf0bff562a3aeb0d9f463b547f..88f7c33f10459e5817bb721df824c06fc23582c3 100644 (file)
@@ -1,13 +1,12 @@
+import { remove } from 'fs-extra'
 import { throttle } from 'lodash'
 import { ConfigManager, downloadFile, logger } from 'packages/peertube-runner/shared'
 import { join } from 'path'
 import { buildUUID } from '@shared/extra-utils'
-import { FFmpegEdition, FFmpegLive, FFmpegVOD } from '@shared/ffmpeg'
+import { FFmpegEdition, FFmpegLive, FFmpegVOD, getDefaultAvailableEncoders, getDefaultEncodersToTry } from '@shared/ffmpeg'
 import { RunnerJob, RunnerJobPayload } from '@shared/models'
 import { PeerTubeServer } from '@shared/server-commands'
 import { getTranscodingLogger } from './transcoding-logger'
-import { getAvailableEncoders, getEncodersToTry } from './transcoding-profiles'
-import { remove } from 'fs-extra'
 
 export type JobWithToken <T extends RunnerJobPayload = RunnerJobPayload> = RunnerJob<T> & { jobToken: string }
 
@@ -92,8 +91,8 @@ function getCommonFFmpegOptions () {
     tmpDirectory: ConfigManager.Instance.getTranscodingDirectory(),
     profile: 'default',
     availableEncoders: {
-      available: getAvailableEncoders(),
-      encodersToTry: getEncodersToTry()
+      available: getDefaultAvailableEncoders(),
+      encodersToTry: getDefaultEncodersToTry()
     },
     logger: getTranscodingLogger()
   }
index 8e09a7869060ea68c55cc25bc8d5f28be60ce6f2..556c51365a3efd1eda37494b8b3aec85c6741824 100644 (file)
@@ -1,4 +1,3 @@
 export * from './common'
 export * from './process-vod'
 export * from './transcoding-logger'
-export * from './transcoding-profiles'
index f8262096e98c058d25213fcb7df4f64634c139b5..9c745d0319ea3e879791b288aedd12205be16b36 100644 (file)
@@ -1,11 +1,11 @@
 import { remove } from 'fs-extra'
 import { pick } from 'lodash'
 import { logger } from 'packages/peertube-runner/shared'
-import { extname, join } from 'path'
+import { join } from 'path'
 import { buildUUID } from '@shared/extra-utils'
 import {
-  RunnerJobVideoEditionTranscodingPayload,
-  VideoEditionTranscodingSuccess,
+  RunnerJobStudioTranscodingPayload,
+  VideoStudioTranscodingSuccess,
   VideoStudioTask,
   VideoStudioTaskCutPayload,
   VideoStudioTaskIntroPayload,
@@ -16,7 +16,7 @@ import {
 import { ConfigManager } from '../../../shared/config-manager'
 import { buildFFmpegEdition, downloadInputFile, JobWithToken, ProcessOptions } from './common'
 
-export async function processStudioTranscoding (options: ProcessOptions<RunnerJobVideoEditionTranscodingPayload>) {
+export async function processStudioTranscoding (options: ProcessOptions<RunnerJobStudioTranscodingPayload>) {
   const { server, job, runnerToken } = options
   const payload = job.payload
 
@@ -43,7 +43,7 @@ export async function processStudioTranscoding (options: ProcessOptions<RunnerJo
       tmpInputFilePath = outputPath
     }
 
-    const successBody: VideoEditionTranscodingSuccess = {
+    const successBody: VideoStudioTranscodingSuccess = {
       videoFile: outputPath
     }
 
@@ -94,14 +94,18 @@ async function processAddIntroOutro (options: TaskProcessorOptions<VideoStudioTa
 
   const introOutroPath = await downloadInputFile({ url: task.options.file, runnerToken, job })
 
-  return buildFFmpegEdition().addIntroOutro({
-    ...pick(options, [ 'inputPath', 'outputPath' ]),
+  try {
+    await buildFFmpegEdition().addIntroOutro({
+      ...pick(options, [ 'inputPath', 'outputPath' ]),
 
-    introOutroPath,
-    type: task.name === 'add-intro'
-      ? 'intro'
-      : 'outro'
-  })
+      introOutroPath,
+      type: task.name === 'add-intro'
+        ? 'intro'
+        : 'outro'
+    })
+  } finally {
+    await remove(introOutroPath)
+  }
 }
 
 function processCut (options: TaskProcessorOptions<VideoStudioTaskCutPayload>) {
@@ -124,15 +128,19 @@ async function processAddWatermark (options: TaskProcessorOptions<VideoStudioTas
 
   const watermarkPath = await downloadInputFile({ url: task.options.file, runnerToken, job })
 
-  return buildFFmpegEdition().addWatermark({
-    ...pick(options, [ 'inputPath', 'outputPath' ]),
+  try {
+    await buildFFmpegEdition().addWatermark({
+      ...pick(options, [ 'inputPath', 'outputPath' ]),
 
-    watermarkPath,
+      watermarkPath,
 
-    videoFilters: {
-      watermarkSizeRatio: task.options.watermarkSizeRatio,
-      horitonzalMarginRatio: task.options.horitonzalMarginRatio,
-      verticalMarginRatio: task.options.verticalMarginRatio
-    }
-  })
+      videoFilters: {
+        watermarkSizeRatio: task.options.watermarkSizeRatio,
+        horitonzalMarginRatio: task.options.horitonzalMarginRatio,
+        verticalMarginRatio: task.options.verticalMarginRatio
+      }
+    })
+  } finally {
+    await remove(watermarkPath)
+  }
 }
index d84ece3cbcc51c3d81b4e8380557add9dbe90dc7..22489afd573e2ec0f808f8b2c27b907fb6c61d80 100644 (file)
@@ -22,31 +22,34 @@ export async function processWebVideoTranscoding (options: ProcessOptions<Runner
 
   const outputPath = join(ConfigManager.Instance.getTranscodingDirectory(), `output-${buildUUID()}.mp4`)
 
-  await ffmpegVod.transcode({
-    type: 'video',
-
-    inputPath,
+  try {
+    await ffmpegVod.transcode({
+      type: 'video',
 
-    outputPath,
+      inputPath,
 
-    inputFileMutexReleaser: () => {},
+      outputPath,
 
-    resolution: payload.output.resolution,
-    fps: payload.output.fps
-  })
+      inputFileMutexReleaser: () => {},
 
-  const successBody: VODWebVideoTranscodingSuccess = {
-    videoFile: outputPath
-  }
+      resolution: payload.output.resolution,
+      fps: payload.output.fps
+    })
 
-  await server.runnerJobs.success({
-    jobToken: job.jobToken,
-    jobUUID: job.uuid,
-    runnerToken,
-    payload: successBody
-  })
+    const successBody: VODWebVideoTranscodingSuccess = {
+      videoFile: outputPath
+    }
 
-  await remove(outputPath)
+    await server.runnerJobs.success({
+      jobToken: job.jobToken,
+      jobUUID: job.uuid,
+      runnerToken,
+      payload: successBody
+    })
+  } finally {
+    await remove(inputPath)
+    await remove(outputPath)
+  }
 }
 
 export async function processHLSTranscoding (options: ProcessOptions<RunnerJobVODHLSTranscodingPayload>) {
@@ -105,30 +108,34 @@ export async function processAudioMergeTranscoding (options: ProcessOptions<Runn
 
   const ffmpegVod = buildFFmpegVOD({ job, server, runnerToken })
 
-  await ffmpegVod.transcode({
-    type: 'merge-audio',
-
-    audioPath,
-    inputPath,
+  try {
+    await ffmpegVod.transcode({
+      type: 'merge-audio',
 
-    outputPath,
+      audioPath,
+      inputPath,
 
-    inputFileMutexReleaser: () => {},
+      outputPath,
 
-    resolution: payload.output.resolution,
-    fps: payload.output.fps
-  })
+      inputFileMutexReleaser: () => {},
 
-  const successBody: VODAudioMergeTranscodingSuccess = {
-    videoFile: outputPath
-  }
+      resolution: payload.output.resolution,
+      fps: payload.output.fps
+    })
 
-  await server.runnerJobs.success({
-    jobToken: job.jobToken,
-    jobUUID: job.uuid,
-    runnerToken,
-    payload: successBody
-  })
+    const successBody: VODAudioMergeTranscodingSuccess = {
+      videoFile: outputPath
+    }
 
-  await remove(outputPath)
+    await server.runnerJobs.success({
+      jobToken: job.jobToken,
+      jobUUID: job.uuid,
+      runnerToken,
+      payload: successBody
+    })
+  } finally {
+    await remove(audioPath)
+    await remove(inputPath)
+    await remove(outputPath)
+  }
 }
index 87d5a39cc6db2805963bba241201fdfb271fc8ea..1137d8206af35f744bcf3c9f5acf875c42e9e8fa 100644 (file)
@@ -2,7 +2,7 @@ import {
   RunnerJobLiveRTMPHLSTranscodingPayload,
   RunnerJobPayload,
   RunnerJobType,
-  RunnerJobVideoEditionTranscodingPayload,
+  RunnerJobStudioTranscodingPayload,
   RunnerJobVODAudioMergeTranscodingPayload,
   RunnerJobVODHLSTranscodingPayload,
   RunnerJobVODWebVideoTranscodingPayload,
@@ -22,7 +22,7 @@ const supportedMatrix = {
   'live-rtmp-hls-transcoding': (_payload: RunnerJobLiveRTMPHLSTranscodingPayload) => {
     return true
   },
-  'video-edition-transcoding': (payload: RunnerJobVideoEditionTranscodingPayload) => {
+  'video-studio-transcoding': (payload: RunnerJobStudioTranscodingPayload) => {
     const tasks = payload?.tasks
     const supported = new Set<VideoStudioTaskPayload['name']>([ 'add-intro', 'add-outro', 'add-watermark', 'cut' ])
 
index 4efa40b3ad289b4535d90312c095d5ba1b7eea0b..260d824a875a6cbc2c01210fc10656417238a156 100644 (file)
@@ -31,7 +31,7 @@ runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/studio/task-file
   asyncMiddleware(jobOfRunnerGetValidator),
   asyncMiddleware(runnerJobGetVideoTranscodingFileValidator),
   runnerJobGetVideoStudioTaskFileValidator,
-  getVideoEditionTaskFile
+  getVideoStudioTaskFile
 )
 
 // ---------------------------------------------------------------------------
@@ -94,14 +94,14 @@ function getMaxQualityVideoPreview (req: express.Request, res: express.Response)
   return res.sendFile(file.getPath())
 }
 
-function getVideoEditionTaskFile (req: express.Request, res: express.Response) {
+function getVideoStudioTaskFile (req: express.Request, res: express.Response) {
   const runnerJob = res.locals.runnerJob
   const runner = runnerJob.Runner
   const video = res.locals.videoAll
   const filename = req.params.filename
 
   logger.info(
-    'Get video edition task file %s of video %s of job %s for runner %s', filename, video.uuid, runnerJob.uuid, runner.name,
+    'Get video studio task file %s of video %s of job %s for runner %s', filename, video.uuid, runnerJob.uuid, runner.name,
     lTags(runner.name, runnerJob.id, runnerJob.type)
   )
 
index 8e34c07a38ee0a79d3fe5e29edb4936d97fa75ca..3f2a92182edcd3b9b2afe8f520820ffadfc6ca52 100644 (file)
@@ -42,7 +42,7 @@ import {
   RunnerJobUpdateBody,
   RunnerJobUpdatePayload,
   UserRight,
-  VideoEditionTranscodingSuccess,
+  VideoStudioTranscodingSuccess,
   VODAudioMergeTranscodingSuccess,
   VODHLSTranscodingSuccess,
   VODWebVideoTranscodingSuccess
@@ -300,7 +300,7 @@ const jobSuccessPayloadBuilders: {
     }
   },
 
-  'video-edition-transcoding': (payload: VideoEditionTranscodingSuccess, files) => {
+  'video-studio-transcoding': (payload: VideoStudioTranscodingSuccess, files) => {
     return {
       ...payload,
 
index 934bd37c9516096c3380556bf9cffa7c014e77c9..725a7658f58eff3942ea8d8b5454cab191efeec2 100644 (file)
@@ -6,7 +6,7 @@ import {
   RunnerJobSuccessPayload,
   RunnerJobType,
   RunnerJobUpdatePayload,
-  VideoEditionTranscodingSuccess,
+  VideoStudioTranscodingSuccess,
   VODAudioMergeTranscodingSuccess,
   VODHLSTranscodingSuccess,
   VODWebVideoTranscodingSuccess
@@ -25,7 +25,7 @@ function isRunnerJobSuccessPayloadValid (value: RunnerJobSuccessPayload, type: R
     isRunnerJobVODHLSResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
     isRunnerJobVODAudioMergeResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
     isRunnerJobLiveRTMPHLSResultPayloadValid(value as LiveRTMPHLSTranscodingSuccess, type) ||
-    isRunnerJobVideoEditionResultPayloadValid(value as VideoEditionTranscodingSuccess, type, files)
+    isRunnerJobVideoStudioResultPayloadValid(value as VideoStudioTranscodingSuccess, type, files)
 }
 
 // ---------------------------------------------------------------------------
@@ -37,7 +37,7 @@ function isRunnerJobProgressValid (value: string) {
 function isRunnerJobUpdatePayloadValid (value: RunnerJobUpdatePayload, type: RunnerJobType, files: UploadFilesForCheck) {
   return isRunnerJobVODWebVideoUpdatePayloadValid(value, type, files) ||
     isRunnerJobVODHLSUpdatePayloadValid(value, type, files) ||
-    isRunnerJobVideoEditionUpdatePayloadValid(value, type, files) ||
+    isRunnerJobVideoStudioUpdatePayloadValid(value, type, files) ||
     isRunnerJobVODAudioMergeUpdatePayloadValid(value, type, files) ||
     isRunnerJobLiveRTMPHLSUpdatePayloadValid(value, type, files)
 }
@@ -105,12 +105,12 @@ function isRunnerJobLiveRTMPHLSResultPayloadValid (
   return type === 'live-rtmp-hls-transcoding' && (!value || (typeof value === 'object' && Object.keys(value).length === 0))
 }
 
-function isRunnerJobVideoEditionResultPayloadValid (
-  _value: VideoEditionTranscodingSuccess,
+function isRunnerJobVideoStudioResultPayloadValid (
+  _value: VideoStudioTranscodingSuccess,
   type: RunnerJobType,
   files: UploadFilesForCheck
 ) {
-  return type === 'video-edition-transcoding' &&
+  return type === 'video-studio-transcoding' &&
     isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null })
 }
 
@@ -177,11 +177,11 @@ function isRunnerJobLiveRTMPHLSUpdatePayloadValid (
     )
 }
 
-function isRunnerJobVideoEditionUpdatePayloadValid (
+function isRunnerJobVideoStudioUpdatePayloadValid (
   value: RunnerJobUpdatePayload,
   type: RunnerJobType,
   _files: UploadFilesForCheck
 ) {
-  return type === 'video-edition-transcoding' &&
+  return type === 'video-studio-transcoding' &&
     (!value || (typeof value === 'object' && Object.keys(value).length === 0))
 }
index df73caf72534c2651eb5be0f839d5ccc32f96235..caf051bfa7d6e532f6313c5ea374342dd5b6e2e0 100644 (file)
@@ -6,7 +6,7 @@ import { CONFIG } from '@server/initializers/config'
 import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
 import { isAbleToUploadVideo } from '@server/lib/user'
 import { VideoPathManager } from '@server/lib/video-path-manager'
-import { approximateIntroOutroAdditionalSize, onVideoEditionEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
+import { approximateIntroOutroAdditionalSize, onVideoStudioEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
 import { UserModel } from '@server/models/user/user'
 import { VideoModel } from '@server/models/video/video'
 import { MVideo, MVideoFullLight } from '@server/types/models'
@@ -24,7 +24,7 @@ import {
 } from '@shared/models'
 import { logger, loggerTagsFactory } from '../../../helpers/logger'
 
-const lTagsBase = loggerTagsFactory('video-edition')
+const lTagsBase = loggerTagsFactory('video-studio')
 
 async function processVideoStudioEdition (job: Job) {
   const payload = job.data as VideoStudioEditionPayload
@@ -74,7 +74,7 @@ async function processVideoStudioEdition (job: Job) {
 
     logger.info('Video edition ended for video %s.', video.uuid, lTags)
 
-    await onVideoEditionEnded({ video, editionResultPath, tasks: payload.tasks })
+    await onVideoStudioEnded({ video, editionResultPath, tasks: payload.tasks })
   } catch (err) {
     await safeCleanupStudioTMPFiles(payload.tasks)
 
index 76fd1c5ac53a642f811dafec70eabf1ec8219697..28c3e1eda37534ba59e07cea80840a26c4162f7d 100644 (file)
@@ -15,8 +15,8 @@ import {
   RunnerJobSuccessPayload,
   RunnerJobType,
   RunnerJobUpdatePayload,
-  RunnerJobVideoEditionTranscodingPayload,
-  RunnerJobVideoEditionTranscodingPrivatePayload,
+  RunnerJobStudioTranscodingPayload,
+  RunnerJobVideoStudioTranscodingPrivatePayload,
   RunnerJobVODAudioMergeTranscodingPayload,
   RunnerJobVODAudioMergeTranscodingPrivatePayload,
   RunnerJobVODHLSTranscodingPayload,
@@ -47,9 +47,9 @@ type CreateRunnerJobArg =
     privatePayload: RunnerJobLiveRTMPHLSTranscodingPrivatePayload
   } |
   {
-    type: Extract<RunnerJobType, 'video-edition-transcoding'>
-    payload: RunnerJobVideoEditionTranscodingPayload
-    privatePayload: RunnerJobVideoEditionTranscodingPrivatePayload
+    type: Extract<RunnerJobType, 'video-studio-transcoding'>
+    payload: RunnerJobStudioTranscodingPayload
+    privatePayload: RunnerJobVideoStudioTranscodingPrivatePayload
   }
 
 export abstract class AbstractJobHandler <C, U extends RunnerJobUpdatePayload, S extends RunnerJobSuccessPayload> {
index a40cee86504619f55745cee8d3bfd1cef093b593..40ad2f97a01ff108055f64a3b3a666fba728ed70 100644 (file)
@@ -1,7 +1,7 @@
 export * from './abstract-job-handler'
 export * from './live-rtmp-hls-transcoding-job-handler'
 export * from './runner-job-handlers'
-export * from './video-edition-transcoding-job-handler'
+export * from './video-studio-transcoding-job-handler'
 export * from './vod-audio-merge-transcoding-job-handler'
 export * from './vod-hls-transcoding-job-handler'
 export * from './vod-web-video-transcoding-job-handler'
index 4ea6684ea93f9616065f26f2f242b156f16336c4..85551c365b229608315f43661c58064f9b62b3dc 100644 (file)
@@ -2,7 +2,7 @@ import { MRunnerJob } from '@server/types/models/runners'
 import { RunnerJobSuccessPayload, RunnerJobType, RunnerJobUpdatePayload } from '@shared/models'
 import { AbstractJobHandler } from './abstract-job-handler'
 import { LiveRTMPHLSTranscodingJobHandler } from './live-rtmp-hls-transcoding-job-handler'
-import { VideoEditionTranscodingJobHandler } from './video-edition-transcoding-job-handler'
+import { VideoStudioTranscodingJobHandler } from './video-studio-transcoding-job-handler'
 import { VODAudioMergeTranscodingJobHandler } from './vod-audio-merge-transcoding-job-handler'
 import { VODHLSTranscodingJobHandler } from './vod-hls-transcoding-job-handler'
 import { VODWebVideoTranscodingJobHandler } from './vod-web-video-transcoding-job-handler'
@@ -12,7 +12,7 @@ const processors: Record<RunnerJobType, new() => AbstractJobHandler<unknown, Run
   'vod-hls-transcoding': VODHLSTranscodingJobHandler,
   'vod-audio-merge-transcoding': VODAudioMergeTranscodingJobHandler,
   'live-rtmp-hls-transcoding': LiveRTMPHLSTranscodingJobHandler,
-  'video-edition-transcoding': VideoEditionTranscodingJobHandler
+  'video-studio-transcoding': VideoStudioTranscodingJobHandler
 }
 
 export function getRunnerJobHandlerClass (job: MRunnerJob) {
similarity index 80%
rename from server/lib/runners/job-handlers/video-edition-transcoding-job-handler.ts
rename to server/lib/runners/job-handlers/video-studio-transcoding-job-handler.ts
index 39a755c4859770437133ce9a57dcebe5df9dfed8..f604382b7272b74d6815d2e35feb0a227eaf326f 100644 (file)
@@ -1,7 +1,7 @@
 
 import { basename } from 'path'
 import { logger } from '@server/helpers/logger'
-import { onVideoEditionEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
+import { onVideoStudioEnded, safeCleanupStudioTMPFiles } from '@server/lib/video-studio'
 import { MVideo } from '@server/types/models'
 import { MRunnerJob } from '@server/types/models/runners'
 import { buildUUID } from '@shared/extra-utils'
@@ -11,9 +11,9 @@ import {
   isVideoStudioTaskWatermark,
   RunnerJobState,
   RunnerJobUpdatePayload,
-  RunnerJobVideoEditionTranscodingPayload,
-  RunnerJobVideoEditionTranscodingPrivatePayload,
-  VideoEditionTranscodingSuccess,
+  RunnerJobStudioTranscodingPayload,
+  RunnerJobVideoStudioTranscodingPrivatePayload,
+  VideoStudioTranscodingSuccess,
   VideoState,
   VideoStudioTaskPayload
 } from '@shared/models'
@@ -28,13 +28,13 @@ type CreateOptions = {
 }
 
 // eslint-disable-next-line max-len
-export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<CreateOptions, RunnerJobUpdatePayload, VideoEditionTranscodingSuccess> {
+export class VideoStudioTranscodingJobHandler extends AbstractJobHandler<CreateOptions, RunnerJobUpdatePayload, VideoStudioTranscodingSuccess> {
 
   async create (options: CreateOptions) {
     const { video, priority, tasks } = options
 
     const jobUUID = buildUUID()
-    const payload: RunnerJobVideoEditionTranscodingPayload = {
+    const payload: RunnerJobStudioTranscodingPayload = {
       input: {
         videoFileUrl: generateRunnerTranscodingVideoInputFileUrl(jobUUID, video.uuid)
       },
@@ -67,13 +67,13 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
       })
     }
 
-    const privatePayload: RunnerJobVideoEditionTranscodingPrivatePayload = {
+    const privatePayload: RunnerJobVideoStudioTranscodingPrivatePayload = {
       videoUUID: video.uuid,
       originalTasks: tasks
     }
 
     const job = await this.createRunnerJob({
-      type: 'video-edition-transcoding',
+      type: 'video-studio-transcoding',
       jobUUID,
       payload,
       privatePayload,
@@ -103,10 +103,10 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
 
   protected async specificComplete (options: {
     runnerJob: MRunnerJob
-    resultPayload: VideoEditionTranscodingSuccess
+    resultPayload: VideoStudioTranscodingSuccess
   }) {
     const { runnerJob, resultPayload } = options
-    const privatePayload = runnerJob.privatePayload as RunnerJobVideoEditionTranscodingPrivatePayload
+    const privatePayload = runnerJob.privatePayload as RunnerJobVideoStudioTranscodingPrivatePayload
 
     const video = await loadTranscodingRunnerVideo(runnerJob, this.lTags)
     if (!video) {
@@ -116,7 +116,7 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
 
     const videoFilePath = resultPayload.videoFile as string
 
-    await onVideoEditionEnded({ video, editionResultPath: videoFilePath, tasks: privatePayload.originalTasks })
+    await onVideoStudioEnded({ video, editionResultPath: videoFilePath, tasks: privatePayload.originalTasks })
 
     logger.info(
       'Runner video edition transcoding job %s for %s ended.',
@@ -146,7 +146,7 @@ export class VideoEditionTranscodingJobHandler extends AbstractJobHandler<Create
   }) {
     const { runnerJob } = options
 
-    const payload = runnerJob.privatePayload as RunnerJobVideoEditionTranscodingPrivatePayload
+    const payload = runnerJob.privatePayload as RunnerJobVideoStudioTranscodingPrivatePayload
     await safeCleanupStudioTMPFiles(payload.originalTasks)
 
     const video = await loadTranscodingRunnerVideo(options.runnerJob, this.lTags)
index 5251784ac874eb81c6449fcfd7ca7fb8214faa4c..8f8fdd026ecc1c38e313889a0bbb86731380024c 100644 (file)
@@ -1,88 +1,7 @@
 
 import { logger } from '@server/helpers/logger'
-import { getAverageBitrate, getMinLimitBitrate } from '@shared/core-utils'
-import { buildStreamSuffix, FFmpegCommandWrapper, ffprobePromise, getAudioStream, getMaxAudioBitrate } from '@shared/ffmpeg'
-import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams, VideoResolution } from '@shared/models'
-import { canDoQuickAudioTranscode } from './transcoding-quick-transcode'
-
-/**
- *
- * Available encoders and profiles for the transcoding jobs
- * These functions are used by ffmpeg-utils that will get the encoders and options depending on the chosen profile
- *
- * Resources:
- *  * https://slhck.info/video/2017/03/01/rate-control.html
- *  * https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate
- */
-
-// ---------------------------------------------------------------------------
-// Default builders
-// ---------------------------------------------------------------------------
-
-const defaultX264VODOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
-  const { fps, inputRatio, inputBitrate, resolution } = options
-
-  // TODO: remove in 4.2, fps is not optional anymore
-  if (!fps) return { outputOptions: [ ] }
-
-  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
-
-  return {
-    outputOptions: [
-      ...getCommonOutputOptions(targetBitrate),
-
-      `-r ${fps}`
-    ]
-  }
-}
-
-const defaultX264LiveOptionsBuilder: EncoderOptionsBuilder = (options: EncoderOptionsBuilderParams) => {
-  const { streamNum, fps, inputBitrate, inputRatio, resolution } = options
-
-  const targetBitrate = getTargetBitrate({ inputBitrate, ratio: inputRatio, fps, resolution })
-
-  return {
-    outputOptions: [
-      ...getCommonOutputOptions(targetBitrate, streamNum),
-
-      `${buildStreamSuffix('-r:v', streamNum)} ${fps}`,
-      `${buildStreamSuffix('-b:v', streamNum)} ${targetBitrate}`
-    ]
-  }
-}
-
-const defaultAACOptionsBuilder: EncoderOptionsBuilder = async ({ input, streamNum, canCopyAudio }) => {
-  const probe = await ffprobePromise(input)
-
-  if (canCopyAudio && await canDoQuickAudioTranscode(input, probe)) {
-    logger.debug('Copy audio stream %s by AAC encoder.', input)
-    return { copy: true, outputOptions: [ ] }
-  }
-
-  const parsedAudio = await getAudioStream(input, probe)
-
-  // We try to reduce the ceiling bitrate by making rough matches of bitrates
-  // Of course this is far from perfect, but it might save some space in the end
-
-  const audioCodecName = parsedAudio.audioStream['codec_name']
-
-  const bitrate = getMaxAudioBitrate(audioCodecName, parsedAudio.bitrate)
-
-  logger.debug('Calculating audio bitrate of %s by AAC encoder.', input, { bitrate: parsedAudio.bitrate, audioCodecName })
-
-  // Force stereo as it causes some issues with HLS playback in Chrome
-  const base = [ '-channel_layout', 'stereo' ]
-
-  if (bitrate !== -1) {
-    return { outputOptions: base.concat([ buildStreamSuffix('-b:a', streamNum), bitrate + 'k' ]) }
-  }
-
-  return { outputOptions: base }
-}
-
-const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum }) => {
-  return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] }
-}
+import { FFmpegCommandWrapper, getDefaultAvailableEncoders } from '@shared/ffmpeg'
+import { AvailableEncoders, EncoderOptionsBuilder } from '@shared/models'
 
 // ---------------------------------------------------------------------------
 // Profile manager to get and change default profiles
@@ -97,27 +16,7 @@ class VideoTranscodingProfilesManager {
     live: this.buildDefaultEncodersPriorities()
   }
 
-  private readonly availableEncoders = {
-    vod: {
-      libx264: {
-        default: defaultX264VODOptionsBuilder
-      },
-      aac: {
-        default: defaultAACOptionsBuilder
-      },
-      libfdk_aac: {
-        default: defaultLibFDKAACVODOptionsBuilder
-      }
-    },
-    live: {
-      libx264: {
-        default: defaultX264LiveOptionsBuilder
-      },
-      aac: {
-        default: defaultAACOptionsBuilder
-      }
-    }
-  }
+  private readonly availableEncoders = getDefaultAvailableEncoders()
 
   private availableProfiles = {
     vod: [] as string[],
@@ -242,41 +141,3 @@ class VideoTranscodingProfilesManager {
 export {
   VideoTranscodingProfilesManager
 }
-
-// ---------------------------------------------------------------------------
-
-function getTargetBitrate (options: {
-  inputBitrate: number
-  resolution: VideoResolution
-  ratio: number
-  fps: number
-}) {
-  const { inputBitrate, resolution, ratio, fps } = options
-
-  const capped = capBitrate(inputBitrate, getAverageBitrate({ resolution, fps, ratio }))
-  const limit = getMinLimitBitrate({ resolution, fps, ratio })
-
-  return Math.max(limit, capped)
-}
-
-function capBitrate (inputBitrate: number, targetBitrate: number) {
-  if (!inputBitrate) return targetBitrate
-
-  // Add 30% margin to input bitrate
-  const inputBitrateWithMargin = inputBitrate + (inputBitrate * 0.3)
-
-  return Math.min(targetBitrate, inputBitrateWithMargin)
-}
-
-function getCommonOutputOptions (targetBitrate: number, streamNum?: number) {
-  return [
-    `-preset veryfast`,
-    `${buildStreamSuffix('-maxrate:v', streamNum)} ${targetBitrate}`,
-    `${buildStreamSuffix('-bufsize:v', streamNum)} ${targetBitrate * 2}`,
-
-    // NOTE: b-strategy 1 - heuristic algorithm, 16 is optimal B-frames for it
-    `-b_strategy 1`,
-    // NOTE: Why 16: https://github.com/Chocobozzz/PeerTube/pull/774. b-strategy 2 -> B-frames<16
-    `-bf 16`
-  ]
-}
index 2c993faeb2d07dfccb066a5997ea8431238ec72e..0d3db8f60df884a0a25df35fcd7599b61d544aaf 100644 (file)
@@ -9,13 +9,13 @@ import { getVideoStreamDuration } from '@shared/ffmpeg'
 import { VideoStudioEditionPayload, VideoStudioTask, VideoStudioTaskPayload } from '@shared/models'
 import { federateVideoIfNeeded } from './activitypub/videos'
 import { JobQueue } from './job-queue'
-import { VideoEditionTranscodingJobHandler } from './runners'
+import { VideoStudioTranscodingJobHandler } from './runners'
 import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job'
 import { getTranscodingJobPriority } from './transcoding/transcoding-priority'
 import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file'
 import { VideoPathManager } from './video-path-manager'
 
-const lTags = loggerTagsFactory('video-edition')
+const lTags = loggerTagsFactory('video-studio')
 
 export function buildTaskFileFieldname (indice: number, fieldName = 'file') {
   return `tasks[${indice}][options][${fieldName}]`
@@ -78,14 +78,14 @@ export async function createVideoStudioJob (options: {
   const priority = await getTranscodingJobPriority({ user, type: 'studio', fallback: 0 })
 
   if (CONFIG.VIDEO_STUDIO.REMOTE_RUNNERS.ENABLED) {
-    await new VideoEditionTranscodingJobHandler().create({ video, tasks: payload.tasks, priority })
+    await new VideoStudioTranscodingJobHandler().create({ video, tasks: payload.tasks, priority })
     return
   }
 
   await JobQueue.Instance.createJob({ type: 'video-studio-edition', payload, priority })
 }
 
-export async function onVideoEditionEnded (options: {
+export async function onVideoStudioEnded (options: {
   editionResultPath: string
   tasks: VideoStudioTaskPayload[]
   video: MVideoFullLight
index e5afff0e5bd065f3506361303bf8da1230c8e3db..57c27fcfec384206dca60f091aeced632239f112 100644 (file)
@@ -2,7 +2,7 @@ import express from 'express'
 import { param } from 'express-validator'
 import { basename } from 'path'
 import { isSafeFilename } from '@server/helpers/custom-validators/misc'
-import { hasVideoStudioTaskFile, HttpStatusCode, RunnerJobVideoEditionTranscodingPayload } from '@shared/models'
+import { hasVideoStudioTaskFile, HttpStatusCode, RunnerJobStudioTranscodingPayload } from '@shared/models'
 import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared'
 
 const tags = [ 'runner' ]
@@ -37,7 +37,7 @@ export const runnerJobGetVideoStudioTaskFileValidator = [
 
     const filename = req.params.filename
 
-    const payload = res.locals.runnerJob.payload as RunnerJobVideoEditionTranscodingPayload
+    const payload = res.locals.runnerJob.payload as RunnerJobStudioTranscodingPayload
 
     const found = Array.isArray(payload?.tasks) && payload.tasks.some(t => {
       if (hasVideoStudioTaskFile(t)) {
index 90a3013929c68bc357b65b7fead630fa5ff033df..cee1993e60e6ba8767e0871c5d789c5003312b80 100644 (file)
@@ -8,7 +8,7 @@ import {
   RunnerJobState,
   RunnerJobSuccessPayload,
   RunnerJobUpdatePayload,
-  RunnerJobVideoEditionTranscodingPayload,
+  RunnerJobStudioTranscodingPayload,
   VideoPrivacy,
   VideoStudioTaskIntro
 } from '@shared/models'
@@ -404,10 +404,10 @@ describe('Test managing runners', function () {
           tasks: VideoStudioCommand.getComplexTask()
         })
 
-        const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'video-edition-transcoding' })
+        const { job } = await server.runnerJobs.autoAccept({ runnerToken, type: 'video-studio-transcoding' })
         studioAcceptedJob = job
 
-        const tasks = (job.payload as RunnerJobVideoEditionTranscodingPayload).tasks
+        const tasks = (job.payload as RunnerJobStudioTranscodingPayload).tasks
         const fileUrl = (tasks.find(t => isVideoStudioTaskIntro(t)) as VideoStudioTaskIntro).options.file as string
         studioFile = basename(fileUrl)
       }
@@ -787,7 +787,7 @@ describe('Test managing runners', function () {
 
       describe('Video studio', function () {
 
-        it('Should fail with an invalid video edition transcoding payload', async function () {
+        it('Should fail with an invalid video studio transcoding payload', async function () {
           await server.runnerJobs.success({
             jobUUID: studioAcceptedJob.uuid,
             jobToken: studioAcceptedJob.jobToken,
@@ -849,7 +849,7 @@ describe('Test managing runners', function () {
         })
       })
 
-      describe('Video edition tasks file routes', function () {
+      describe('Video studio tasks file routes', function () {
 
         it('Should fail with an invalid studio filename', async function () {
           await fetchStudioFiles({
index 9ae629be6e77970896b56d4da2bb576519e911b5..41c55677568eb53bfae29bf3233aba53bb5f199d 100644 (file)
@@ -5,8 +5,8 @@ import { readFile } from 'fs-extra'
 import { checkPersistentTmpIsEmpty, checkVideoDuration } from '@server/tests/shared'
 import { buildAbsoluteFixturePath } from '@shared/core-utils'
 import {
-  RunnerJobVideoEditionTranscodingPayload,
-  VideoEditionTranscodingSuccess,
+  RunnerJobStudioTranscodingPayload,
+  VideoStudioTranscodingSuccess,
   VideoState,
   VideoStudioTask,
   VideoStudioTaskIntro
@@ -121,10 +121,10 @@ describe('Test runner video studio transcoding', function () {
       await checkVideoDuration(server, videoUUID, 5)
     }
 
-    const { job } = await servers[0].runnerJobs.accept<RunnerJobVideoEditionTranscodingPayload>({ runnerToken, jobUUID })
+    const { job } = await servers[0].runnerJobs.accept<RunnerJobStudioTranscodingPayload>({ runnerToken, jobUUID })
     const jobToken = job.jobToken
 
-    expect(job.type === 'video-edition-transcoding')
+    expect(job.type === 'video-studio-transcoding')
     expect(job.payload.input.videoFileUrl).to.exist
 
     // Check video input file
@@ -150,7 +150,7 @@ describe('Test runner video studio transcoding', function () {
       expect(body).to.deep.equal(inputFile)
     }
 
-    const payload: VideoEditionTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' }
+    const payload: VideoStudioTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' }
     await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
 
     await waitJobs(servers)
index 2f64ef6bdb88c4f6019ff5012a61a99af563e625..d22cfff4a7d8b0a2c81425756a6917fca4c9a1ba 100644 (file)
@@ -270,7 +270,7 @@ describe('Test video studio', function () {
     })
   })
 
-  describe('HLS only video edition', function () {
+  describe('HLS only studio edition', function () {
 
     before(async function () {
       // Disable webtorrent
@@ -300,7 +300,7 @@ describe('Test video studio', function () {
     })
   })
 
-  describe('Object storage video edition', function () {
+  describe('Object storage studio edition', function () {
     if (areMockObjectStorageTestsDisabled()) return
 
     before(async function () {
similarity index 97%
rename from packages/peertube-runner/server/process/shared/transcoding-profiles.ts
rename to shared/ffmpeg/ffmpeg-default-transcoding-profile.ts
index 492d17d6adea51bc3de7a52045a8042cfbcbf3b7..f7fc49465e7f2d0fa5dab38d2a2bca08f3fc775f 100644 (file)
@@ -57,7 +57,7 @@ const defaultLibFDKAACVODOptionsBuilder: EncoderOptionsBuilder = ({ streamNum })
   return { outputOptions: [ buildStreamSuffix('-q:a', streamNum), '5' ] }
 }
 
-export function getAvailableEncoders () {
+export function getDefaultAvailableEncoders () {
   return {
     vod: {
       libx264: {
@@ -81,7 +81,7 @@ export function getAvailableEncoders () {
   }
 }
 
-export function getEncodersToTry () {
+export function getDefaultEncodersToTry () {
   return {
     vod: {
       video: [ 'libx264' ],
index 07a7d54024f39fe5f84d0d2580124da3444ae9d6..1dab292dab79091cb1d1f2ef6d550f69c9e9ac31 100644 (file)
@@ -1,4 +1,5 @@
 export * from './ffmpeg-command-wrapper'
+export * from './ffmpeg-default-transcoding-profile'
 export * from './ffmpeg-edition'
 export * from './ffmpeg-images'
 export * from './ffmpeg-live'
index 9f0db0dc40c3568898130748dac64b17cc7e7e4f..3dda6c51fc871bea288962338f61d608734ccef3 100644 (file)
@@ -8,7 +8,7 @@ export type RunnerJobVODPayload =
 export type RunnerJobPayload =
   RunnerJobVODPayload |
   RunnerJobLiveRTMPHLSTranscodingPayload |
-  RunnerJobVideoEditionTranscodingPayload
+  RunnerJobStudioTranscodingPayload
 
 // ---------------------------------------------------------------------------
 
@@ -46,7 +46,7 @@ export interface RunnerJobVODAudioMergeTranscodingPayload {
   }
 }
 
-export interface RunnerJobVideoEditionTranscodingPayload {
+export interface RunnerJobStudioTranscodingPayload {
   input: {
     videoFileUrl: string
   }
index c8fe0a7d83e57f81a5e90ec0fee67cfc99a24cce..32b837de482db9062fed14e39a9cd2155f8a3535 100644 (file)
@@ -8,7 +8,7 @@ export type RunnerJobVODPrivatePayload =
 export type RunnerJobPrivatePayload =
   RunnerJobVODPrivatePayload |
   RunnerJobLiveRTMPHLSTranscodingPrivatePayload |
-  RunnerJobVideoEditionTranscodingPrivatePayload
+  RunnerJobVideoStudioTranscodingPrivatePayload
 
 // ---------------------------------------------------------------------------
 
@@ -38,7 +38,7 @@ export interface RunnerJobLiveRTMPHLSTranscodingPrivatePayload {
 
 // ---------------------------------------------------------------------------
 
-export interface RunnerJobVideoEditionTranscodingPrivatePayload {
+export interface RunnerJobVideoStudioTranscodingPrivatePayload {
   videoUUID: string
   originalTasks: VideoStudioTaskPayload[]
 }
index 17e921f6968797c82168e536eb4074e13e0524c0..f45336b059e913db03019d82463aa52da2655497 100644 (file)
@@ -12,7 +12,7 @@ export type RunnerJobSuccessPayload =
   VODHLSTranscodingSuccess |
   VODAudioMergeTranscodingSuccess |
   LiveRTMPHLSTranscodingSuccess |
-  VideoEditionTranscodingSuccess
+  VideoStudioTranscodingSuccess
 
 export interface VODWebVideoTranscodingSuccess {
   videoFile: Blob | string
@@ -31,7 +31,7 @@ export interface LiveRTMPHLSTranscodingSuccess {
 
 }
 
-export interface VideoEditionTranscodingSuccess {
+export interface VideoStudioTranscodingSuccess {
   videoFile: Blob | string
 }
 
index 3b997cb6e101e23eb9be8bdf2e2efe85c1c72615..91b92a72941d7ae9e5eb8a960054827b560ff9fc 100644 (file)
@@ -3,4 +3,4 @@ export type RunnerJobType =
   'vod-hls-transcoding' |
   'vod-audio-merge-transcoding' |
   'live-rtmp-hls-transcoding' |
-  'video-edition-transcoding'
+  'video-studio-transcoding'