1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 01:39:37 +02:00
Peertube/client/src/app/shared/shared-admin/admin-config.service.ts
2025-06-18 06:40:19 +02:00

215 lines
6.3 KiB
TypeScript

import { HttpClient } from '@angular/common/http'
import { Injectable, inject } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { Notifier, RestExtractor, ServerService } from '@app/core'
import { formatICU } from '@app/helpers'
import { BuildFormValidator } from '@app/shared/form-validators/form-validator.model'
import { CustomConfig } from '@peertube/peertube-models'
import { DeepPartial } from '@peertube/peertube-typescript-utils'
import merge from 'lodash-es/merge'
import { catchError, map, switchMap } from 'rxjs/operators'
import { environment } from '../../../environments/environment'
import { SelectOptionsItem } from '../../../types/select-options-item.model'
export type FormResolutions = {
'0p': FormControl<boolean>
'144p': FormControl<boolean>
'240p': FormControl<boolean>
'360p': FormControl<boolean>
'480p': FormControl<boolean>
'720p': FormControl<boolean>
'1080p': FormControl<boolean>
'1440p': FormControl<boolean>
'2160p': FormControl<boolean>
}
export type ResolutionOption = { id: keyof FormResolutions, label: string, description?: string }
@Injectable()
export class AdminConfigService {
private authHttp = inject(HttpClient)
private restExtractor = inject(RestExtractor)
private notifier = inject(Notifier)
private serverService = inject(ServerService)
private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/config'
transcodingThreadOptions: SelectOptionsItem[] = []
transcodingResolutionOptions: ResolutionOption[] = []
constructor () {
this.transcodingThreadOptions = [
{ id: 0, label: $localize`Auto (via ffmpeg)` },
{ id: 1, label: '1' },
{ id: 2, label: '2' },
{ id: 4, label: '4' },
{ id: 8, label: '8' },
{ id: 12, label: '12' },
{ id: 16, label: '16' },
{ id: 32, label: '32' }
]
this.transcodingResolutionOptions = [
{
id: '0p',
label: $localize`Audio-only`,
description:
$localize`"Split audio and video" must be enabled for the PeerTube player to propose an "Audio only" resolution to users`
},
{
id: '144p',
label: $localize`144p`
},
{
id: '240p',
label: $localize`240p`
},
{
id: '360p',
label: $localize`360p`
},
{
id: '480p',
label: $localize`480p`
},
{
id: '720p',
label: $localize`720p`
},
{
id: '1080p',
label: $localize`1080p`
},
{
id: '1440p',
label: $localize`1440p`
},
{
id: '2160p',
label: $localize`2160p`
}
]
}
// ---------------------------------------------------------------------------
getCustomConfig () {
return this.authHttp.get<CustomConfig>(AdminConfigService.BASE_APPLICATION_URL + '/custom')
.pipe(catchError(res => this.restExtractor.handleError(res)))
}
updateCustomConfig (partialConfig: DeepPartial<CustomConfig>) {
return this.getCustomConfig()
.pipe(
switchMap(customConfig => {
const newConfig = merge(customConfig, partialConfig)
return this.authHttp.put<CustomConfig>(AdminConfigService.BASE_APPLICATION_URL + '/custom', newConfig)
.pipe(map(() => newConfig))
}),
catchError(res => this.restExtractor.handleError(res))
)
}
getCustomConfigReloadedObs () {
return this.serverService.configReloaded
.pipe(switchMap(() => this.getCustomConfig()))
}
saveAndUpdateCurrent (options: {
currentConfig: CustomConfig
form: FormGroup
formConfig: DeepPartial<CustomConfig>
success: string
}) {
const { currentConfig, form, formConfig, success } = options
this.updateCustomConfig(formConfig)
.pipe(switchMap(() => this.serverService.resetConfig()))
.subscribe({
next: newConfig => {
Object.assign(currentConfig, newConfig)
form.markAsPristine()
this.notifier.success(success)
},
error: err => this.notifier.error(err.message)
})
}
// ---------------------------------------------------------------------------
buildFormResolutions () {
const formResolutions = {} as Record<keyof FormResolutions, BuildFormValidator>
for (const resolution of this.transcodingResolutionOptions) {
formResolutions[resolution.id] = null
}
return formResolutions
}
buildTranscodingProfiles (profiles: string[]) {
return profiles.map(p => {
if (p === 'default') {
return { id: p, label: $localize`Default`, description: $localize`x264, targeting maximum device compatibility` }
}
return { id: p, label: p }
})
}
getTotalTranscodingThreads (options: {
transcoding: {
enabled: boolean
threads: number
}
live: {
transcoding: {
enabled: boolean
threads: number
}
}
}) {
const transcodingEnabled = options.transcoding.enabled
const transcodingThreads = options.transcoding.threads
const liveTranscodingEnabled = options.live.transcoding.enabled
const liveTranscodingThreads = options.live.transcoding.threads
// checks whether all enabled method are on fixed values and not on auto (= 0)
let noneOnAuto = !transcodingEnabled || +transcodingThreads > 0
noneOnAuto &&= !liveTranscodingEnabled || +liveTranscodingThreads > 0
// count total of fixed value, repalcing auto by a single thread (knowing it will display "at least")
let value = 0
if (transcodingEnabled) value += +transcodingThreads || 1
if (liveTranscodingEnabled) value += +liveTranscodingThreads || 1
return {
value,
atMost: noneOnAuto, // auto switches everything to a least estimation since ffmpeg will take as many threads as possible
unit: formatICU($localize`{value, plural, =1 {thread} other {threads}}`, { value })
}
}
checkTranscodingConsistentOptions (options: {
transcoding: {
enabled: boolean
}
live: {
enabled: boolean
allowReplay: boolean
}
}) {
if (
options.transcoding.enabled === false &&
options.live.enabled === true && options.live.allowReplay === true
) {
return $localize`You cannot allow live replay if you don't enable transcoding.`
}
return undefined
}
}