From bdb54e6f8c82b1dc95e41a43bf0a8d1082139309 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 22 Feb 2022 11:14:34 +0100 Subject: [PATCH 1/4] Use local URL for feed guid --- server/controllers/feeds.ts | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index 90faaf0248f..c929a6726c0 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts @@ -104,7 +104,7 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res // Adding video items to the feed, one at a time for (const comment of comments) { - const link = WEBSERVER.URL + comment.getCommentStaticPath() + const localLink = WEBSERVER.URL + comment.getCommentStaticPath() let title = comment.Video.name const author: { name: string, link: string }[] = [] @@ -119,8 +119,8 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res feed.addItem({ title, - id: comment.url, - link, + id: localLink, + link: localLink, content: toSafeHtml(comment.text), author, date: comment.createdAt @@ -269,7 +269,7 @@ function addVideosToFeed (feed: Feed, videos: VideoModel[]) { size_in_bytes: videoFile.size })) - const videos = formattedVideoFiles.map(videoFile => { + const videoFiles = formattedVideoFiles.map(videoFile => { const result = { type: MIMETYPES.VIDEO.EXT_MIMETYPE[extname(videoFile.fileUrl)], medium: 'video', @@ -293,10 +293,12 @@ function addVideosToFeed (feed: Feed, videos: VideoModel[]) { }) } + const localLink = WEBSERVER.URL + video.getWatchStaticPath() + feed.addItem({ title: video.name, - id: video.url, - link: WEBSERVER.URL + video.getWatchStaticPath(), + id: localLink, + link: localLink, description: mdToOneLinePlainText(video.getTruncatedDescription()), content: toSafeHtml(video.description), author: [ @@ -311,20 +313,20 @@ function addVideosToFeed (feed: Feed, videos: VideoModel[]) { // Enclosure video: { - url: videos[0].url, - length: videos[0].fileSize, - type: videos[0].type + url: videoFiles[0].url, + length: videoFiles[0].fileSize, + type: videoFiles[0].type }, // Media RSS - videos, + videos: videoFiles, embed: { - url: video.getEmbedStaticPath(), + url: WEBSERVER.URL + video.getEmbedStaticPath(), allowFullscreen: true }, player: { - url: video.getWatchStaticPath() + url: WEBSERVER.URL + video.getWatchStaticPath() }, categories, community: { From 4edee628a0a154360b30eab48924b3987ac90798 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 22 Feb 2022 11:25:03 +0100 Subject: [PATCH 2/4] Improve account removal message for users --- .../my-account-danger-zone.component.ts | 9 +++++++-- client/src/app/modal/confirm.component.ts | 10 ++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts index 4a46f1ad907..2bae3499e75 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts @@ -19,8 +19,13 @@ export class MyAccountDangerZoneComponent { async deleteMe () { const res = await this.confirmService.confirmWithInput( - // eslint-disable-next-line max-len - $localize`Are you sure you want to delete your account? This will delete all your data, including channels, videos and comments. Content cached by other servers and other third-parties might make longer to be deleted.`, + $localize`Are you sure you want to delete your account?` + + '

