From f443a74649174b2f9347c158e30f8ac7aa3e958a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 4 Mar 2022 13:40:02 +0100 Subject: Add latency setting support --- .../edit-custom-config.component.ts | 3 ++ .../edit-live-configuration.component.html | 12 ++++++++ .../+video-edit/shared/video-edit.component.html | 11 +++++++ .../+video-edit/shared/video-edit.component.ts | 25 +++++++++++++++- .../+videos/+video-edit/video-update.component.ts | 4 ++- .../+videos/+video-watch/video-watch.component.ts | 34 ++++++++++++++++++---- 6 files changed, 81 insertions(+), 8 deletions(-) (limited to 'client/src/app') 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 e3b6f8305..94f1021bf 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 @@ -189,6 +189,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { maxInstanceLives: MAX_INSTANCE_LIVES_VALIDATOR, maxUserLives: MAX_USER_LIVES_VALIDATOR, allowReplay: null, + latencySetting: { + enabled: null + }, transcoding: { enabled: null, diff --git a/client/src/app/+admin/config/edit-custom-config/edit-live-configuration.component.html b/client/src/app/+admin/config/edit-custom-config/edit-live-configuration.component.html index 10d5278c1..8d6a4ce19 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-live-configuration.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-live-configuration.component.html @@ -36,6 +36,18 @@ +
+ + + Small latency disables P2P and high latency can increase P2P ratio + + + +
+
+ +
+ + + +
+ {{ formErrors.latencyMode }} +
+
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts index 2801fc519..a2399eafb 100644 --- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts @@ -1,6 +1,6 @@ import { forkJoin } from 'rxjs' import { map } from 'rxjs/operators' -import { SelectChannelItem } from 'src/types/select-options-item.model' +import { SelectChannelItem, SelectOptionsItem } from 'src/types/select-options-item.model' import { ChangeDetectorRef, Component, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' import { AbstractControl, FormArray, FormControl, FormGroup, Validators } from '@angular/forms' import { HooksService, PluginService, ServerService } from '@app/core' @@ -26,6 +26,7 @@ import { PluginInfo } from '@root-helpers/plugins-manager' import { HTMLServerConfig, LiveVideo, + LiveVideoLatencyMode, RegisterClientFormFieldOptions, RegisterClientVideoFieldOptions, VideoConstant, @@ -78,6 +79,23 @@ export class VideoEditComponent implements OnInit, OnDestroy { videoCategories: VideoConstant[] = [] videoLicences: VideoConstant[] = [] videoLanguages: VideoLanguages[] = [] + latencyModes: SelectOptionsItem[] = [ + { + id: LiveVideoLatencyMode.SMALL_LATENCY, + label: $localize`Small latency`, + description: $localize`Reduce latency to ~15s disabling P2P` + }, + { + id: LiveVideoLatencyMode.DEFAULT, + label: $localize`Default`, + description: $localize`Average latency of 30s` + }, + { + id: LiveVideoLatencyMode.HIGH_LATENCY, + label: $localize`High latency`, + description: $localize`Average latency of 60s increasing P2P ratio` + } + ] pluginDataFormGroup: FormGroup @@ -141,6 +159,7 @@ export class VideoEditComponent implements OnInit, OnDestroy { originallyPublishedAt: VIDEO_ORIGINALLY_PUBLISHED_AT_VALIDATOR, liveStreamKey: null, permanentLive: null, + latencyMode: null, saveReplay: null } @@ -273,6 +292,10 @@ export class VideoEditComponent implements OnInit, OnDestroy { return this.form.value['permanentLive'] === true } + isLatencyModeEnabled () { + return this.serverConfig.live.latencySetting.enabled + } + isPluginFieldHidden (pluginField: PluginField) { if (typeof pluginField.commonOptions.hidden !== 'function') return false diff --git a/client/src/app/+videos/+video-edit/video-update.component.ts b/client/src/app/+videos/+video-edit/video-update.component.ts index d9e8344fc..9c4998f2e 100644 --- a/client/src/app/+videos/+video-edit/video-update.component.ts +++ b/client/src/app/+videos/+video-edit/video-update.component.ts @@ -64,6 +64,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { if (this.liveVideo) { this.form.patchValue({ saveReplay: this.liveVideo.saveReplay, + latencyMode: this.liveVideo.latencyMode, permanentLive: this.liveVideo.permanentLive }) } @@ -127,7 +128,8 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { const liveVideoUpdate: LiveVideoUpdate = { saveReplay: !!this.form.value.saveReplay, - permanentLive: !!this.form.value.permanentLive + permanentLive: !!this.form.value.permanentLive, + latencyMode: this.form.value.latencyMode } // Don't update live attributes if they did not change diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts index 1f45c4d26..067d3bc84 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts @@ -1,5 +1,5 @@ import { Hotkey, HotkeysService } from 'angular2-hotkeys' -import { forkJoin, Subscription } from 'rxjs' +import { forkJoin, map, Observable, of, Subscription, switchMap } from 'rxjs' import { isP2PEnabled } from 'src/assets/player/utils' import { PlatformLocation } from '@angular/common' import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' @@ -22,11 +22,13 @@ import { HooksService } from '@app/core/plugins/hooks.service' import { isXPercentInViewport, scrollToTop } from '@app/helpers' import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' +import { LiveVideoService } from '@app/shared/shared-video-live' import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' import { timeToInt } from '@shared/core-utils' import { HTMLServerConfig, HttpStatusCode, + LiveVideo, PeerTubeProblemDocument, ServerErrorCode, VideoCaption, @@ -63,6 +65,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { video: VideoDetails = null videoCaptions: VideoCaption[] = [] + liveVideo: LiveVideo playlistPosition: number playlist: VideoPlaylist = null @@ -89,6 +92,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { private router: Router, private videoService: VideoService, private playlistService: VideoPlaylistService, + private liveVideoService: LiveVideoService, private confirmService: ConfirmService, private metaService: MetaService, private authService: AuthService, @@ -239,12 +243,21 @@ export class VideoWatchComponent implements OnInit, OnDestroy { 'filter:api.video-watch.video.get.result' ) + const videoAndLiveObs: Observable<{ video: VideoDetails, live?: LiveVideo }> = videoObs.pipe( + switchMap(video => { + if (!video.isLive) return of({ video }) + + return this.liveVideoService.getVideoLive(video.uuid) + .pipe(map(live => ({ live, video }))) + }) + ) + forkJoin([ - videoObs, + videoAndLiveObs, this.videoCaptionService.listCaptions(videoId), this.userService.getAnonymousOrLoggedUser() ]).subscribe({ - next: ([ video, captionsResult, loggedInOrAnonymousUser ]) => { + next: ([ { video, live }, captionsResult, loggedInOrAnonymousUser ]) => { const queryParams = this.route.snapshot.queryParams const urlOptions = { @@ -261,7 +274,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { peertubeLink: false } - this.onVideoFetched({ video, videoCaptions: captionsResult.data, loggedInOrAnonymousUser, urlOptions }) + this.onVideoFetched({ video, live, videoCaptions: captionsResult.data, loggedInOrAnonymousUser, urlOptions }) .catch(err => this.handleGlobalError(err)) }, @@ -330,16 +343,18 @@ export class VideoWatchComponent implements OnInit, OnDestroy { private async onVideoFetched (options: { video: VideoDetails + live: LiveVideo videoCaptions: VideoCaption[] urlOptions: URLOptions loggedInOrAnonymousUser: User }) { - const { video, videoCaptions, urlOptions, loggedInOrAnonymousUser } = options + const { video, live, videoCaptions, urlOptions, loggedInOrAnonymousUser } = options this.subscribeToLiveEventsIfNeeded(this.video, video) this.video = video this.videoCaptions = videoCaptions + this.liveVideo = live // Re init attributes this.playerPlaceholderImgSrc = undefined @@ -387,6 +402,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { const params = { video: this.video, videoCaptions: this.videoCaptions, + liveVideo: this.liveVideo, urlOptions, loggedInOrAnonymousUser, user: this.user @@ -532,12 +548,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy { private buildPlayerManagerOptions (params: { video: VideoDetails + liveVideo: LiveVideo videoCaptions: VideoCaption[] urlOptions: CustomizationOptions & { playerMode: PlayerMode } loggedInOrAnonymousUser: User user?: AuthUser }) { - const { video, videoCaptions, urlOptions, loggedInOrAnonymousUser, user } = params + const { video, liveVideo, videoCaptions, urlOptions, loggedInOrAnonymousUser, user } = params const getStartTime = () => { const byUrl = urlOptions.startTime !== undefined @@ -562,6 +579,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { src: environment.apiUrl + c.captionPath })) + const liveOptions = video.isLive + ? { latencyMode: liveVideo.latencyMode } + : undefined + const options: PeertubePlayerManagerOptions = { common: { autoplay: this.isAutoplay(), @@ -597,6 +618,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { embedTitle: video.name, isLive: video.isLive, + liveOptions, language: this.localeId, -- cgit v1.2.3