diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index 48678a194..5f0a5ff6c 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -436,8 +436,25 @@
+
+
new transcoding profiles can be added by PeerTube plugins
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index ae6a9e844..48fb86968 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -9,6 +9,7 @@ import {
ADMIN_EMAIL_VALIDATOR,
CACHE_CAPTIONS_SIZE_VALIDATOR,
CACHE_PREVIEWS_SIZE_VALIDATOR,
+ CONCURRENCY_VALIDATOR,
INDEX_URL_VALIDATOR,
INSTANCE_NAME_VALIDATOR,
INSTANCE_SHORT_DESCRIPTION_VALIDATOR,
@@ -36,6 +37,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
resolutions: { id: string, label: string, description?: string }[] = []
liveResolutions: { id: string, label: string, description?: string }[] = []
+ concurrencyOptions: number[] = []
transcodingThreadOptions: { label: string, value: number }[] = []
liveMaxDurationOptions: { label: string, value: number }[] = []
@@ -103,6 +105,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
{ value: 4, label: '4' },
{ value: 8, label: '8' }
]
+ this.concurrencyOptions = [ 1, 2, 3, 4, 5, 6 ]
this.vodTranscodingProfileOptions = [ 'default' ]
this.liveTranscodingProfileOptions = [ 'default' ]
@@ -230,6 +233,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
},
import: {
videos: {
+ concurrency: CONCURRENCY_VALIDATOR,
http: {
enabled: null
},
@@ -262,6 +266,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
allowAdditionalExtensions: null,
allowAudioFiles: null,
profile: null,
+ concurrency: CONCURRENCY_VALIDATOR,
resolutions: {},
hls: {
enabled: null
diff --git a/client/src/app/shared/form-validators/custom-config-validators.ts b/client/src/app/shared/form-validators/custom-config-validators.ts
index 41b3cbba9..23f2156c2 100644
--- a/client/src/app/shared/form-validators/custom-config-validators.ts
+++ b/client/src/app/shared/form-validators/custom-config-validators.ts
@@ -65,6 +65,14 @@ export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = {
}
}
+export const CONCURRENCY_VALIDATOR: BuildFormValidator = {
+ VALIDATORS: [Validators.required, Validators.min(1)],
+ MESSAGES: {
+ 'required': $localize`Concurrency is required.`,
+ 'min': $localize`Concurrency should be greater or equal to 1.`
+ }
+}
+
export const INDEX_URL_VALIDATOR: BuildFormValidator = {
VALIDATORS: [Validators.pattern(/^https:\/\//)],
MESSAGES: {
diff --git a/config/default.yaml b/config/default.yaml
index 95df2e06c..3bbb3e5c4 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -233,7 +233,10 @@ transcoding:
# If a user uploads an audio file, PeerTube will create a video by merging the preview file and the audio file
allow_audio_files: true
+ # Amount of threads used by ffmpeg for 1 transcoding job
threads: 1
+ # Amount of transcoding jobs to execute in parallel
+ concurrency: 1
# Choose the transcoding profile
# New profiles can be added by plugins
@@ -312,6 +315,9 @@ live:
import:
# Add ability for your users to import remote videos (from YouTube, torrent...)
videos:
+ # Amount of import jobs to execute in parallel
+ concurrency: 1
+
http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html
enabled: false
diff --git a/config/production.yaml.example b/config/production.yaml.example
index 13a646918..d75e30276 100644
--- a/config/production.yaml.example
+++ b/config/production.yaml.example
@@ -244,7 +244,10 @@ transcoding:
# If a user uploads an audio file, PeerTube will create a video by merging the preview file and the audio file
allow_audio_files: true
+ # Amount of threads used by ffmpeg for 1 transcoding job
threads: 1
+ # Amount of transcoding jobs to execute in parallel
+ concurrency: 1
# Choose the transcoding profile
# New profiles can be added by plugins
@@ -323,6 +326,9 @@ live:
import:
# Add ability for your users to import remote videos (from YouTube, torrent...)
videos:
+ # Amount of import jobs to execute in parallel
+ concurrency: 1
+
http: # Classic HTTP or all sites supported by youtube-dl https://rg3.github.io/youtube-dl/supportedsites.html
enabled: false
diff --git a/config/test.yaml b/config/test.yaml
index 6fedb1dc3..ae8011ba5 100644
--- a/config/test.yaml
+++ b/config/test.yaml
@@ -71,6 +71,7 @@ transcoding:
allow_additional_extensions: false
allow_audio_files: false
threads: 2
+ concurrency: 2
resolutions:
0p: false
240p: true
@@ -106,6 +107,7 @@ live:
import:
videos:
+ concurrency: 2
http:
enabled: true
proxy:
diff --git a/scripts/create-transcoding-job.ts b/scripts/create-transcoding-job.ts
index eb620aeca..5f56d6d36 100755
--- a/scripts/create-transcoding-job.ts
+++ b/scripts/create-transcoding-job.ts
@@ -53,7 +53,8 @@ async function run () {
videoUUID: video.uuid,
resolution,
isPortraitMode: false,
- copyCodecs: false
+ copyCodecs: false,
+ isMaxQuality: false
})
}
} else if (options.resolution !== undefined) {
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 7fda06a87..5c242da04 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -417,6 +417,7 @@ function customConfig (): CustomConfig {
allowAdditionalExtensions: CONFIG.TRANSCODING.ALLOW_ADDITIONAL_EXTENSIONS,
allowAudioFiles: CONFIG.TRANSCODING.ALLOW_AUDIO_FILES,
threads: CONFIG.TRANSCODING.THREADS,
+ concurrency: CONFIG.TRANSCODING.CONCURRENCY,
profile: CONFIG.TRANSCODING.PROFILE,
resolutions: {
'0p': CONFIG.TRANSCODING.RESOLUTIONS['0p'],
@@ -458,6 +459,7 @@ function customConfig (): CustomConfig {
},
import: {
videos: {
+ concurrency: CONFIG.IMPORT.VIDEOS.CONCURRENCY,
http: {
enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED
},
diff --git a/server/initializers/checker-after-init.ts b/server/initializers/checker-after-init.ts
index 979c97a8b..2b00e2047 100644
--- a/server/initializers/checker-after-init.ts
+++ b/server/initializers/checker-after-init.ts
@@ -116,6 +116,16 @@ function checkConfig () {
if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) {
return 'You need to enable at least WebTorrent transcoding or HLS transcoding.'
}
+
+ if (CONFIG.TRANSCODING.CONCURRENCY <= 0) {
+ return 'Transcoding concurrency should be > 0'
+ }
+ }
+
+ if (CONFIG.IMPORT.VIDEOS.HTTP.ENABLED || CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED) {
+ if (CONFIG.IMPORT.VIDEOS.CONCURRENCY <= 0) {
+ return 'Video import concurrency should be > 0'
+ }
}
// Broadcast message
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts
index cac24f0b6..a186afbdd 100644
--- a/server/initializers/checker-before-init.ts
+++ b/server/initializers/checker-before-init.ts
@@ -22,10 +22,10 @@ function checkMissedConfig () {
'signup.filters.cidr.whitelist', 'signup.filters.cidr.blacklist',
'redundancy.videos.strategies', 'redundancy.videos.check_interval',
'transcoding.enabled', 'transcoding.threads', 'transcoding.allow_additional_extensions', 'transcoding.hls.enabled',
- 'transcoding.profile',
+ 'transcoding.profile', 'transcoding.concurrency',
'transcoding.resolutions.0p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p', 'transcoding.resolutions.480p',
'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p', 'transcoding.resolutions.2160p',
- 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'auto_blacklist.videos.of_users.enabled',
+ 'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'auto_blacklist.videos.of_users.enabled',
'trending.videos.interval_days',
'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route',
'instance.is_nsfw', 'instance.default_nsfw_policy', 'instance.robots', 'instance.securitytxt',
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index 3b44d82ed..930fd784e 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -188,6 +188,7 @@ const CONFIG = {
get ALLOW_ADDITIONAL_EXTENSIONS () { return config.get('transcoding.allow_additional_extensions') },
get ALLOW_AUDIO_FILES () { return config.get('transcoding.allow_audio_files') },
get THREADS () { return config.get('transcoding.threads') },
+ get CONCURRENCY () { return config.get('transcoding.concurrency') },
get PROFILE () { return config.get('transcoding.profile') },
RESOLUTIONS: {
get '0p' () { return config.get('transcoding.resolutions.0p') },
@@ -237,6 +238,8 @@ const CONFIG = {
},
IMPORT: {
VIDEOS: {
+ get CONCURRENCY () { return config.get('import.videos.concurrency') },
+
HTTP: {
get ENABLED () { return config.get('import.videos.http.enabled') },
get FORCE_IPV4 () { return config.get('import.videos.http.force_ipv4') },
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
index 9d9b3966c..7beaca238 100644
--- a/server/initializers/constants.ts
+++ b/server/initializers/constants.ts
@@ -146,14 +146,12 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = {
'video-redundancy': 1,
'video-live-ending': 1
}
-const JOB_CONCURRENCY: { [id in JobType]: number } = {
+const JOB_CONCURRENCY: { [id in JobType]?: number } = {
'activitypub-http-broadcast': 1,
'activitypub-http-unicast': 5,
'activitypub-http-fetcher': 1,
'activitypub-follow': 1,
'video-file-import': 1,
- 'video-transcoding': 1,
- 'video-import': 1,
'email': 5,
'videos-views': 1,
'activitypub-refresher': 1,
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
index 4718a7d5c..e248b645e 100644
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ b/server/lib/job-queue/handlers/video-transcoding.ts
@@ -76,7 +76,7 @@ async function processVideoTranscoding (job: Bull.Job) {
// Job handlers
// ---------------------------------------------------------------------------
-async function handleHLSJob (job: Bull.Job, payload: HLSTranscodingPayload, video: MVideoFullLight) {
+async function handleHLSJob (job: Bull.Job, payload: HLSTranscodingPayload, video: MVideoFullLight, user: MUser) {
const videoFileInput = payload.copyCodecs
? video.getWebTorrentFile(payload.resolution)
: video.getMaxQualityFile()
@@ -93,7 +93,7 @@ async function handleHLSJob (job: Bull.Job, payload: HLSTranscodingPayload, vide
job
})
- await retryTransactionWrapper(onHlsPlaylistGeneration, video, payload.resolution)
+ await retryTransactionWrapper(onHlsPlaylistGeneration, video, user, payload)
}
async function handleNewWebTorrentResolutionJob (
@@ -110,9 +110,7 @@ async function handleNewWebTorrentResolutionJob (
async function handleWebTorrentMergeAudioJob (job: Bull.Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
await mergeAudioVideofile(video, payload.resolution, job)
- await retryTransactionWrapper(onNewWebTorrentFileResolution, video, user, payload)
-
- await createLowerResolutionsJobs(video, user, payload.resolution, false)
+ await retryTransactionWrapper(onVideoFileOptimizer, video, payload, 'video', user)
}
async function handleWebTorrentOptimizeJob (job: Bull.Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
@@ -123,13 +121,11 @@ async function handleWebTorrentOptimizeJob (job: Bull.Job, payload: OptimizeTran
// ---------------------------------------------------------------------------
-async function onHlsPlaylistGeneration (video: MVideoFullLight, resolution: number) {
+async function onHlsPlaylistGeneration (video: MVideoFullLight, user: MUser, payload: HLSTranscodingPayload) {
if (video === undefined) return undefined
- const maxQualityFile = video.getMaxQualityFile()
-
- // We generated the max quality HLS playlist, we don't need the webtorrent files anymore if the admin disabled it
- if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && video.hasWebTorrentFiles() && maxQualityFile.resolution === resolution) {
+ if (payload.isMaxQuality && CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false) {
+ // Remove webtorrent files if not enabled
for (const file of video.VideoFiles) {
await video.removeFile(file)
await video.removeTorrent(file)
@@ -137,6 +133,9 @@ async function onHlsPlaylistGeneration (video: MVideoFullLight, resolution: numb
}
video.VideoFiles = []
+
+ // Create HLS new resolution jobs
+ await createLowerResolutionsJobs(video, user, payload.resolution, payload.isPortraitMode, 'hls')
}
return publishAndFederateIfNeeded(video)
@@ -144,7 +143,7 @@ async function onHlsPlaylistGeneration (video: MVideoFullLight, resolution: numb
async function onVideoFileOptimizer (
videoArg: MVideoWithFile,
- payload: OptimizeTranscodingPayload,
+ payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload,
transcodeType: TranscodeOptionsType,
user: MUserId
) {
@@ -166,11 +165,12 @@ async function onVideoFileOptimizer (
isPortraitMode,
resolution: videoDatabase.getMaxQualityFile().resolution,
// If we quick transcoded original file, force transcoding for HLS to avoid some weird playback issues
- copyCodecs: transcodeType !== 'quick-transcode'
+ copyCodecs: transcodeType !== 'quick-transcode',
+ isMaxQuality: true
})
await createHlsJobIfEnabled(user, originalFileHLSPayload)
- const hasNewResolutions = createLowerResolutionsJobs(videoDatabase, user, videoFileResolution, isPortraitMode)
+ const hasNewResolutions = await createLowerResolutionsJobs(videoDatabase, user, videoFileResolution, isPortraitMode, 'webtorrent')
if (!hasNewResolutions) {
// No transcoding to do, it's now published
@@ -193,7 +193,7 @@ async function onNewWebTorrentFileResolution (
) {
await publishAndFederateIfNeeded(video)
- await createHlsJobIfEnabled(user, Object.assign({}, payload, { copyCodecs: true }))
+ await createHlsJobIfEnabled(user, Object.assign({}, payload, { copyCodecs: true, isMaxQuality: false }))
}
// ---------------------------------------------------------------------------
@@ -210,6 +210,7 @@ async function createHlsJobIfEnabled (user: MUserId, payload: {
resolution: number
isPortraitMode?: boolean
copyCodecs: boolean
+ isMaxQuality: boolean
}) {
if (!payload || CONFIG.TRANSCODING.HLS.ENABLED !== true) return
@@ -222,7 +223,8 @@ async function createHlsJobIfEnabled (user: MUserId, payload: {
videoUUID: payload.videoUUID,
resolution: payload.resolution,
isPortraitMode: payload.isPortraitMode,
- copyCodecs: payload.copyCodecs
+ copyCodecs: payload.copyCodecs,
+ isMaxQuality: payload.isMaxQuality
}
return JobQueue.Instance.createJobWithPromise({ type: 'video-transcoding', payload: hlsTranscodingPayload }, jobOptions)
@@ -232,7 +234,8 @@ async function createLowerResolutionsJobs (
video: MVideoFullLight,
user: MUserId,
videoFileResolution: number,
- isPortraitMode: boolean
+ isPortraitMode: boolean,
+ type: 'hls' | 'webtorrent'
) {
// Create transcoding jobs if there are enabled resolutions
const resolutionsEnabled = computeResolutionsToTranscode(videoFileResolution, 'vod')
@@ -250,7 +253,7 @@ async function createLowerResolutionsJobs (
for (const resolution of resolutionsEnabled) {
let dataInput: VideoTranscodingPayload
- if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED) {
+ if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED && type === 'webtorrent') {
// WebTorrent will create subsequent HLS job
dataInput = {
type: 'new-resolution-to-webtorrent',
@@ -258,13 +261,16 @@ async function createLowerResolutionsJobs (
resolution,
isPortraitMode
}
- } else if (CONFIG.TRANSCODING.HLS.ENABLED) {
+ }
+
+ if (CONFIG.TRANSCODING.HLS.ENABLED && type === 'hls') {
dataInput = {
type: 'new-resolution-to-hls',
videoUUID: video.uuid,
resolution,
isPortraitMode,
- copyCodecs: false
+ copyCodecs: false,
+ isMaxQuality: false
}
}
diff --git a/server/lib/job-queue/job-queue.ts b/server/lib/job-queue/job-queue.ts
index 38b1d6f1f..72fed6072 100644
--- a/server/lib/job-queue/job-queue.ts
+++ b/server/lib/job-queue/job-queue.ts
@@ -1,5 +1,6 @@
import * as Bull from 'bull'
import { jobStates } from '@server/helpers/custom-validators/jobs'
+import { CONFIG } from '@server/initializers/config'
import { processVideoRedundancy } from '@server/lib/job-queue/handlers/video-redundancy'
import {
ActivitypubFollowPayload,
@@ -105,11 +106,11 @@ class JobQueue {
}
}
- for (const handlerName of Object.keys(handlers)) {
+ for (const handlerName of (Object.keys(handlers) as JobType[])) {
const queue = new Bull(handlerName, queueOptions)
const handler = handlers[handlerName]
- queue.process(JOB_CONCURRENCY[handlerName], handler)
+ queue.process(this.getJobConcurrency(handlerName), handler)
.catch(err => logger.error('Error in job queue processor %s.', handlerName, { err }))
queue.on('failed', (job, err) => {
@@ -235,6 +236,13 @@ class JobQueue {
return jobTypes.filter(t => t === jobType)
}
+ private getJobConcurrency (jobType: JobType) {
+ if (jobType === 'video-transcoding') return CONFIG.TRANSCODING.CONCURRENCY
+ if (jobType === 'video-import') return CONFIG.IMPORT.VIDEOS.CONCURRENCY
+
+ return JOB_CONCURRENCY[jobType]
+ }
+
static get Instance () {
return this.instance || (this.instance = new this())
}
diff --git a/server/lib/video-transcoding.ts b/server/lib/video-transcoding.ts
index 88a6e0673..a58c9dd20 100644
--- a/server/lib/video-transcoding.ts
+++ b/server/lib/video-transcoding.ts
@@ -272,7 +272,7 @@ async function generateHlsPlaylistCommon (options: {
const { type, video, inputPath, resolution, copyCodecs, isPortraitMode, isAAC, job } = options
const transcodeDirectory = CONFIG.STORAGE.TMP_DIR
- const videoTranscodedBasePath = join(transcodeDirectory, type, video.uuid)
+ const videoTranscodedBasePath = join(transcodeDirectory, type)
await ensureDir(videoTranscodedBasePath)
const videoFilename = generateVideoStreamingPlaylistName(video.uuid, resolution)
@@ -337,8 +337,6 @@ async function generateHlsPlaylistCommon (options: {
await move(playlistFileTranscodePath, playlistPath, { overwrite: true })
// Move video file
await move(join(videoTranscodedBasePath, videoFilename), videoFilePath, { overwrite: true })
- // Cleanup directory
- await remove(videoTranscodedBasePath)
const stats = await stat(videoFilePath)
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts
index 52c28799f..71098ff99 100644
--- a/server/middlewares/validators/config.ts
+++ b/server/middlewares/validators/config.ts
@@ -39,6 +39,7 @@ const customConfigUpdateValidator = [
body('transcoding.enabled').isBoolean().withMessage('Should have a valid transcoding enabled boolean'),
body('transcoding.allowAdditionalExtensions').isBoolean().withMessage('Should have a valid additional extensions boolean'),
body('transcoding.threads').isInt().withMessage('Should have a valid transcoding threads number'),
+ body('transcoding.concurrency').isInt({ min: 1 }).withMessage('Should have a valid transcoding concurrency number'),
body('transcoding.resolutions.0p').isBoolean().withMessage('Should have a valid transcoding 0p resolution enabled boolean'),
body('transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
body('transcoding.resolutions.360p').isBoolean().withMessage('Should have a valid transcoding 360p resolution enabled boolean'),
@@ -51,6 +52,7 @@ const customConfigUpdateValidator = [
body('transcoding.webtorrent.enabled').isBoolean().withMessage('Should have a valid webtorrent transcoding enabled boolean'),
body('transcoding.hls.enabled').isBoolean().withMessage('Should have a valid hls transcoding enabled boolean'),
+ body('import.videos.concurrency').isInt({ min: 0 }).withMessage('Should have a valid import concurrency number'),
body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'),
body('import.videos.torrent.enabled').isBoolean().withMessage('Should have a valid import video torrent enabled boolean'),
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 3f6fd8dc0..14e80a3ba 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -345,7 +345,6 @@ export type AvailableForListIDsOptions = {
include: [
{
model: VideoFileModel,
- separate: true, // We may have multiple files, having multiple redundancies so let's separate this join
required: false,
include: subInclude
}
@@ -372,7 +371,6 @@ export type AvailableForListIDsOptions = {
include: [
{
model: VideoStreamingPlaylistModel.unscoped(),
- separate: true, // We may have multiple streaming playlists, having multiple redundancies so let's separate this join
required: false,
include: subInclude
}
@@ -1689,7 +1687,7 @@ export class VideoModel extends Model {
channelModel.Account = accountModel
- const videoModel = new VideoModel(pick(row, videoKeys))
+ const videoModel = new VideoModel(pick(row, videoKeys), buildOpts)
videoModel.VideoChannel = channelModel
videoModel.UserVideoHistories = []
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index d6c20f7af..c7eb3189b 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -86,6 +86,7 @@ describe('Test config API validators', function () {
enabled: true,
allowAdditionalExtensions: true,
allowAudioFiles: true,
+ concurrency: 1,
threads: 1,
profile: 'vod_profile',
resolutions: {
@@ -130,6 +131,7 @@ describe('Test config API validators', function () {
},
import: {
videos: {
+ concurrency: 1,
http: {
enabled: false
},
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index 26df8373e..b2371614f 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -70,6 +70,7 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
expect(data.transcoding.allowAdditionalExtensions).to.be.false
expect(data.transcoding.allowAudioFiles).to.be.false
expect(data.transcoding.threads).to.equal(2)
+ expect(data.transcoding.concurrency).to.equal(2)
expect(data.transcoding.profile).to.equal('default')
expect(data.transcoding.resolutions['240p']).to.be.true
expect(data.transcoding.resolutions['360p']).to.be.true
@@ -97,6 +98,7 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
expect(data.live.transcoding.resolutions['1440p']).to.be.false
expect(data.live.transcoding.resolutions['2160p']).to.be.false
+ expect(data.import.videos.concurrency).to.equal(2)
expect(data.import.videos.http.enabled).to.be.true
expect(data.import.videos.torrent.enabled).to.be.true
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.false
@@ -159,6 +161,7 @@ function checkUpdatedConfig (data: CustomConfig) {
expect(data.transcoding.enabled).to.be.true
expect(data.transcoding.threads).to.equal(1)
+ expect(data.transcoding.concurrency).to.equal(3)
expect(data.transcoding.allowAdditionalExtensions).to.be.true
expect(data.transcoding.allowAudioFiles).to.be.true
expect(data.transcoding.profile).to.equal('vod_profile')
@@ -186,6 +189,7 @@ function checkUpdatedConfig (data: CustomConfig) {
expect(data.live.transcoding.resolutions['1080p']).to.be.true
expect(data.live.transcoding.resolutions['2160p']).to.be.true
+ expect(data.import.videos.concurrency).to.equal(4)
expect(data.import.videos.http.enabled).to.be.false
expect(data.import.videos.torrent.enabled).to.be.false
expect(data.autoBlacklist.videos.ofUsers.enabled).to.be.true
@@ -323,6 +327,7 @@ describe('Test config', function () {
allowAdditionalExtensions: true,
allowAudioFiles: true,
threads: 1,
+ concurrency: 3,
profile: 'vod_profile',
resolutions: {
'0p': false,
@@ -364,6 +369,7 @@ describe('Test config', function () {
},
import: {
videos: {
+ concurrency: 4,
http: {
enabled: false
},
diff --git a/shared/extra-utils/server/config.ts b/shared/extra-utils/server/config.ts
index db5a473ca..efe569243 100644
--- a/shared/extra-utils/server/config.ts
+++ b/shared/extra-utils/server/config.ts
@@ -112,6 +112,7 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti
allowAdditionalExtensions: true,
allowAudioFiles: true,
threads: 1,
+ concurrency: 3,
profile: 'default',
resolutions: {
'0p': false,
@@ -153,6 +154,7 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti
},
import: {
videos: {
+ concurrency: 3,
http: {
enabled: false
},
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index d23b8abef..93b2d3417 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -87,6 +87,7 @@ export interface CustomConfig {
allowAudioFiles: boolean
threads: number
+ concurrency: number
profile: string
@@ -120,6 +121,8 @@ export interface CustomConfig {
import: {
videos: {
+ concurrency: number
+
http: {
enabled: boolean
}
diff --git a/shared/models/server/job.model.ts b/shared/models/server/job.model.ts
index ddd678b91..44f92abf1 100644
--- a/shared/models/server/job.model.ts
+++ b/shared/models/server/job.model.ts
@@ -106,6 +106,7 @@ export interface HLSTranscodingPayload extends BaseTranscodingPayload {
isPortraitMode?: boolean
resolution: VideoResolution
copyCodecs: boolean
+ isMaxQuality: boolean
}
export interface NewResolutionTranscodingPayload extends BaseTranscodingPayload {