' + + // eslint-disable-next-line max-len + $localize`This will delete all your data, including channels, videos, comments and you won't be able to create another user on this instance with "${this.user.username}" username.` + + '

' + + $localize`Content cached by other servers and other third-parties might make longer to be deleted.`, + $localize`Type your username to confirm`, this.user.username, $localize`Delete your account`, diff --git a/client/src/app/modal/confirm.component.ts b/client/src/app/modal/confirm.component.ts index 457dd1f3f5e..ec4e1d60fbf 100644 --- a/client/src/app/modal/confirm.component.ts +++ b/client/src/app/modal/confirm.component.ts @@ -1,4 +1,5 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' +import { HtmlRendererService } from '@app/core' import { ConfirmService } from '@app/core/confirm/confirm.service' import { POP_STATE_MODAL_DISMISS } from '@app/helpers' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' @@ -24,6 +25,7 @@ export class ConfirmComponent implements OnInit { constructor ( private modalService: NgbModal, + private html: HtmlRendererService, private confirmService: ConfirmService ) { } @@ -31,14 +33,18 @@ export class ConfirmComponent implements OnInit { this.confirmService.showConfirm.subscribe( ({ title, message, expectedInputValue, inputLabel, confirmButtonText }) => { this.title = title - this.message = message this.inputLabel = inputLabel this.expectedInputValue = expectedInputValue this.confirmButtonText = confirmButtonText || $localize`Confirm` - this.showModal() + this.html.toSafeHtml(message) + .then(message => { + this.message = message + + this.showModal() + }) } ) } From 89e3de8dc6dbe3c78aefb5f43e0feffd97b1af02 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 22 Feb 2022 11:41:44 +0100 Subject: [PATCH 3/4] Reduce latency when adding a video to playlist --- .../video-add-to-playlist.component.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts index 55393059563..e4972ec10ab 100644 --- a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts +++ b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts @@ -56,6 +56,8 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, private listenToPlaylistChangeSub: Subscription private playlistsData: CachedPlaylist[] = [] + private pendingAddId: number + constructor ( protected formValidatorService: FormValidatorService, private authService: AuthService, @@ -215,8 +217,9 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, } isPrimaryCheckboxChecked (playlist: PlaylistSummary) { - return playlist.elements.filter(e => e.enabled) - .length !== 0 + // Reduce latency when adding a video to a playlist using pendingAddId + return this.pendingAddId === playlist.id || + playlist.elements.filter(e => e.enabled).length !== 0 } toggleOptionalRow (playlist: PlaylistSummary) { @@ -367,6 +370,8 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, if (element.startTimestamp) body.startTimestamp = element.startTimestamp if (element.stopTimestamp && element.stopTimestamp !== this.video.duration) body.stopTimestamp = element.stopTimestamp + this.pendingAddId = playlist.id + this.videoPlaylistService.addVideoInPlaylist(playlist.id, body) .subscribe({ next: res => { @@ -379,9 +384,17 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, if (element) element.playlistElementId = res.videoPlaylistElement.id }, - error: err => this.notifier.error(err.message), + error: err => { + this.pendingAddId = undefined + this.cd.markForCheck() + + this.notifier.error(err.message) + }, - complete: () => this.cd.markForCheck() + complete: () => { + this.pendingAddId = undefined + this.cd.markForCheck() + } }) } From ac5f679ad60fc48db6d9a9534a8ac5fd20eda36f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 22 Feb 2022 13:44:12 +0100 Subject: [PATCH 4/4] Fix HLS buffer --- .../p2p-media-loader/segment-url-builder.ts | 4 +- .../player/peertube-player-options-builder.ts | 61 +++++++++++++------ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/client/src/assets/player/p2p-media-loader/segment-url-builder.ts b/client/src/assets/player/p2p-media-loader/segment-url-builder.ts index 5ddc81ff6d5..9d324078a51 100644 --- a/client/src/assets/player/p2p-media-loader/segment-url-builder.ts +++ b/client/src/assets/player/p2p-media-loader/segment-url-builder.ts @@ -1,10 +1,10 @@ import { Segment } from '@peertube/p2p-media-loader-core' import { RedundancyUrlManager } from './redundancy-url-manager' -function segmentUrlBuilderFactory (redundancyUrlManager: RedundancyUrlManager, requiredSegmentsPriority: number) { +function segmentUrlBuilderFactory (redundancyUrlManager: RedundancyUrlManager, useOriginPriority: number) { return function segmentBuilder (segment: Segment) { // Don't use redundancy for high priority segments - if (segment.priority <= requiredSegmentsPriority) return segment.url + if (segment.priority <= useOriginPriority) return segment.url return redundancyUrlManager.buildUrl(segment.url) } diff --git a/client/src/assets/player/peertube-player-options-builder.ts b/client/src/assets/player/peertube-player-options-builder.ts index 901f6cd3bbc..71be5ccff34 100644 --- a/client/src/assets/player/peertube-player-options-builder.ts +++ b/client/src/assets/player/peertube-player-options-builder.ts @@ -19,6 +19,7 @@ import { VideoJSPluginOptions } from './peertube-videojs-typings' import { buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils' +import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core' export type PlayerMode = 'webtorrent' | 'p2p-media-loader' @@ -198,9 +199,6 @@ export class PeertubePlayerOptionsBuilder { const p2pMediaLoaderOptions = this.options.p2pMediaLoader const commonOptions = this.options.common - const trackerAnnounce = p2pMediaLoaderOptions.trackerAnnounce - .filter(t => t.startsWith('ws')) - const redundancyUrlManager = new RedundancyUrlManager(this.options.p2pMediaLoader.redundancyBaseUrls) const p2pMediaLoader: P2PMediaLoaderPluginOptions = { @@ -210,23 +208,8 @@ export class PeertubePlayerOptionsBuilder { src: p2pMediaLoaderOptions.playlistUrl } - let consumeOnly = false - if ((navigator as any)?.connection?.type === 'cellular') { - console.log('We are on a cellular connection: disabling seeding.') - consumeOnly = true - } - const p2pMediaLoaderConfig: HlsJsEngineSettings = { - loader: { - trackerAnnounce, - segmentValidator: segmentValidatorFactory(this.options.p2pMediaLoader.segmentsSha256Url, this.options.common.isLive), - rtcConfig: getRtcConfig(), - requiredSegmentsPriority: 1, - simultaneousHttpDownloads: 1, - segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager, 1), - useP2P: commonOptions.p2pEnabled, - consumeOnly - }, + loader: this.getP2PMediaLoaderOptions(redundancyUrlManager), segments: { swarmId: p2pMediaLoaderOptions.playlistUrl } @@ -256,6 +239,46 @@ export class PeertubePlayerOptionsBuilder { return toAssign } + private getP2PMediaLoaderOptions (redundancyUrlManager: RedundancyUrlManager): Partial { + let consumeOnly = false + if ((navigator as any)?.connection?.type === 'cellular') { + console.log('We are on a cellular connection: disabling seeding.') + consumeOnly = true + } + + const trackerAnnounce = this.options.p2pMediaLoader.trackerAnnounce + .filter(t => t.startsWith('ws')) + + const specificLiveOrVODOptions = this.options.common.isLive + ? { // Live + requiredSegmentsPriority: 1 + } + : { // VOD + requiredSegmentsPriority: 3, + + cachedSegmentExpiration: 86400000, + cachedSegmentsCount: 100, + + httpDownloadMaxPriority: 9, + httpDownloadProbability: 0.06, + httpDownloadProbabilitySkipIfNoPeers: true, + + p2pDownloadMaxPriority: 50 + } + + return { + trackerAnnounce, + segmentValidator: segmentValidatorFactory(this.options.p2pMediaLoader.segmentsSha256Url, this.options.common.isLive), + rtcConfig: getRtcConfig(), + simultaneousHttpDownloads: 1, + segmentUrlBuilder: segmentUrlBuilderFactory(redundancyUrlManager, 1), + useP2P: this.options.common.p2pEnabled, + consumeOnly, + + ...specificLiveOrVODOptions + } + } + private getHLSOptions (p2pMediaLoaderConfig: HlsJsEngineSettings) { const base = { capLevelToPlayerSize: true,