aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html10
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts13
-rw-r--r--client/src/app/core/server/server.service.ts2
-rw-r--r--client/src/app/shared/shared-instance/instance-features-table.component.html7
-rw-r--r--client/src/app/shared/shared-instance/instance-features-table.component.ts14
-rw-r--r--config/default.yaml8
-rw-r--r--server/controllers/api/config.ts4
-rw-r--r--server/initializers/checker-before-init.ts2
-rw-r--r--server/initializers/config.ts3
-rw-r--r--server/middlewares/validators/config.ts2
-rw-r--r--server/middlewares/validators/videos/video-live.ts35
-rw-r--r--server/models/video/video.ts31
-rw-r--r--server/tests/api/check-params/config.ts2
-rw-r--r--server/tests/api/server/config.ts6
-rw-r--r--shared/extra-utils/server/config.ts2
-rw-r--r--shared/models/server/custom-config.model.ts3
-rw-r--r--shared/models/server/server-config.model.ts2
-rw-r--r--shared/models/server/server-error-code.enum.ts4
19 files changed, 147 insertions, 5 deletions
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 2f3202e06..686f3601b 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
@@ -740,6 +740,16 @@
740 </div> 740 </div>
741 741
742 <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }"> 742 <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
743 <label i18n for="liveMaxInstanceLives">Max lives created on your instance (-1 for "unlimited")</label>
744 <input type="number" name="liveMaxInstanceLives" formControlName="maxInstanceLives" />
745 </div>
746
747 <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
748 <label i18n for="liveMaxUserLives">Max lives created per user (-1 for "unlimited")</label>
749 <input type="number" name="liveMaxUserLives" formControlName="maxUserLives" />
750 </div>
751
752 <div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
743 <label i18n for="liveMaxDuration">Max live duration</label> 753 <label i18n for="liveMaxDuration">Max live duration</label>
744 <div class="peertube-select-container"> 754 <div class="peertube-select-container">
745 <select id="liveMaxDuration" formControlName="maxDuration" class="form-control"> 755 <select id="liveMaxDuration" formControlName="maxDuration" class="form-control">
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 745238647..de1cf46b1 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
@@ -216,6 +216,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
216 enabled: null, 216 enabled: null,
217 217
218 maxDuration: null, 218 maxDuration: null,
219 maxInstanceLives: null,
220 maxUserLives: null,
219 allowReplay: null, 221 allowReplay: null,
220 222
221 transcoding: { 223 transcoding: {
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
index 9868c37d2..870a70d3d 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
@@ -7,7 +7,7 @@ import { scrollToTop } from '@app/helpers'
7import { FormValidatorService } from '@app/shared/shared-forms' 7import { FormValidatorService } from '@app/shared/shared-forms'
8import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' 8import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
9import { LoadingBarService } from '@ngx-loading-bar/core' 9import { LoadingBarService } from '@ngx-loading-bar/core'
10import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoPrivacy } from '@shared/models' 10import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, ServerErrorCode, VideoPrivacy } from '@shared/models'
11import { VideoSend } from './video-send' 11import { VideoSend } from './video-send'
12 12
13@Component({ 13@Component({
@@ -81,7 +81,16 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, CanCompon
81 81
82 err => { 82 err => {
83 this.firstStepError.emit() 83 this.firstStepError.emit()
84 this.notifier.error(err.message) 84
85 let message = err.message
86
87 if (err.body?.code === ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED) {
88 message = $localize`Cannot create live because this instance have too many created lives`
89 } else if (err.body?.code) {
90 message = $localize`Cannot create live because you created too many lives`
91 }
92
93 this.notifier.error(message)
85 } 94 }
86 ) 95 )
87 } 96 }
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index c19c3c12e..1abf87118 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -78,6 +78,8 @@ export class ServerService {
78 enabled: false, 78 enabled: false,
79 allowReplay: true, 79 allowReplay: true,
80 maxDuration: null, 80 maxDuration: null,
81 maxInstanceLives: -1,
82 maxUserLives: -1,
81 transcoding: { 83 transcoding: {
82 enabled: false, 84 enabled: false,
83 enabledResolutions: [] 85 enabledResolutions: []
diff --git a/client/src/app/shared/shared-instance/instance-features-table.component.html b/client/src/app/shared/shared-instance/instance-features-table.component.html
index 002695238..ce2557147 100644
--- a/client/src/app/shared/shared-instance/instance-features-table.component.html
+++ b/client/src/app/shared/shared-instance/instance-features-table.component.html
@@ -82,6 +82,13 @@
82 </tr> 82 </tr>
83 83
84 <tr> 84 <tr>
85 <th i18n class="sub-label" scope="row">Max parallel lives</th>
86 <td i18n>
87 {{ maxUserLives }} per user / {{ maxInstanceLives }} per instance
88 </td>
89 </tr>
90
91 <tr>
85 <th i18n class="label" colspan="2">Import</th> 92 <th i18n class="label" colspan="2">Import</th>
86 </tr> 93 </tr>
87 94
diff --git a/client/src/app/shared/shared-instance/instance-features-table.component.ts b/client/src/app/shared/shared-instance/instance-features-table.component.ts
index 76b595c20..0166157f9 100644
--- a/client/src/app/shared/shared-instance/instance-features-table.component.ts
+++ b/client/src/app/shared/shared-instance/instance-features-table.component.ts
@@ -21,6 +21,20 @@ export class InstanceFeaturesTableComponent implements OnInit {
21 return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily) 21 return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily)
22 } 22 }
23 23
24 get maxInstanceLives () {
25 const value = this.serverConfig.live.maxInstanceLives
26 if (value === -1) return $localize`Unlimited`
27
28 return value
29 }
30
31 get maxUserLives () {
32 const value = this.serverConfig.live.maxUserLives
33 if (value === -1) return $localize`Unlimited`
34
35 return value
36 }
37
24 ngOnInit () { 38 ngOnInit () {
25 this.serverConfig = this.serverService.getTmpConfig() 39 this.serverConfig = this.serverService.getTmpConfig()
26 this.serverService.getConfig() 40 this.serverService.getConfig()
diff --git a/config/default.yaml b/config/default.yaml
index d0937bfc8..af16f081f 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -250,6 +250,14 @@ live:
250 # Set null to disable duration limit 250 # Set null to disable duration limit
251 max_duration: 5 hours 251 max_duration: 5 hours
252 252
253 # Limit max number of live videos created on your instance
254 # -1 == unlimited
255 max_instance_lives: 20
256
257 # Limit max number of live videos created by a user on your instance
258 # -1 == unlimited
259 max_user_lives: 3
260
253 # Allow your users to save a replay of their live 261 # Allow your users to save a replay of their live
254 # PeerTube will transcode segments in a video file 262 # PeerTube will transcode segments in a video file
255 # If the user daily/total quota is reached, PeerTube will stop the live 263 # If the user daily/total quota is reached, PeerTube will stop the live
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 99aabba62..eb9f5f4b4 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -120,6 +120,8 @@ async function getConfig (req: express.Request, res: express.Response) {
120 120
121 allowReplay: CONFIG.LIVE.ALLOW_REPLAY, 121 allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
122 maxDuration: CONFIG.LIVE.MAX_DURATION, 122 maxDuration: CONFIG.LIVE.MAX_DURATION,
123 maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES,
124 maxUserLives: CONFIG.LIVE.MAX_USER_LIVES,
123 125
124 transcoding: { 126 transcoding: {
125 enabled: CONFIG.LIVE.TRANSCODING.ENABLED, 127 enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
@@ -430,6 +432,8 @@ function customConfig (): CustomConfig {
430 enabled: CONFIG.LIVE.ENABLED, 432 enabled: CONFIG.LIVE.ENABLED,
431 allowReplay: CONFIG.LIVE.ALLOW_REPLAY, 433 allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
432 maxDuration: CONFIG.LIVE.MAX_DURATION, 434 maxDuration: CONFIG.LIVE.MAX_DURATION,
435 maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES,
436 maxUserLives: CONFIG.LIVE.MAX_USER_LIVES,
433 transcoding: { 437 transcoding: {
434 enabled: CONFIG.LIVE.TRANSCODING.ENABLED, 438 enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
435 threads: CONFIG.LIVE.TRANSCODING.THREADS, 439 threads: CONFIG.LIVE.TRANSCODING.THREADS,
diff --git a/server/initializers/checker-before-init.ts b/server/initializers/checker-before-init.ts
index d4140e3fa..93b71a242 100644
--- a/server/initializers/checker-before-init.ts
+++ b/server/initializers/checker-before-init.ts
@@ -38,7 +38,7 @@ function checkMissedConfig () {
38 'federation.videos.federate_unlisted', 38 'federation.videos.federate_unlisted',
39 'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url', 39 'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url',
40 'search.search_index.disable_local_search', 'search.search_index.is_default_search', 40 'search.search_index.disable_local_search', 'search.search_index.is_default_search',
41 'live.enabled', 'live.allow_replay', 'live.max_duration', 41 'live.enabled', 'live.allow_replay', 'live.max_duration', 'live.max_user_lives', 'live.max_instance_lives',
42 'live.transcoding.enabled', 'live.transcoding.threads', 42 'live.transcoding.enabled', 'live.transcoding.threads',
43 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p', 43 'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p',
44 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p' 44 'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p'
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index 9e8927350..b70361aa9 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -202,6 +202,9 @@ const CONFIG = {
202 get ENABLED () { return config.get<boolean>('live.enabled') }, 202 get ENABLED () { return config.get<boolean>('live.enabled') },
203 203
204 get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) }, 204 get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) },
205 get MAX_INSTANCE_LIVES () { return config.get<number>('live.max_instance_lives') },
206 get MAX_USER_LIVES () { return config.get<number>('live.max_user_lives') },
207
205 get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') }, 208 get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') },
206 209
207 RTMP: { 210 RTMP: {
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts
index 41a6ae4f9..d0071ccc1 100644
--- a/server/middlewares/validators/config.ts
+++ b/server/middlewares/validators/config.ts
@@ -65,6 +65,8 @@ const customConfigUpdateValidator = [
65 body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'), 65 body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'),
66 body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'), 66 body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'),
67 body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'), 67 body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'),
68 body('live.maxInstanceLives').custom(isIntOrNull).withMessage('Should have a valid max instance lives'),
69 body('live.maxUserLives').custom(isIntOrNull).withMessage('Should have a valid max user lives'),
68 body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'), 70 body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'),
69 body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'), 71 body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'),
70 body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'), 72 body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts
index ab57e67bf..69200cb60 100644
--- a/server/middlewares/validators/videos/video-live.ts
+++ b/server/middlewares/validators/videos/video-live.ts
@@ -2,7 +2,7 @@ import * as express from 'express'
2import { body, param } from 'express-validator' 2import { body, param } from 'express-validator'
3import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos' 3import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos'
4import { VideoLiveModel } from '@server/models/video/video-live' 4import { VideoLiveModel } from '@server/models/video/video-live'
5import { UserRight, VideoState } from '@shared/models' 5import { ServerErrorCode, UserRight, VideoState } from '@shared/models'
6import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc' 6import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
7import { isVideoNameValid } from '../../../helpers/custom-validators/videos' 7import { isVideoNameValid } from '../../../helpers/custom-validators/videos'
8import { cleanUpReqFiles } from '../../../helpers/express-utils' 8import { cleanUpReqFiles } from '../../../helpers/express-utils'
@@ -10,6 +10,7 @@ import { logger } from '../../../helpers/logger'
10import { CONFIG } from '../../../initializers/config' 10import { CONFIG } from '../../../initializers/config'
11import { areValidationErrors } from '../utils' 11import { areValidationErrors } from '../utils'
12import { getCommonVideoEditAttributes } from './videos' 12import { getCommonVideoEditAttributes } from './videos'
13import { VideoModel } from '@server/models/video/video'
13 14
14const videoLiveGetValidator = [ 15const videoLiveGetValidator = [
15 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), 16 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
@@ -50,11 +51,15 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
50 logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body }) 51 logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body })
51 52
52 if (CONFIG.LIVE.ENABLED !== true) { 53 if (CONFIG.LIVE.ENABLED !== true) {
54 cleanUpReqFiles(req)
55
53 return res.status(403) 56 return res.status(403)
54 .json({ error: 'Live is not enabled on this instance' }) 57 .json({ error: 'Live is not enabled on this instance' })
55 } 58 }
56 59
57 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { 60 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) {
61 cleanUpReqFiles(req)
62
58 return res.status(403) 63 return res.status(403)
59 .json({ error: 'Saving live replay is not allowed instance' }) 64 .json({ error: 'Saving live replay is not allowed instance' })
60 } 65 }
@@ -64,6 +69,34 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
64 const user = res.locals.oauth.token.User 69 const user = res.locals.oauth.token.User
65 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) 70 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
66 71
72 if (CONFIG.LIVE.MAX_INSTANCE_LIVES !== -1) {
73 const totalInstanceLives = await VideoModel.countLocalLives()
74
75 if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) {
76 cleanUpReqFiles(req)
77
78 return res.status(403)
79 .json({
80 code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED,
81 error: 'Cannot create this live because the max instance lives limit is reached.'
82 })
83 }
84 }
85
86 if (CONFIG.LIVE.MAX_USER_LIVES !== -1) {
87 const totalUserLives = await VideoModel.countLivesOfAccount(user.Account.id)
88
89 if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) {
90 cleanUpReqFiles(req)
91
92 return res.status(403)
93 .json({
94 code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED,
95 error: 'Cannot create this live because the max user lives limit is reached.'
96 })
97 }
98 }
99
67 return next() 100 return next()
68 } 101 }
69]) 102])
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 78fec5585..d094f19b0 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1142,6 +1142,37 @@ export class VideoModel extends Model<VideoModel> {
1142 return VideoModel.getAvailableForApi(queryOptions) 1142 return VideoModel.getAvailableForApi(queryOptions)
1143 } 1143 }
1144 1144
1145 static countLocalLives () {
1146 const options = {
1147 where: {
1148 remote: false,
1149 isLive: true
1150 }
1151 }
1152
1153 return VideoModel.count(options)
1154 }
1155
1156 static countLivesOfAccount (accountId: number) {
1157 const options = {
1158 where: {
1159 remote: false,
1160 isLive: true
1161 },
1162 include: [
1163 {
1164 required: true,
1165 model: VideoChannelModel.unscoped(),
1166 where: {
1167 accountId
1168 }
1169 }
1170 ]
1171 }
1172
1173 return VideoModel.count(options)
1174 }
1175
1145 static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> { 1176 static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> {
1146 const where = buildWhereIdOrUUID(id) 1177 const where = buildWhereIdOrUUID(id)
1147 const options = { 1178 const options = {
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 2882ceb7c..42ac5e1f9 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -105,6 +105,8 @@ describe('Test config API validators', function () {
105 105
106 allowReplay: false, 106 allowReplay: false,
107 maxDuration: null, 107 maxDuration: null,
108 maxInstanceLives: -1,
109 maxUserLives: 50,
108 110
109 transcoding: { 111 transcoding: {
110 enabled: true, 112 enabled: true,
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index a7f035362..6c37be113 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -81,6 +81,8 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
81 expect(data.live.enabled).to.be.false 81 expect(data.live.enabled).to.be.false
82 expect(data.live.allowReplay).to.be.true 82 expect(data.live.allowReplay).to.be.true
83 expect(data.live.maxDuration).to.equal(1000 * 3600 * 5) 83 expect(data.live.maxDuration).to.equal(1000 * 3600 * 5)
84 expect(data.live.maxInstanceLives).to.equal(20)
85 expect(data.live.maxUserLives).to.equal(3)
84 expect(data.live.transcoding.enabled).to.be.false 86 expect(data.live.transcoding.enabled).to.be.false
85 expect(data.live.transcoding.threads).to.equal(2) 87 expect(data.live.transcoding.threads).to.equal(2)
86 expect(data.live.transcoding.resolutions['240p']).to.be.false 88 expect(data.live.transcoding.resolutions['240p']).to.be.false
@@ -166,6 +168,8 @@ function checkUpdatedConfig (data: CustomConfig) {
166 expect(data.live.enabled).to.be.true 168 expect(data.live.enabled).to.be.true
167 expect(data.live.allowReplay).to.be.false 169 expect(data.live.allowReplay).to.be.false
168 expect(data.live.maxDuration).to.equal(5000) 170 expect(data.live.maxDuration).to.equal(5000)
171 expect(data.live.maxInstanceLives).to.equal(-1)
172 expect(data.live.maxUserLives).to.equal(10)
169 expect(data.live.transcoding.enabled).to.be.true 173 expect(data.live.transcoding.enabled).to.be.true
170 expect(data.live.transcoding.threads).to.equal(4) 174 expect(data.live.transcoding.threads).to.equal(4)
171 expect(data.live.transcoding.resolutions['240p']).to.be.true 175 expect(data.live.transcoding.resolutions['240p']).to.be.true
@@ -330,6 +334,8 @@ describe('Test config', function () {
330 enabled: true, 334 enabled: true,
331 allowReplay: false, 335 allowReplay: false,
332 maxDuration: 5000, 336 maxDuration: 5000,
337 maxInstanceLives: -1,
338 maxUserLives: 10,
333 transcoding: { 339 transcoding: {
334 enabled: true, 340 enabled: true,
335 threads: 4, 341 threads: 4,
diff --git a/shared/extra-utils/server/config.ts b/shared/extra-utils/server/config.ts
index bb7e23d54..7c1ad0a75 100644
--- a/shared/extra-utils/server/config.ts
+++ b/shared/extra-utils/server/config.ts
@@ -130,6 +130,8 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti
130 enabled: true, 130 enabled: true,
131 allowReplay: false, 131 allowReplay: false,
132 maxDuration: null, 132 maxDuration: null,
133 maxInstanceLives: -1,
134 maxUserLives: 50,
133 transcoding: { 135 transcoding: {
134 enabled: true, 136 enabled: true,
135 threads: 4, 137 threads: 4,
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index 11b2ef2eb..67e05e23f 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -99,7 +99,10 @@ export interface CustomConfig {
99 enabled: boolean 99 enabled: boolean
100 100
101 allowReplay: boolean 101 allowReplay: boolean
102
102 maxDuration: number 103 maxDuration: number
104 maxInstanceLives: number
105 maxUserLives: number
103 106
104 transcoding: { 107 transcoding: {
105 enabled: boolean 108 enabled: boolean
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts
index 1563d848e..a01fcbe41 100644
--- a/shared/models/server/server-config.model.ts
+++ b/shared/models/server/server-config.model.ts
@@ -102,6 +102,8 @@ export interface ServerConfig {
102 enabled: boolean 102 enabled: boolean
103 103
104 maxDuration: number 104 maxDuration: number
105 maxInstanceLives: number
106 maxUserLives: number
105 allowReplay: boolean 107 allowReplay: boolean
106 108
107 transcoding: { 109 transcoding: {
diff --git a/shared/models/server/server-error-code.enum.ts b/shared/models/server/server-error-code.enum.ts
index 0bfb2c470..c02b0e6c7 100644
--- a/shared/models/server/server-error-code.enum.ts
+++ b/shared/models/server/server-error-code.enum.ts
@@ -1,3 +1,5 @@
1export const enum ServerErrorCode { 1export const enum ServerErrorCode {
2 DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1 2 DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1,
3 MAX_INSTANCE_LIVES_LIMIT_REACHED = 2,
4 MAX_USER_LIVES_LIMIT_REACHED = 3,
3} 5}