From ad5db1044c8599eaaaa2a578b350777ae996b068 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 18 Nov 2021 14:35:08 +0100 Subject: Add ability to run transcoding jobs --- .../overview/videos/video-list.component.html | 4 +-- .../+admin/overview/videos/video-list.component.ts | 32 ++++++++++++++++-- .../app/shared/shared-main/video/video.model.ts | 12 +++++++ .../app/shared/shared-main/video/video.service.ts | 12 +++++++ .../video-actions-dropdown.component.ts | 38 ++++++++++++++++++++-- 5 files changed, 90 insertions(+), 8 deletions(-) (limited to 'client/src') diff --git a/client/src/app/+admin/overview/videos/video-list.component.html b/client/src/app/+admin/overview/videos/video-list.component.html index 6e4fb4c6f..738bcedee 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.html +++ b/client/src/app/+admin/overview/videos/video-list.component.html @@ -56,8 +56,8 @@ diff --git a/client/src/app/+admin/overview/videos/video-list.component.ts b/client/src/app/+admin/overview/videos/video-list.component.ts index 3c21adb44..4aed5221b 100644 --- a/client/src/app/+admin/overview/videos/video-list.component.ts +++ b/client/src/app/+admin/overview/videos/video-list.component.ts @@ -40,7 +40,8 @@ export class VideoListComponent extends RestTable implements OnInit { duplicate: true, mute: true, liveInfo: false, - removeFiles: true + removeFiles: true, + transcoding: true } loading = true @@ -89,16 +90,28 @@ export class VideoListComponent extends RestTable implements OnInit { } ], [ + { + label: $localize`Run HLS transcoding`, + handler: videos => this.runTranscoding(videos, 'hls'), + isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)), + iconName: 'cog' + }, + { + label: $localize`Run WebTorrent transcoding`, + handler: videos => this.runTranscoding(videos, 'webtorrent'), + isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)), + iconName: 'cog' + }, { label: $localize`Delete HLS files`, handler: videos => this.removeVideoFiles(videos, 'hls'), - isDisplayed: videos => this.authUser.hasRight(UserRight.MANAGE_VIDEO_FILES) && videos.every(v => v.hasHLS() && v.hasWebTorrent()), + isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)), iconName: 'delete' }, { label: $localize`Delete WebTorrent files`, handler: videos => this.removeVideoFiles(videos, 'webtorrent'), - isDisplayed: videos => this.authUser.hasRight(UserRight.MANAGE_VIDEO_FILES) && videos.every(v => v.hasHLS() && v.hasWebTorrent()), + isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)), iconName: 'delete' } ] @@ -226,4 +239,17 @@ export class VideoListComponent extends RestTable implements OnInit { error: err => this.notifier.error(err.message) }) } + + private runTranscoding (videos: Video[], type: 'hls' | 'webtorrent') { + this.videoService.runTranscoding(videos.map(v => v.id), type) + .subscribe({ + next: () => { + this.notifier.success($localize`Transcoding jobs created.`) + + this.reloadData() + }, + + error: err => this.notifier.error(err.message) + }) + } } diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts index 4203ff1c0..eefa90489 100644 --- a/client/src/app/shared/shared-main/video/video.model.ts +++ b/client/src/app/shared/shared-main/video/video.model.ts @@ -220,6 +220,18 @@ export class Video implements VideoServerModel { return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO)) } + canRemoveFiles (user: AuthUser) { + return user.hasRight(UserRight.MANAGE_VIDEO_FILES) && + this.state.id !== VideoState.TO_TRANSCODE && + this.hasHLS() && + this.hasWebTorrent() + } + + canRunTranscoding (user: AuthUser) { + return user.hasRight(UserRight.RUN_VIDEO_TRANSCODING) && + this.state.id !== VideoState.TO_TRANSCODE + } + hasHLS () { return this.streamingPlaylists?.some(p => p.type === VideoStreamingPlaylistType.HLS) } diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts index d135a27dc..9bfa397f8 100644 --- a/client/src/app/shared/shared-main/video/video.service.ts +++ b/client/src/app/shared/shared-main/video/video.service.ts @@ -21,6 +21,7 @@ import { VideoInclude, VideoPrivacy, VideoSortField, + VideoTranscodingCreate, VideoUpdate } from '@shared/models' import { environment } from '../../../../environments/environment' @@ -308,6 +309,17 @@ export class VideoService { ) } + runTranscoding (videoIds: (number | string)[], type: 'hls' | 'webtorrent') { + const body: VideoTranscodingCreate = { transcodingType: type } + + return from(videoIds) + .pipe( + concatMap(id => this.authHttp.post(VideoService.BASE_VIDEO_URL + '/' + id + '/transcoding', body)), + toArray(), + catchError(err => this.restExtractor.handleError(err)) + ) + } + loadCompleteDescription (descriptionPath: string) { return this.authHttp .get<{ description: string }>(environment.apiUrl + descriptionPath) diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts index 82c084791..2ab9f4739 100644 --- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@a import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core' import { BlocklistService, VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation' import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' -import { UserRight, VideoCaption } from '@shared/models' +import { UserRight, VideoCaption, VideoState } from '@shared/models' import { Actor, DropdownAction, @@ -28,6 +28,7 @@ export type VideoActionsDisplayType = { mute?: boolean liveInfo?: boolean removeFiles?: boolean + transcoding?: boolean } @Component({ @@ -56,7 +57,9 @@ export class VideoActionsDropdownComponent implements OnChanges { report: true, duplicate: true, mute: true, - liveInfo: false + liveInfo: false, + removeFiles: false, + transcoding: false } @Input() placement = 'left' @@ -71,6 +74,7 @@ export class VideoActionsDropdownComponent implements OnChanges { @Output() videoUnblocked = new EventEmitter() @Output() videoBlocked = new EventEmitter() @Output() videoAccountMuted = new EventEmitter() + @Output() transcodingCreated = new EventEmitter() @Output() modalOpened = new EventEmitter() videoActions: DropdownAction<{ video: Video }>[][] = [] @@ -177,7 +181,11 @@ export class VideoActionsDropdownComponent implements OnChanges { } canRemoveVideoFiles () { - return this.user.hasRight(UserRight.MANAGE_VIDEO_FILES) && this.video.hasHLS() && this.video.hasWebTorrent() + return this.video.canRemoveFiles(this.user) + } + + canRunTranscoding () { + return this.video.canRunTranscoding(this.user) } /* Action handlers */ @@ -268,6 +276,18 @@ export class VideoActionsDropdownComponent implements OnChanges { }) } + runTranscoding (video: Video, type: 'hls' | 'webtorrent') { + this.videoService.runTranscoding([ video.id ], type) + .subscribe({ + next: () => { + this.notifier.success($localize`Transcoding jobs created for ${video.name}.`) + this.transcodingCreated.emit() + }, + + error: err => this.notifier.error(err.message) + }) + } + onVideoBlocked () { this.videoBlocked.emit() } @@ -341,6 +361,18 @@ export class VideoActionsDropdownComponent implements OnChanges { } ], [ + { + label: $localize`Run HLS transcoding`, + handler: ({ video }) => this.runTranscoding(video, 'hls'), + isDisplayed: () => this.displayOptions.transcoding && this.canRunTranscoding(), + iconName: 'cog' + }, + { + label: $localize`Run WebTorrent transcoding`, + handler: ({ video }) => this.runTranscoding(video, 'webtorrent'), + isDisplayed: () => this.displayOptions.transcoding && this.canRunTranscoding(), + iconName: 'cog' + }, { label: $localize`Delete HLS files`, handler: ({ video }) => this.removeVideoFiles(video, 'hls'), -- cgit v1.2.3