Add max lives limit
This commit is contained in:
parent
d846d99c6c
commit
a056ca4813
|
@ -739,6 +739,16 @@
|
||||||
</my-peertube-checkbox>
|
</my-peertube-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
|
||||||
|
<label i18n for="liveMaxInstanceLives">Max lives created on your instance (-1 for "unlimited")</label>
|
||||||
|
<input type="number" name="liveMaxInstanceLives" formControlName="maxInstanceLives" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
|
||||||
|
<label i18n for="liveMaxUserLives">Max lives created per user (-1 for "unlimited")</label>
|
||||||
|
<input type="number" name="liveMaxUserLives" formControlName="maxUserLives" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
|
<div class="form-group" [ngClass]="{ 'disabled-checkbox-extra': !isLiveEnabled() }">
|
||||||
<label i18n for="liveMaxDuration">Max live duration</label>
|
<label i18n for="liveMaxDuration">Max live duration</label>
|
||||||
<div class="peertube-select-container">
|
<div class="peertube-select-container">
|
||||||
|
|
|
@ -216,6 +216,8 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit, A
|
||||||
enabled: null,
|
enabled: null,
|
||||||
|
|
||||||
maxDuration: null,
|
maxDuration: null,
|
||||||
|
maxInstanceLives: null,
|
||||||
|
maxUserLives: null,
|
||||||
allowReplay: null,
|
allowReplay: null,
|
||||||
|
|
||||||
transcoding: {
|
transcoding: {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { scrollToTop } from '@app/helpers'
|
||||||
import { FormValidatorService } from '@app/shared/shared-forms'
|
import { FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
|
import { LiveVideoService, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main'
|
||||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoPrivacy } from '@shared/models'
|
import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, ServerErrorCode, VideoPrivacy } from '@shared/models'
|
||||||
import { VideoSend } from './video-send'
|
import { VideoSend } from './video-send'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -81,7 +81,16 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, CanCompon
|
||||||
|
|
||||||
err => {
|
err => {
|
||||||
this.firstStepError.emit()
|
this.firstStepError.emit()
|
||||||
this.notifier.error(err.message)
|
|
||||||
|
let message = err.message
|
||||||
|
|
||||||
|
if (err.body?.code === ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED) {
|
||||||
|
message = $localize`Cannot create live because this instance have too many created lives`
|
||||||
|
} else if (err.body?.code) {
|
||||||
|
message = $localize`Cannot create live because you created too many lives`
|
||||||
|
}
|
||||||
|
|
||||||
|
this.notifier.error(message)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,8 @@ export class ServerService {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
allowReplay: true,
|
allowReplay: true,
|
||||||
maxDuration: null,
|
maxDuration: null,
|
||||||
|
maxInstanceLives: -1,
|
||||||
|
maxUserLives: -1,
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
enabledResolutions: []
|
enabledResolutions: []
|
||||||
|
|
|
@ -81,6 +81,13 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th i18n class="sub-label" scope="row">Max parallel lives</th>
|
||||||
|
<td i18n>
|
||||||
|
{{ maxUserLives }} per user / {{ maxInstanceLives }} per instance
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th i18n class="label" colspan="2">Import</th>
|
<th i18n class="label" colspan="2">Import</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -21,6 +21,20 @@ export class InstanceFeaturesTableComponent implements OnInit {
|
||||||
return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily)
|
return Math.min(this.initialUserVideoQuota, this.serverConfig.user.videoQuotaDaily)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get maxInstanceLives () {
|
||||||
|
const value = this.serverConfig.live.maxInstanceLives
|
||||||
|
if (value === -1) return $localize`Unlimited`
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
get maxUserLives () {
|
||||||
|
const value = this.serverConfig.live.maxUserLives
|
||||||
|
if (value === -1) return $localize`Unlimited`
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this.serverConfig = this.serverService.getTmpConfig()
|
this.serverConfig = this.serverService.getTmpConfig()
|
||||||
this.serverService.getConfig()
|
this.serverService.getConfig()
|
||||||
|
|
|
@ -250,6 +250,14 @@ live:
|
||||||
# Set null to disable duration limit
|
# Set null to disable duration limit
|
||||||
max_duration: 5 hours
|
max_duration: 5 hours
|
||||||
|
|
||||||
|
# Limit max number of live videos created on your instance
|
||||||
|
# -1 == unlimited
|
||||||
|
max_instance_lives: 20
|
||||||
|
|
||||||
|
# Limit max number of live videos created by a user on your instance
|
||||||
|
# -1 == unlimited
|
||||||
|
max_user_lives: 3
|
||||||
|
|
||||||
# Allow your users to save a replay of their live
|
# Allow your users to save a replay of their live
|
||||||
# PeerTube will transcode segments in a video file
|
# PeerTube will transcode segments in a video file
|
||||||
# If the user daily/total quota is reached, PeerTube will stop the live
|
# If the user daily/total quota is reached, PeerTube will stop the live
|
||||||
|
|
|
@ -120,6 +120,8 @@ async function getConfig (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
|
allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
|
||||||
maxDuration: CONFIG.LIVE.MAX_DURATION,
|
maxDuration: CONFIG.LIVE.MAX_DURATION,
|
||||||
|
maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES,
|
||||||
|
maxUserLives: CONFIG.LIVE.MAX_USER_LIVES,
|
||||||
|
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
|
enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
|
||||||
|
@ -430,6 +432,8 @@ function customConfig (): CustomConfig {
|
||||||
enabled: CONFIG.LIVE.ENABLED,
|
enabled: CONFIG.LIVE.ENABLED,
|
||||||
allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
|
allowReplay: CONFIG.LIVE.ALLOW_REPLAY,
|
||||||
maxDuration: CONFIG.LIVE.MAX_DURATION,
|
maxDuration: CONFIG.LIVE.MAX_DURATION,
|
||||||
|
maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES,
|
||||||
|
maxUserLives: CONFIG.LIVE.MAX_USER_LIVES,
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
|
enabled: CONFIG.LIVE.TRANSCODING.ENABLED,
|
||||||
threads: CONFIG.LIVE.TRANSCODING.THREADS,
|
threads: CONFIG.LIVE.TRANSCODING.THREADS,
|
||||||
|
|
|
@ -38,7 +38,7 @@ function checkMissedConfig () {
|
||||||
'federation.videos.federate_unlisted',
|
'federation.videos.federate_unlisted',
|
||||||
'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url',
|
'search.remote_uri.users', 'search.remote_uri.anonymous', 'search.search_index.enabled', 'search.search_index.url',
|
||||||
'search.search_index.disable_local_search', 'search.search_index.is_default_search',
|
'search.search_index.disable_local_search', 'search.search_index.is_default_search',
|
||||||
'live.enabled', 'live.allow_replay', 'live.max_duration',
|
'live.enabled', 'live.allow_replay', 'live.max_duration', 'live.max_user_lives', 'live.max_instance_lives',
|
||||||
'live.transcoding.enabled', 'live.transcoding.threads',
|
'live.transcoding.enabled', 'live.transcoding.threads',
|
||||||
'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p',
|
'live.transcoding.resolutions.240p', 'live.transcoding.resolutions.360p', 'live.transcoding.resolutions.480p',
|
||||||
'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p'
|
'live.transcoding.resolutions.720p', 'live.transcoding.resolutions.1080p', 'live.transcoding.resolutions.2160p'
|
||||||
|
|
|
@ -202,6 +202,9 @@ const CONFIG = {
|
||||||
get ENABLED () { return config.get<boolean>('live.enabled') },
|
get ENABLED () { return config.get<boolean>('live.enabled') },
|
||||||
|
|
||||||
get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) },
|
get MAX_DURATION () { return parseDurationToMs(config.get<string>('live.max_duration')) },
|
||||||
|
get MAX_INSTANCE_LIVES () { return config.get<number>('live.max_instance_lives') },
|
||||||
|
get MAX_USER_LIVES () { return config.get<number>('live.max_user_lives') },
|
||||||
|
|
||||||
get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') },
|
get ALLOW_REPLAY () { return config.get<boolean>('live.allow_replay') },
|
||||||
|
|
||||||
RTMP: {
|
RTMP: {
|
||||||
|
|
|
@ -65,6 +65,8 @@ const customConfigUpdateValidator = [
|
||||||
body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'),
|
body('live.enabled').isBoolean().withMessage('Should have a valid live enabled boolean'),
|
||||||
body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'),
|
body('live.allowReplay').isBoolean().withMessage('Should have a valid live allow replay boolean'),
|
||||||
body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'),
|
body('live.maxDuration').custom(isIntOrNull).withMessage('Should have a valid live max duration'),
|
||||||
|
body('live.maxInstanceLives').custom(isIntOrNull).withMessage('Should have a valid max instance lives'),
|
||||||
|
body('live.maxUserLives').custom(isIntOrNull).withMessage('Should have a valid max user lives'),
|
||||||
body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'),
|
body('live.transcoding.enabled').isBoolean().withMessage('Should have a valid live transcoding enabled boolean'),
|
||||||
body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'),
|
body('live.transcoding.threads').isInt().withMessage('Should have a valid live transcoding threads'),
|
||||||
body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
|
body('live.transcoding.resolutions.240p').isBoolean().withMessage('Should have a valid transcoding 240p resolution enabled boolean'),
|
||||||
|
|
|
@ -2,7 +2,7 @@ import * as express from 'express'
|
||||||
import { body, param } from 'express-validator'
|
import { body, param } from 'express-validator'
|
||||||
import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos'
|
import { checkUserCanManageVideo, doesVideoChannelOfAccountExist, doesVideoExist } from '@server/helpers/middlewares/videos'
|
||||||
import { VideoLiveModel } from '@server/models/video/video-live'
|
import { VideoLiveModel } from '@server/models/video/video-live'
|
||||||
import { UserRight, VideoState } from '@shared/models'
|
import { ServerErrorCode, UserRight, VideoState } from '@shared/models'
|
||||||
import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
|
import { isBooleanValid, isIdOrUUIDValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
|
||||||
import { isVideoNameValid } from '../../../helpers/custom-validators/videos'
|
import { isVideoNameValid } from '../../../helpers/custom-validators/videos'
|
||||||
import { cleanUpReqFiles } from '../../../helpers/express-utils'
|
import { cleanUpReqFiles } from '../../../helpers/express-utils'
|
||||||
|
@ -10,6 +10,7 @@ import { logger } from '../../../helpers/logger'
|
||||||
import { CONFIG } from '../../../initializers/config'
|
import { CONFIG } from '../../../initializers/config'
|
||||||
import { areValidationErrors } from '../utils'
|
import { areValidationErrors } from '../utils'
|
||||||
import { getCommonVideoEditAttributes } from './videos'
|
import { getCommonVideoEditAttributes } from './videos'
|
||||||
|
import { VideoModel } from '@server/models/video/video'
|
||||||
|
|
||||||
const videoLiveGetValidator = [
|
const videoLiveGetValidator = [
|
||||||
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
|
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
|
||||||
|
@ -50,11 +51,15 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
|
||||||
logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body })
|
logger.debug('Checking videoLiveAddValidator parameters', { parameters: req.body })
|
||||||
|
|
||||||
if (CONFIG.LIVE.ENABLED !== true) {
|
if (CONFIG.LIVE.ENABLED !== true) {
|
||||||
|
cleanUpReqFiles(req)
|
||||||
|
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Live is not enabled on this instance' })
|
.json({ error: 'Live is not enabled on this instance' })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) {
|
if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) {
|
||||||
|
cleanUpReqFiles(req)
|
||||||
|
|
||||||
return res.status(403)
|
return res.status(403)
|
||||||
.json({ error: 'Saving live replay is not allowed instance' })
|
.json({ error: 'Saving live replay is not allowed instance' })
|
||||||
}
|
}
|
||||||
|
@ -64,6 +69,34 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
|
||||||
const user = res.locals.oauth.token.User
|
const user = res.locals.oauth.token.User
|
||||||
if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
|
if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
|
||||||
|
|
||||||
|
if (CONFIG.LIVE.MAX_INSTANCE_LIVES !== -1) {
|
||||||
|
const totalInstanceLives = await VideoModel.countLocalLives()
|
||||||
|
|
||||||
|
if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) {
|
||||||
|
cleanUpReqFiles(req)
|
||||||
|
|
||||||
|
return res.status(403)
|
||||||
|
.json({
|
||||||
|
code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED,
|
||||||
|
error: 'Cannot create this live because the max instance lives limit is reached.'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG.LIVE.MAX_USER_LIVES !== -1) {
|
||||||
|
const totalUserLives = await VideoModel.countLivesOfAccount(user.Account.id)
|
||||||
|
|
||||||
|
if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) {
|
||||||
|
cleanUpReqFiles(req)
|
||||||
|
|
||||||
|
return res.status(403)
|
||||||
|
.json({
|
||||||
|
code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED,
|
||||||
|
error: 'Cannot create this live because the max user lives limit is reached.'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
|
@ -1142,6 +1142,37 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
return VideoModel.getAvailableForApi(queryOptions)
|
return VideoModel.getAvailableForApi(queryOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static countLocalLives () {
|
||||||
|
const options = {
|
||||||
|
where: {
|
||||||
|
remote: false,
|
||||||
|
isLive: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoModel.count(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
static countLivesOfAccount (accountId: number) {
|
||||||
|
const options = {
|
||||||
|
where: {
|
||||||
|
remote: false,
|
||||||
|
isLive: true
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
model: VideoChannelModel.unscoped(),
|
||||||
|
where: {
|
||||||
|
accountId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return VideoModel.count(options)
|
||||||
|
}
|
||||||
|
|
||||||
static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> {
|
static load (id: number | string, t?: Transaction): Bluebird<MVideoThumbnail> {
|
||||||
const where = buildWhereIdOrUUID(id)
|
const where = buildWhereIdOrUUID(id)
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
@ -105,6 +105,8 @@ describe('Test config API validators', function () {
|
||||||
|
|
||||||
allowReplay: false,
|
allowReplay: false,
|
||||||
maxDuration: null,
|
maxDuration: null,
|
||||||
|
maxInstanceLives: -1,
|
||||||
|
maxUserLives: 50,
|
||||||
|
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
|
@ -81,6 +81,8 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
|
||||||
expect(data.live.enabled).to.be.false
|
expect(data.live.enabled).to.be.false
|
||||||
expect(data.live.allowReplay).to.be.true
|
expect(data.live.allowReplay).to.be.true
|
||||||
expect(data.live.maxDuration).to.equal(1000 * 3600 * 5)
|
expect(data.live.maxDuration).to.equal(1000 * 3600 * 5)
|
||||||
|
expect(data.live.maxInstanceLives).to.equal(20)
|
||||||
|
expect(data.live.maxUserLives).to.equal(3)
|
||||||
expect(data.live.transcoding.enabled).to.be.false
|
expect(data.live.transcoding.enabled).to.be.false
|
||||||
expect(data.live.transcoding.threads).to.equal(2)
|
expect(data.live.transcoding.threads).to.equal(2)
|
||||||
expect(data.live.transcoding.resolutions['240p']).to.be.false
|
expect(data.live.transcoding.resolutions['240p']).to.be.false
|
||||||
|
@ -166,6 +168,8 @@ function checkUpdatedConfig (data: CustomConfig) {
|
||||||
expect(data.live.enabled).to.be.true
|
expect(data.live.enabled).to.be.true
|
||||||
expect(data.live.allowReplay).to.be.false
|
expect(data.live.allowReplay).to.be.false
|
||||||
expect(data.live.maxDuration).to.equal(5000)
|
expect(data.live.maxDuration).to.equal(5000)
|
||||||
|
expect(data.live.maxInstanceLives).to.equal(-1)
|
||||||
|
expect(data.live.maxUserLives).to.equal(10)
|
||||||
expect(data.live.transcoding.enabled).to.be.true
|
expect(data.live.transcoding.enabled).to.be.true
|
||||||
expect(data.live.transcoding.threads).to.equal(4)
|
expect(data.live.transcoding.threads).to.equal(4)
|
||||||
expect(data.live.transcoding.resolutions['240p']).to.be.true
|
expect(data.live.transcoding.resolutions['240p']).to.be.true
|
||||||
|
@ -330,6 +334,8 @@ describe('Test config', function () {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
allowReplay: false,
|
allowReplay: false,
|
||||||
maxDuration: 5000,
|
maxDuration: 5000,
|
||||||
|
maxInstanceLives: -1,
|
||||||
|
maxUserLives: 10,
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
threads: 4,
|
threads: 4,
|
||||||
|
|
|
@ -130,6 +130,8 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti
|
||||||
enabled: true,
|
enabled: true,
|
||||||
allowReplay: false,
|
allowReplay: false,
|
||||||
maxDuration: null,
|
maxDuration: null,
|
||||||
|
maxInstanceLives: -1,
|
||||||
|
maxUserLives: 50,
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
threads: 4,
|
threads: 4,
|
||||||
|
|
|
@ -99,7 +99,10 @@ export interface CustomConfig {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
|
|
||||||
allowReplay: boolean
|
allowReplay: boolean
|
||||||
|
|
||||||
maxDuration: number
|
maxDuration: number
|
||||||
|
maxInstanceLives: number
|
||||||
|
maxUserLives: number
|
||||||
|
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
|
|
|
@ -102,6 +102,8 @@ export interface ServerConfig {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
|
|
||||||
maxDuration: number
|
maxDuration: number
|
||||||
|
maxInstanceLives: number
|
||||||
|
maxUserLives: number
|
||||||
allowReplay: boolean
|
allowReplay: boolean
|
||||||
|
|
||||||
transcoding: {
|
transcoding: {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export const enum ServerErrorCode {
|
export const enum ServerErrorCode {
|
||||||
DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1
|
DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1,
|
||||||
|
MAX_INSTANCE_LIVES_LIMIT_REACHED = 2,
|
||||||
|
MAX_USER_LIVES_LIMIT_REACHED = 3,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user