Rename studio to editor
This commit is contained in:
parent
1808a1f8e4
commit
92e66e04f7
81 changed files with 368 additions and 370 deletions
|
@ -200,7 +200,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
|
||||||
resolutions: {}
|
resolutions: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: null
|
enabled: null
|
||||||
},
|
},
|
||||||
autoBlacklist: {
|
autoBlacklist: {
|
||||||
|
|
|
@ -193,9 +193,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-row mt-2"> <!-- video editor grid -->
|
<div class="form-row mt-2"> <!-- video studio grid -->
|
||||||
<div class="form-group col-12 col-lg-4 col-xl-3">
|
<div class="form-group col-12 col-lg-4 col-xl-3">
|
||||||
<div i18n class="inner-form-title">VIDEO EDITOR</div>
|
<div i18n class="inner-form-title">VIDEO STUDIO</div>
|
||||||
<div i18n class="inner-form-description">
|
<div i18n class="inner-form-description">
|
||||||
Allows your users to edit their video (cut, add intro/outro, add a watermark etc)
|
Allows your users to edit their video (cut, add intro/outro, add a watermark etc)
|
||||||
</div>
|
</div>
|
||||||
|
@ -203,14 +203,14 @@
|
||||||
|
|
||||||
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
|
<div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
|
||||||
|
|
||||||
<ng-container formGroupName="videoEditor">
|
<ng-container formGroupName="videoStudio">
|
||||||
<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
|
<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
|
||||||
<my-peertube-checkbox
|
<my-peertube-checkbox
|
||||||
inputName="videoEditorEnabled" formControlName="enabled"
|
inputName="videoStudioEnabled" formControlName="enabled"
|
||||||
i18n-labelText labelText="Enable video editor"
|
i18n-labelText labelText="Enable video studio"
|
||||||
>
|
>
|
||||||
<ng-container ngProjectAs="description" *ngIf="!isTranscodingEnabled()">
|
<ng-container ngProjectAs="description" *ngIf="!isTranscodingEnabled()">
|
||||||
<span i18n>⚠️ You need to enable transcoding first to enable video editor</span>
|
<span i18n>⚠️ You need to enable transcoding first to enable video studio</span>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</my-peertube-checkbox>
|
</my-peertube-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -72,7 +72,7 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
private checkTranscodingFields () {
|
private checkTranscodingFields () {
|
||||||
const transcodingControl = this.form.get('transcoding.enabled')
|
const transcodingControl = this.form.get('transcoding.enabled')
|
||||||
const videoEditorControl = this.form.get('videoEditor.enabled')
|
const videoStudioControl = this.form.get('videoStudio.enabled')
|
||||||
const hlsControl = this.form.get('transcoding.hls.enabled')
|
const hlsControl = this.form.get('transcoding.hls.enabled')
|
||||||
const webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
|
const webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
|
||||||
transcodingControl.valueChanges
|
transcodingControl.valueChanges
|
||||||
.subscribe(newValue => {
|
.subscribe(newValue => {
|
||||||
if (newValue === false) {
|
if (newValue === false) {
|
||||||
videoEditorControl.setValue(false)
|
videoStudioControl.setValue(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
|
||||||
abuseStateChange: $localize`One of your abuse reports has been accepted or rejected by moderators`,
|
abuseStateChange: $localize`One of your abuse reports has been accepted or rejected by moderators`,
|
||||||
newPeerTubeVersion: $localize`A new PeerTube version is available`,
|
newPeerTubeVersion: $localize`A new PeerTube version is available`,
|
||||||
newPluginVersion: $localize`One of your plugin/theme has a new available version`,
|
newPluginVersion: $localize`One of your plugin/theme has a new available version`,
|
||||||
myVideoEditionFinished: $localize`Video edition finished`
|
myVideoStudioEditionFinished: $localize`Video studio edition has finished`
|
||||||
}
|
}
|
||||||
this.notificationSettingGroups = [
|
this.notificationSettingGroups = [
|
||||||
{
|
{
|
||||||
|
@ -64,7 +64,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
|
||||||
'blacklistOnMyVideo',
|
'blacklistOnMyVideo',
|
||||||
'myVideoPublished',
|
'myVideoPublished',
|
||||||
'myVideoImportFinished',
|
'myVideoImportFinished',
|
||||||
'myVideoEditionFinished'
|
'myVideoStudioEditionFinished'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -205,9 +205,9 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
|
||||||
private buildActions () {
|
private buildActions () {
|
||||||
this.videoActions = [
|
this.videoActions = [
|
||||||
{
|
{
|
||||||
label: $localize`Editor`,
|
label: $localize`Studio`,
|
||||||
linkBuilder: ({ video }) => [ '/video-editor/edit', video.uuid ],
|
linkBuilder: ({ video }) => [ '/studio/edit', video.uuid ],
|
||||||
isDisplayed: ({ video }) => video.isEditableBy(this.authService.getUser(), this.serverService.getHTMLConfig().videoEditor.enabled),
|
isDisplayed: ({ video }) => video.isEditableBy(this.authService.getUser(), this.serverService.getHTMLConfig().videoStudio.enabled),
|
||||||
iconName: 'film'
|
iconName: 'film'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
export * from './video-editor-edit.component'
|
|
||||||
export * from './video-editor-edit.resolver'
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './video-editor.module'
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './video-editor.service'
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { NgModule } from '@angular/core'
|
|
||||||
import { RouterModule, Routes } from '@angular/router'
|
|
||||||
import { VideoEditorEditResolver } from './edit'
|
|
||||||
import { VideoEditorEditComponent } from './edit/video-editor-edit.component'
|
|
||||||
|
|
||||||
const videoEditorRoutes: Routes = [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'edit/:videoId',
|
|
||||||
component: VideoEditorEditComponent,
|
|
||||||
data: {
|
|
||||||
meta: {
|
|
||||||
title: $localize`Edit video`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
video: VideoEditorEditResolver
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ RouterModule.forChild(videoEditorRoutes) ],
|
|
||||||
exports: [ RouterModule ]
|
|
||||||
})
|
|
||||||
export class VideoEditorRoutingModule {}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { NgModule } from '@angular/core'
|
|
||||||
import { SharedFormModule } from '@app/shared/shared-forms'
|
|
||||||
import { SharedMainModule } from '@app/shared/shared-main'
|
|
||||||
import { VideoEditorEditComponent, VideoEditorEditResolver } from './edit'
|
|
||||||
import { VideoEditorService } from './shared'
|
|
||||||
import { VideoEditorRoutingModule } from './video-editor-routing.module'
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
VideoEditorRoutingModule,
|
|
||||||
|
|
||||||
SharedMainModule,
|
|
||||||
SharedFormModule
|
|
||||||
],
|
|
||||||
|
|
||||||
declarations: [
|
|
||||||
VideoEditorEditComponent
|
|
||||||
],
|
|
||||||
|
|
||||||
exports: [],
|
|
||||||
|
|
||||||
providers: [
|
|
||||||
VideoEditorService,
|
|
||||||
VideoEditorEditResolver
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class VideoEditorModule { }
|
|
2
client/src/app/+video-studio/edit/index.ts
Normal file
2
client/src/app/+video-studio/edit/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './video-studio-edit.component'
|
||||||
|
export * from './video-studio-edit.resolver'
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="margin-content">
|
<div class="margin-content">
|
||||||
<h1 class="title-page title-page-single" i18n>Edit {{ video.name }}</h1>
|
<h1 class="title-page title-page-single" i18n>Studio for {{ video.name }}</h1>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<form role="form" [formGroup]="form">
|
<form role="form" [formGroup]="form">
|
|
@ -2,18 +2,18 @@ import { Component, OnInit } from '@angular/core'
|
||||||
import { ActivatedRoute, Router } from '@angular/router'
|
import { ActivatedRoute, Router } from '@angular/router'
|
||||||
import { ConfirmService, Notifier, ServerService } from '@app/core'
|
import { ConfirmService, Notifier, ServerService } from '@app/core'
|
||||||
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { Video, VideoDetails } from '@app/shared/shared-main'
|
import { VideoDetails } from '@app/shared/shared-main'
|
||||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { secondsToTime } from '@shared/core-utils'
|
import { secondsToTime } from '@shared/core-utils'
|
||||||
import { VideoEditorTask, VideoEditorTaskCut } from '@shared/models'
|
import { VideoStudioTask, VideoStudioTaskCut } from '@shared/models'
|
||||||
import { VideoEditorService } from '../shared'
|
import { VideoStudioService } from '../shared'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-editor-edit',
|
selector: 'my-video-studio-edit',
|
||||||
templateUrl: './video-editor-edit.component.html',
|
templateUrl: './video-studio-edit.component.html',
|
||||||
styleUrls: [ './video-editor-edit.component.scss' ]
|
styleUrls: [ './video-studio-edit.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideoEditorEditComponent extends FormReactive implements OnInit {
|
export class VideoStudioEditComponent extends FormReactive implements OnInit {
|
||||||
isRunningEdition = false
|
isRunningEdition = false
|
||||||
|
|
||||||
video: VideoDetails
|
video: VideoDetails
|
||||||
|
@ -24,7 +24,7 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private videoEditorService: VideoEditorService,
|
private videoStudioService: VideoStudioService,
|
||||||
private loadingBar: LoadingBarService,
|
private loadingBar: LoadingBarService,
|
||||||
private confirmService: ConfirmService
|
private confirmService: ConfirmService
|
||||||
) {
|
) {
|
||||||
|
@ -84,11 +84,13 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
|
||||||
|
|
||||||
this.loadingBar.useRef().start()
|
this.loadingBar.useRef().start()
|
||||||
|
|
||||||
return this.videoEditorService.editVideo(this.video.uuid, tasks)
|
return this.videoStudioService.editVideo(this.video.uuid, tasks)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.notifier.success($localize`Video updated.`)
|
this.notifier.success($localize`Edition tasks created.`)
|
||||||
this.router.navigateByUrl(Video.buildWatchUrl(this.video))
|
|
||||||
|
// Don't redirect to old video version watch page that could be confusing for users
|
||||||
|
this.router.navigateByUrl('/my-library/videos')
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => {
|
error: err => {
|
||||||
|
@ -153,13 +155,13 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildTasks () {
|
private buildTasks () {
|
||||||
const tasks: VideoEditorTask[] = []
|
const tasks: VideoStudioTask[] = []
|
||||||
const value = this.form.value
|
const value = this.form.value
|
||||||
|
|
||||||
const cut = value['cut']
|
const cut = value['cut']
|
||||||
if (cut['start'] !== 0 || cut['end'] !== this.video.duration) {
|
if (cut['start'] !== 0 || cut['end'] !== this.video.duration) {
|
||||||
|
|
||||||
const options: VideoEditorTaskCut['options'] = {}
|
const options: VideoStudioTaskCut['options'] = {}
|
||||||
if (cut['start'] !== 0) options.start = cut['start']
|
if (cut['start'] !== 0) options.start = cut['start']
|
||||||
if (cut['end'] !== this.video.duration) options.end = cut['end']
|
if (cut['end'] !== this.video.duration) options.end = cut['end']
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve } from '@angular/router'
|
||||||
import { VideoService } from '@app/shared/shared-main'
|
import { VideoService } from '@app/shared/shared-main'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VideoEditorEditResolver implements Resolve<any> {
|
export class VideoStudioEditResolver implements Resolve<any> {
|
||||||
constructor (
|
constructor (
|
||||||
private videoService: VideoService
|
private videoService: VideoService
|
||||||
) {
|
) {
|
1
client/src/app/+video-studio/index.ts
Normal file
1
client/src/app/+video-studio/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './video-studio.module'
|
1
client/src/app/+video-studio/shared/index.ts
Normal file
1
client/src/app/+video-studio/shared/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './video-studio.service'
|
|
@ -4,19 +4,19 @@ import { Injectable } from '@angular/core'
|
||||||
import { RestExtractor } from '@app/core'
|
import { RestExtractor } from '@app/core'
|
||||||
import { objectToFormData } from '@app/helpers'
|
import { objectToFormData } from '@app/helpers'
|
||||||
import { VideoService } from '@app/shared/shared-main'
|
import { VideoService } from '@app/shared/shared-main'
|
||||||
import { VideoEditorCreateEdition, VideoEditorTask } from '@shared/models'
|
import { VideoStudioCreateEdition, VideoStudioTask } from '@shared/models'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VideoEditorService {
|
export class VideoStudioService {
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private authHttp: HttpClient,
|
private authHttp: HttpClient,
|
||||||
private restExtractor: RestExtractor
|
private restExtractor: RestExtractor
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
editVideo (videoId: number | string, tasks: VideoEditorTask[]) {
|
editVideo (videoId: number | string, tasks: VideoStudioTask[]) {
|
||||||
const url = VideoService.BASE_VIDEO_URL + '/' + videoId + '/editor/edit'
|
const url = VideoService.BASE_VIDEO_URL + '/' + videoId + '/studio/edit'
|
||||||
const body: VideoEditorCreateEdition = {
|
const body: VideoStudioCreateEdition = {
|
||||||
tasks
|
tasks
|
||||||
}
|
}
|
||||||
|
|
29
client/src/app/+video-studio/video-studio-routing.module.ts
Normal file
29
client/src/app/+video-studio/video-studio-routing.module.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { NgModule } from '@angular/core'
|
||||||
|
import { RouterModule, Routes } from '@angular/router'
|
||||||
|
import { VideoStudioEditComponent, VideoStudioEditResolver } from './edit'
|
||||||
|
|
||||||
|
const videoStudioRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'edit/:videoId',
|
||||||
|
component: VideoStudioEditComponent,
|
||||||
|
data: {
|
||||||
|
meta: {
|
||||||
|
title: $localize`Studio`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
video: VideoStudioEditResolver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [ RouterModule.forChild(videoStudioRoutes) ],
|
||||||
|
exports: [ RouterModule ]
|
||||||
|
})
|
||||||
|
export class VideoStudioRoutingModule {}
|
27
client/src/app/+video-studio/video-studio.module.ts
Normal file
27
client/src/app/+video-studio/video-studio.module.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { NgModule } from '@angular/core'
|
||||||
|
import { SharedFormModule } from '@app/shared/shared-forms'
|
||||||
|
import { SharedMainModule } from '@app/shared/shared-main'
|
||||||
|
import { VideoStudioEditComponent, VideoStudioEditResolver } from './edit'
|
||||||
|
import { VideoStudioService } from './shared'
|
||||||
|
import { VideoStudioRoutingModule } from './video-studio-routing.module'
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
VideoStudioRoutingModule,
|
||||||
|
|
||||||
|
SharedMainModule,
|
||||||
|
SharedFormModule
|
||||||
|
],
|
||||||
|
|
||||||
|
declarations: [
|
||||||
|
VideoStudioEditComponent
|
||||||
|
],
|
||||||
|
|
||||||
|
exports: [],
|
||||||
|
|
||||||
|
providers: [
|
||||||
|
VideoStudioService,
|
||||||
|
VideoStudioEditResolver
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class VideoStudioModule { }
|
|
@ -35,7 +35,7 @@ export class ActionButtonsComponent implements OnInit, OnChanges {
|
||||||
playlist: false,
|
playlist: false,
|
||||||
download: true,
|
download: true,
|
||||||
update: true,
|
update: true,
|
||||||
editor: true,
|
studio: true,
|
||||||
blacklist: true,
|
blacklist: true,
|
||||||
delete: true,
|
delete: true,
|
||||||
report: true,
|
report: true,
|
||||||
|
|
|
@ -144,8 +144,8 @@ const routes: Routes = [
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: 'video-editor',
|
path: 'studio',
|
||||||
loadChildren: () => import('./+video-editor/video-editor.module').then(m => m.VideoEditorModule),
|
loadChildren: () => import('./+video-studio/video-studio.module').then(m => m.VideoStudioModule),
|
||||||
canActivateChild: [ MetaGuard ]
|
canActivateChild: [ MetaGuard ]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,7 @@ export class UserNotification implements UserNotificationServer {
|
||||||
this.pluginQueryParams.pluginType = this.plugin.type + ''
|
this.pluginQueryParams.pluginType = this.plugin.type + ''
|
||||||
break
|
break
|
||||||
|
|
||||||
case UserNotificationType.MY_VIDEO_EDITION_FINISHED:
|
case UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED:
|
||||||
this.videoUrl = this.buildVideoUrl(this.video)
|
this.videoUrl = this.buildVideoUrl(this.video)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="19"> <!-- UserNotificationType.MY_VIDEO_EDITION_FINISHED -->
|
<ng-container *ngSwitchCase="19"> <!-- UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED -->
|
||||||
<my-global-icon iconName="film" aria-hidden="true"></my-global-icon>
|
<my-global-icon iconName="film" aria-hidden="true"></my-global-icon>
|
||||||
|
|
||||||
<div class="message" i18n>
|
<div class="message" i18n>
|
||||||
|
|
|
@ -228,8 +228,8 @@ export class Video implements VideoServerModel {
|
||||||
return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO))
|
return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO))
|
||||||
}
|
}
|
||||||
|
|
||||||
isEditableBy (user: AuthUser, videoEditorEnabled: boolean) {
|
isEditableBy (user: AuthUser, videoStudioEnabled: boolean) {
|
||||||
return videoEditorEnabled &&
|
return videoStudioEnabled &&
|
||||||
this.state?.id === VideoState.PUBLISHED &&
|
this.state?.id === VideoState.PUBLISHED &&
|
||||||
this.isUpdatableBy(user)
|
this.isUpdatableBy(user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ export type VideoActionsDisplayType = {
|
||||||
liveInfo?: boolean
|
liveInfo?: boolean
|
||||||
removeFiles?: boolean
|
removeFiles?: boolean
|
||||||
transcoding?: boolean
|
transcoding?: boolean
|
||||||
editor?: boolean
|
studio?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -61,7 +61,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
|
||||||
liveInfo: false,
|
liveInfo: false,
|
||||||
removeFiles: false,
|
removeFiles: false,
|
||||||
transcoding: false,
|
transcoding: false,
|
||||||
editor: true
|
studio: true
|
||||||
}
|
}
|
||||||
@Input() placement = 'left'
|
@Input() placement = 'left'
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoEditable () {
|
isVideoEditable () {
|
||||||
return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoEditor.enabled)
|
return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoStudio.enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideoRemovable () {
|
isVideoRemovable () {
|
||||||
|
@ -337,10 +337,10 @@ export class VideoActionsDropdownComponent implements OnChanges {
|
||||||
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
|
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $localize`Editor`,
|
label: $localize`Studio`,
|
||||||
linkBuilder: ({ video }) => [ '/video-editor/edit', video.uuid ],
|
linkBuilder: ({ video }) => [ '/studio/edit', video.uuid ],
|
||||||
iconName: 'film',
|
iconName: 'film',
|
||||||
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.editor && this.isVideoEditable()
|
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.studio && this.isVideoEditable()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $localize`Block`,
|
label: $localize`Block`,
|
||||||
|
|
|
@ -436,7 +436,7 @@ live:
|
||||||
1440p: false
|
1440p: false
|
||||||
2160p: false
|
2160p: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
# Enable video edition by users (cut, add intro/outro, add watermark etc)
|
# Enable video edition by users (cut, add intro/outro, add watermark etc)
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,7 @@ live:
|
||||||
1440p: false
|
1440p: false
|
||||||
2160p: false
|
2160p: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
# Enable video edition by users (cut, add intro/outro, add watermark etc)
|
# Enable video edition by users (cut, add intro/outro, add watermark etc)
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ signup:
|
||||||
transcoding:
|
transcoding:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
live:
|
live:
|
||||||
|
|
|
@ -31,5 +31,5 @@ admin:
|
||||||
transcoding:
|
transcoding:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -31,5 +31,5 @@ admin:
|
||||||
transcoding:
|
transcoding:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -31,5 +31,5 @@ admin:
|
||||||
transcoding:
|
transcoding:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -31,5 +31,5 @@ admin:
|
||||||
transcoding:
|
transcoding:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
|
@ -168,5 +168,5 @@ views:
|
||||||
local_buffer_update_interval: '5 seconds'
|
local_buffer_update_interval: '5 seconds'
|
||||||
ip_view_expiration: '1 second'
|
ip_view_expiration: '1 second'
|
||||||
|
|
||||||
video_editor:
|
video_studio:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -259,8 +259,8 @@ function customConfig (): CustomConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: CONFIG.VIDEO_EDITOR.ENABLED
|
enabled: CONFIG.VIDEO_STUDIO.ENABLED
|
||||||
},
|
},
|
||||||
import: {
|
import: {
|
||||||
videos: {
|
videos: {
|
||||||
|
|
|
@ -83,7 +83,7 @@ async function updateNotificationSettings (req: express.Request, res: express.Re
|
||||||
abuseStateChange: body.abuseStateChange,
|
abuseStateChange: body.abuseStateChange,
|
||||||
newPeerTubeVersion: body.newPeerTubeVersion,
|
newPeerTubeVersion: body.newPeerTubeVersion,
|
||||||
newPluginVersion: body.newPluginVersion,
|
newPluginVersion: body.newPluginVersion,
|
||||||
myVideoEditionFinished: body.myVideoEditionFinished
|
myVideoStudioEditionFinished: body.myVideoStudioEditionFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
await UserNotificationSettingModel.update(values, query)
|
await UserNotificationSettingModel.update(values, query)
|
||||||
|
|
|
@ -35,7 +35,7 @@ import { VideoModel } from '../../../models/video/video'
|
||||||
import { blacklistRouter } from './blacklist'
|
import { blacklistRouter } from './blacklist'
|
||||||
import { videoCaptionsRouter } from './captions'
|
import { videoCaptionsRouter } from './captions'
|
||||||
import { videoCommentRouter } from './comment'
|
import { videoCommentRouter } from './comment'
|
||||||
import { editorRouter } from './editor'
|
import { studioRouter } from './studio'
|
||||||
import { filesRouter } from './files'
|
import { filesRouter } from './files'
|
||||||
import { videoImportsRouter } from './import'
|
import { videoImportsRouter } from './import'
|
||||||
import { liveRouter } from './live'
|
import { liveRouter } from './live'
|
||||||
|
@ -52,7 +52,7 @@ const videosRouter = express.Router()
|
||||||
videosRouter.use('/', blacklistRouter)
|
videosRouter.use('/', blacklistRouter)
|
||||||
videosRouter.use('/', rateVideoRouter)
|
videosRouter.use('/', rateVideoRouter)
|
||||||
videosRouter.use('/', videoCommentRouter)
|
videosRouter.use('/', videoCommentRouter)
|
||||||
videosRouter.use('/', editorRouter)
|
videosRouter.use('/', studioRouter)
|
||||||
videosRouter.use('/', videoCaptionsRouter)
|
videosRouter.use('/', videoCaptionsRouter)
|
||||||
videosRouter.use('/', videoImportsRouter)
|
videosRouter.use('/', videoImportsRouter)
|
||||||
videosRouter.use('/', ownershipVideoRouter)
|
videosRouter.use('/', ownershipVideoRouter)
|
||||||
|
|
|
@ -2,26 +2,26 @@ import express from 'express'
|
||||||
import { createAnyReqFiles } from '@server/helpers/express-utils'
|
import { createAnyReqFiles } from '@server/helpers/express-utils'
|
||||||
import { MIMETYPES } from '@server/initializers/constants'
|
import { MIMETYPES } from '@server/initializers/constants'
|
||||||
import { JobQueue } from '@server/lib/job-queue'
|
import { JobQueue } from '@server/lib/job-queue'
|
||||||
import { buildTaskFileFieldname, getTaskFile } from '@server/lib/video-editor'
|
import { buildTaskFileFieldname, getTaskFile } from '@server/lib/video-studio'
|
||||||
import {
|
import {
|
||||||
HttpStatusCode,
|
HttpStatusCode,
|
||||||
VideoEditionTaskPayload,
|
VideoState,
|
||||||
VideoEditorCreateEdition,
|
VideoStudioCreateEdition,
|
||||||
VideoEditorTask,
|
VideoStudioTask,
|
||||||
VideoEditorTaskCut,
|
VideoStudioTaskCut,
|
||||||
VideoEditorTaskIntro,
|
VideoStudioTaskIntro,
|
||||||
VideoEditorTaskOutro,
|
VideoStudioTaskOutro,
|
||||||
VideoEditorTaskWatermark,
|
VideoStudioTaskPayload,
|
||||||
VideoState
|
VideoStudioTaskWatermark
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
import { asyncMiddleware, authenticate, videosEditorAddEditionValidator } from '../../../middlewares'
|
import { asyncMiddleware, authenticate, videoStudioAddEditionValidator } from '../../../middlewares'
|
||||||
|
|
||||||
const editorRouter = express.Router()
|
const studioRouter = express.Router()
|
||||||
|
|
||||||
const tasksFiles = createAnyReqFiles(
|
const tasksFiles = createAnyReqFiles(
|
||||||
MIMETYPES.VIDEO.MIMETYPE_EXT,
|
MIMETYPES.VIDEO.MIMETYPE_EXT,
|
||||||
(req: express.Request, file: Express.Multer.File, cb: (err: Error, result?: boolean) => void) => {
|
(req: express.Request, file: Express.Multer.File, cb: (err: Error, result?: boolean) => void) => {
|
||||||
const body = req.body as VideoEditorCreateEdition
|
const body = req.body as VideoStudioCreateEdition
|
||||||
|
|
||||||
// Fetch array element
|
// Fetch array element
|
||||||
const matches = file.fieldname.match(/tasks\[(\d+)\]/)
|
const matches = file.fieldname.match(/tasks\[(\d+)\]/)
|
||||||
|
@ -43,24 +43,24 @@ const tasksFiles = createAnyReqFiles(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
editorRouter.post('/:videoId/editor/edit',
|
studioRouter.post('/:videoId/studio/edit',
|
||||||
authenticate,
|
authenticate,
|
||||||
tasksFiles,
|
tasksFiles,
|
||||||
asyncMiddleware(videosEditorAddEditionValidator),
|
asyncMiddleware(videoStudioAddEditionValidator),
|
||||||
asyncMiddleware(createEditionTasks)
|
asyncMiddleware(createEditionTasks)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
editorRouter
|
studioRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
async function createEditionTasks (req: express.Request, res: express.Response) {
|
async function createEditionTasks (req: express.Request, res: express.Response) {
|
||||||
const files = req.files as Express.Multer.File[]
|
const files = req.files as Express.Multer.File[]
|
||||||
const body = req.body as VideoEditorCreateEdition
|
const body = req.body as VideoStudioCreateEdition
|
||||||
const video = res.locals.videoAll
|
const video = res.locals.videoAll
|
||||||
|
|
||||||
video.state = VideoState.TO_EDIT
|
video.state = VideoState.TO_EDIT
|
||||||
|
@ -71,13 +71,13 @@ async function createEditionTasks (req: express.Request, res: express.Response)
|
||||||
tasks: body.tasks.map((t, i) => buildTaskPayload(t, i, files))
|
tasks: body.tasks.map((t, i) => buildTaskPayload(t, i, files))
|
||||||
}
|
}
|
||||||
|
|
||||||
JobQueue.Instance.createJob({ type: 'video-edition', payload })
|
JobQueue.Instance.createJob({ type: 'video-studio-edition', payload })
|
||||||
|
|
||||||
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
|
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskPayloadBuilders: {
|
const taskPayloadBuilders: {
|
||||||
[id in VideoEditorTask['name']]: (task: VideoEditorTask, indice?: number, files?: Express.Multer.File[]) => VideoEditionTaskPayload
|
[id in VideoStudioTask['name']]: (task: VideoStudioTask, indice?: number, files?: Express.Multer.File[]) => VideoStudioTaskPayload
|
||||||
} = {
|
} = {
|
||||||
'add-intro': buildIntroOutroTask,
|
'add-intro': buildIntroOutroTask,
|
||||||
'add-outro': buildIntroOutroTask,
|
'add-outro': buildIntroOutroTask,
|
||||||
|
@ -85,11 +85,11 @@ const taskPayloadBuilders: {
|
||||||
'add-watermark': buildWatermarkTask
|
'add-watermark': buildWatermarkTask
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTaskPayload (task: VideoEditorTask, indice: number, files: Express.Multer.File[]): VideoEditionTaskPayload {
|
function buildTaskPayload (task: VideoStudioTask, indice: number, files: Express.Multer.File[]): VideoStudioTaskPayload {
|
||||||
return taskPayloadBuilders[task.name](task, indice, files)
|
return taskPayloadBuilders[task.name](task, indice, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildIntroOutroTask (task: VideoEditorTaskIntro | VideoEditorTaskOutro, indice: number, files: Express.Multer.File[]) {
|
function buildIntroOutroTask (task: VideoStudioTaskIntro | VideoStudioTaskOutro, indice: number, files: Express.Multer.File[]) {
|
||||||
return {
|
return {
|
||||||
name: task.name,
|
name: task.name,
|
||||||
options: {
|
options: {
|
||||||
|
@ -98,7 +98,7 @@ function buildIntroOutroTask (task: VideoEditorTaskIntro | VideoEditorTaskOutro,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCutTask (task: VideoEditorTaskCut) {
|
function buildCutTask (task: VideoStudioTaskCut) {
|
||||||
return {
|
return {
|
||||||
name: task.name,
|
name: task.name,
|
||||||
options: {
|
options: {
|
||||||
|
@ -108,7 +108,7 @@ function buildCutTask (task: VideoEditorTaskCut) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildWatermarkTask (task: VideoEditorTaskWatermark, indice: number, files: Express.Multer.File[]) {
|
function buildWatermarkTask (task: VideoStudioTaskWatermark, indice: number, files: Express.Multer.File[]) {
|
||||||
return {
|
return {
|
||||||
name: task.name,
|
name: task.name,
|
||||||
options: {
|
options: {
|
|
@ -1,40 +1,40 @@
|
||||||
import validator from 'validator'
|
import validator from 'validator'
|
||||||
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
|
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
|
||||||
import { buildTaskFileFieldname } from '@server/lib/video-editor'
|
import { buildTaskFileFieldname } from '@server/lib/video-studio'
|
||||||
import { VideoEditorTask } from '@shared/models'
|
import { VideoStudioTask } from '@shared/models'
|
||||||
import { isArray } from './misc'
|
import { isArray } from './misc'
|
||||||
import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos'
|
import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos'
|
||||||
|
|
||||||
function isValidEditorTasksArray (tasks: any) {
|
function isValidStudioTasksArray (tasks: any) {
|
||||||
if (!isArray(tasks)) return false
|
if (!isArray(tasks)) return false
|
||||||
|
|
||||||
return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.min &&
|
return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_STUDIO.TASKS.min &&
|
||||||
tasks.length <= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.max
|
tasks.length <= CONSTRAINTS_FIELDS.VIDEO_STUDIO.TASKS.max
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEditorCutTaskValid (task: VideoEditorTask) {
|
function isStudioCutTaskValid (task: VideoStudioTask) {
|
||||||
if (task.name !== 'cut') return false
|
if (task.name !== 'cut') return false
|
||||||
if (!task.options) return false
|
if (!task.options) return false
|
||||||
|
|
||||||
const { start, end } = task.options
|
const { start, end } = task.options
|
||||||
if (!start && !end) return false
|
if (!start && !end) return false
|
||||||
|
|
||||||
if (start && !validator.isInt(start + '', CONSTRAINTS_FIELDS.VIDEO_EDITOR.CUT_TIME)) return false
|
if (start && !validator.isInt(start + '', CONSTRAINTS_FIELDS.VIDEO_STUDIO.CUT_TIME)) return false
|
||||||
if (end && !validator.isInt(end + '', CONSTRAINTS_FIELDS.VIDEO_EDITOR.CUT_TIME)) return false
|
if (end && !validator.isInt(end + '', CONSTRAINTS_FIELDS.VIDEO_STUDIO.CUT_TIME)) return false
|
||||||
|
|
||||||
if (!start || !end) return true
|
if (!start || !end) return true
|
||||||
|
|
||||||
return parseInt(start + '') < parseInt(end + '')
|
return parseInt(start + '') < parseInt(end + '')
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEditorTaskAddIntroOutroValid (task: VideoEditorTask, indice: number, files: Express.Multer.File[]) {
|
function isStudioTaskAddIntroOutroValid (task: VideoStudioTask, indice: number, files: Express.Multer.File[]) {
|
||||||
const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file'))
|
const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file'))
|
||||||
|
|
||||||
return (task.name === 'add-intro' || task.name === 'add-outro') &&
|
return (task.name === 'add-intro' || task.name === 'add-outro') &&
|
||||||
file && isVideoFileMimeTypeValid([ file ], null)
|
file && isVideoFileMimeTypeValid([ file ], null)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEditorTaskAddWatermarkValid (task: VideoEditorTask, indice: number, files: Express.Multer.File[]) {
|
function isStudioTaskAddWatermarkValid (task: VideoStudioTask, indice: number, files: Express.Multer.File[]) {
|
||||||
const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file'))
|
const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file'))
|
||||||
|
|
||||||
return task.name === 'add-watermark' &&
|
return task.name === 'add-watermark' &&
|
||||||
|
@ -44,9 +44,9 @@ function isEditorTaskAddWatermarkValid (task: VideoEditorTask, indice: number, f
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isValidEditorTasksArray,
|
isValidStudioTasksArray,
|
||||||
|
|
||||||
isEditorCutTaskValid,
|
isStudioCutTaskValid,
|
||||||
isEditorTaskAddIntroOutroValid,
|
isStudioTaskAddIntroOutroValid,
|
||||||
isEditorTaskAddWatermarkValid
|
isStudioTaskAddWatermarkValid
|
||||||
}
|
}
|
|
@ -49,7 +49,7 @@ function checkConfig () {
|
||||||
checkSearchConfig()
|
checkSearchConfig()
|
||||||
checkLiveConfig()
|
checkLiveConfig()
|
||||||
checkObjectStorageConfig()
|
checkObjectStorageConfig()
|
||||||
checkVideoEditorConfig()
|
checkVideoStudioConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We get db by param to not import it in this file (import orders)
|
// We get db by param to not import it in this file (import orders)
|
||||||
|
@ -260,8 +260,8 @@ function checkObjectStorageConfig () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkVideoEditorConfig () {
|
function checkVideoStudioConfig () {
|
||||||
if (CONFIG.VIDEO_EDITOR.ENABLED === true && CONFIG.TRANSCODING.ENABLED === false) {
|
if (CONFIG.VIDEO_STUDIO.ENABLED === true && CONFIG.TRANSCODING.ENABLED === false) {
|
||||||
throw new Error('Video editor cannot be enabled if transcoding is disabled')
|
throw new Error('Video studio cannot be enabled if transcoding is disabled')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ function checkMissedConfig () {
|
||||||
'transcoding.profile', 'transcoding.concurrency',
|
'transcoding.profile', 'transcoding.concurrency',
|
||||||
'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p',
|
'transcoding.resolutions.0p', 'transcoding.resolutions.144p', 'transcoding.resolutions.240p', 'transcoding.resolutions.360p',
|
||||||
'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p',
|
'transcoding.resolutions.480p', 'transcoding.resolutions.720p', 'transcoding.resolutions.1080p', 'transcoding.resolutions.1440p',
|
||||||
'transcoding.resolutions.2160p', 'video_editor.enabled',
|
'transcoding.resolutions.2160p', 'video_studio.enabled',
|
||||||
'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'auto_blacklist.videos.of_users.enabled',
|
'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'auto_blacklist.videos.of_users.enabled',
|
||||||
'trending.videos.interval_days',
|
'trending.videos.interval_days',
|
||||||
'client.videos.miniature.display_author_avatar',
|
'client.videos.miniature.display_author_avatar',
|
||||||
|
|
|
@ -335,8 +335,8 @@ const CONFIG = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
VIDEO_EDITOR: {
|
VIDEO_STUDIO: {
|
||||||
get ENABLED () { return config.get<boolean>('video_editor.enabled') }
|
get ENABLED () { return config.get<boolean>('video_studio.enabled') }
|
||||||
},
|
},
|
||||||
IMPORT: {
|
IMPORT: {
|
||||||
VIDEOS: {
|
VIDEOS: {
|
||||||
|
|
|
@ -152,7 +152,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = {
|
||||||
'activitypub-refresher': 1,
|
'activitypub-refresher': 1,
|
||||||
'video-redundancy': 1,
|
'video-redundancy': 1,
|
||||||
'video-live-ending': 1,
|
'video-live-ending': 1,
|
||||||
'video-edition': 1,
|
'video-studio-edition': 1,
|
||||||
'manage-video-torrent': 1,
|
'manage-video-torrent': 1,
|
||||||
'move-to-object-storage': 3
|
'move-to-object-storage': 3
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-im
|
||||||
'activitypub-refresher': 1,
|
'activitypub-refresher': 1,
|
||||||
'video-redundancy': 1,
|
'video-redundancy': 1,
|
||||||
'video-live-ending': 10,
|
'video-live-ending': 10,
|
||||||
'video-edition': 1,
|
'video-studio-edition': 1,
|
||||||
'manage-video-torrent': 1,
|
'manage-video-torrent': 1,
|
||||||
'move-to-object-storage': 1
|
'move-to-object-storage': 1
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ const JOB_TTL: { [id in JobType]: number } = {
|
||||||
'activitypub-cleaner': 1000 * 3600, // 1 hour
|
'activitypub-cleaner': 1000 * 3600, // 1 hour
|
||||||
'video-file-import': 1000 * 3600, // 1 hour
|
'video-file-import': 1000 * 3600, // 1 hour
|
||||||
'video-transcoding': 1000 * 3600 * 48, // 2 days, transcoding could be long
|
'video-transcoding': 1000 * 3600 * 48, // 2 days, transcoding could be long
|
||||||
'video-edition': 1000 * 3600 * 10, // 10 hours
|
'video-studio-edition': 1000 * 3600 * 10, // 10 hours
|
||||||
'video-import': 1000 * 3600 * 2, // 2 hours
|
'video-import': 1000 * 3600 * 2, // 2 hours
|
||||||
'email': 60000 * 10, // 10 minutes
|
'email': 60000 * 10, // 10 minutes
|
||||||
'actor-keys': 60000 * 20, // 20 minutes
|
'actor-keys': 60000 * 20, // 20 minutes
|
||||||
|
@ -358,7 +358,7 @@ const CONSTRAINTS_FIELDS = {
|
||||||
COMMONS: {
|
COMMONS: {
|
||||||
URL: { min: 5, max: 2000 } // Length
|
URL: { min: 5, max: 2000 } // Length
|
||||||
},
|
},
|
||||||
VIDEO_EDITOR: {
|
VIDEO_STUDIO: {
|
||||||
TASKS: { min: 1, max: 10 }, // Number of tasks
|
TASKS: { min: 1, max: 10 }, // Number of tasks
|
||||||
CUT_TIME: { min: 0 } // Value
|
CUT_TIME: { min: 0 } // Value
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ async function up (utils: {
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
allowNull: true
|
allowNull: true
|
||||||
}
|
}
|
||||||
await utils.queryInterface.addColumn('userNotificationSetting', 'myVideoEditionFinished', data, { transaction })
|
await utils.queryInterface.addColumn('userNotificationSetting', 'myVideoStudioEditionFinished', data, { transaction })
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const query = 'UPDATE "userNotificationSetting" SET "myVideoEditionFinished" = 1'
|
const query = 'UPDATE "userNotificationSetting" SET "myVideoStudioEditionFinished" = 1'
|
||||||
await utils.sequelize.query(query, { transaction })
|
await utils.sequelize.query(query, { transaction })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ async function up (utils: {
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
}
|
}
|
||||||
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoEditionFinished', data, { transaction })
|
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoStudioEditionFinished', data, { transaction })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ import { generateWebTorrentVideoFilename } from '@server/lib/paths'
|
||||||
import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
|
import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
|
||||||
import { isAbleToUploadVideo } from '@server/lib/user'
|
import { isAbleToUploadVideo } from '@server/lib/user'
|
||||||
import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
|
import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
|
||||||
import { approximateIntroOutroAdditionalSize } from '@server/lib/video-editor'
|
|
||||||
import { VideoPathManager } from '@server/lib/video-path-manager'
|
import { VideoPathManager } from '@server/lib/video-path-manager'
|
||||||
|
import { approximateIntroOutroAdditionalSize } from '@server/lib/video-studio'
|
||||||
import { UserModel } from '@server/models/user/user'
|
import { UserModel } from '@server/models/user/user'
|
||||||
import { VideoModel } from '@server/models/video/video'
|
import { VideoModel } from '@server/models/video/video'
|
||||||
import { VideoFileModel } from '@server/models/video/video-file'
|
import { VideoFileModel } from '@server/models/video/video-file'
|
||||||
|
@ -26,23 +26,23 @@ import {
|
||||||
getVideoStreamFPS
|
getVideoStreamFPS
|
||||||
} from '@shared/extra-utils'
|
} from '@shared/extra-utils'
|
||||||
import {
|
import {
|
||||||
VideoEditionPayload,
|
VideoStudioEditionPayload,
|
||||||
VideoEditionTaskPayload,
|
VideoStudioTaskPayload,
|
||||||
VideoEditorTask,
|
VideoStudioTaskCutPayload,
|
||||||
VideoEditorTaskCutPayload,
|
VideoStudioTaskIntroPayload,
|
||||||
VideoEditorTaskIntroPayload,
|
VideoStudioTaskOutroPayload,
|
||||||
VideoEditorTaskOutroPayload,
|
VideoStudioTaskWatermarkPayload,
|
||||||
VideoEditorTaskWatermarkPayload
|
VideoStudioTask
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
import { logger, loggerTagsFactory } from '../../../helpers/logger'
|
import { logger, loggerTagsFactory } from '../../../helpers/logger'
|
||||||
|
|
||||||
const lTagsBase = loggerTagsFactory('video-edition')
|
const lTagsBase = loggerTagsFactory('video-edition')
|
||||||
|
|
||||||
async function processVideoEdition (job: Job) {
|
async function processVideoStudioEdition (job: Job) {
|
||||||
const payload = job.data as VideoEditionPayload
|
const payload = job.data as VideoStudioEditionPayload
|
||||||
const lTags = lTagsBase(payload.videoUUID)
|
const lTags = lTagsBase(payload.videoUUID)
|
||||||
|
|
||||||
logger.info('Process video edition of %s in job %d.', payload.videoUUID, job.id, lTags)
|
logger.info('Process video studio edition of %s in job %d.', payload.videoUUID, job.id, lTags)
|
||||||
|
|
||||||
const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(payload.videoUUID)
|
const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(payload.videoUUID)
|
||||||
|
|
||||||
|
@ -106,12 +106,12 @@ async function processVideoEdition (job: Job) {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
processVideoEdition
|
processVideoStudioEdition
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
type TaskProcessorOptions <T extends VideoEditionTaskPayload = VideoEditionTaskPayload> = {
|
type TaskProcessorOptions <T extends VideoStudioTaskPayload = VideoStudioTaskPayload> = {
|
||||||
inputPath: string
|
inputPath: string
|
||||||
outputPath: string
|
outputPath: string
|
||||||
video: MVideo
|
video: MVideo
|
||||||
|
@ -119,7 +119,7 @@ type TaskProcessorOptions <T extends VideoEditionTaskPayload = VideoEditionTaskP
|
||||||
lTags: { tags: string[] }
|
lTags: { tags: string[] }
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskProcessors: { [id in VideoEditorTask['name']]: (options: TaskProcessorOptions) => Promise<any> } = {
|
const taskProcessors: { [id in VideoStudioTask['name']]: (options: TaskProcessorOptions) => Promise<any> } = {
|
||||||
'add-intro': processAddIntroOutro,
|
'add-intro': processAddIntroOutro,
|
||||||
'add-outro': processAddIntroOutro,
|
'add-outro': processAddIntroOutro,
|
||||||
'cut': processCut,
|
'cut': processCut,
|
||||||
|
@ -137,7 +137,7 @@ async function processTask (options: TaskProcessorOptions) {
|
||||||
return processor(options)
|
return processor(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
function processAddIntroOutro (options: TaskProcessorOptions<VideoEditorTaskIntroPayload | VideoEditorTaskOutroPayload>) {
|
function processAddIntroOutro (options: TaskProcessorOptions<VideoStudioTaskIntroPayload | VideoStudioTaskOutroPayload>) {
|
||||||
const { task } = options
|
const { task } = options
|
||||||
|
|
||||||
return addIntroOutro({
|
return addIntroOutro({
|
||||||
|
@ -153,7 +153,7 @@ function processAddIntroOutro (options: TaskProcessorOptions<VideoEditorTaskIntr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function processCut (options: TaskProcessorOptions<VideoEditorTaskCutPayload>) {
|
function processCut (options: TaskProcessorOptions<VideoStudioTaskCutPayload>) {
|
||||||
const { task } = options
|
const { task } = options
|
||||||
|
|
||||||
return cutVideo({
|
return cutVideo({
|
||||||
|
@ -164,7 +164,7 @@ function processCut (options: TaskProcessorOptions<VideoEditorTaskCutPayload>) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function processAddWatermark (options: TaskProcessorOptions<VideoEditorTaskWatermarkPayload>) {
|
function processAddWatermark (options: TaskProcessorOptions<VideoStudioTaskWatermarkPayload>) {
|
||||||
const { task } = options
|
const { task } = options
|
||||||
|
|
||||||
return addWatermark({
|
return addWatermark({
|
||||||
|
@ -212,10 +212,10 @@ async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileExceptio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkUserQuotaOrThrow (video: MVideoFullLight, payload: VideoEditionPayload) {
|
async function checkUserQuotaOrThrow (video: MVideoFullLight, payload: VideoStudioEditionPayload) {
|
||||||
const user = await UserModel.loadByVideoId(video.id)
|
const user = await UserModel.loadByVideoId(video.id)
|
||||||
|
|
||||||
const filePathFinder = (i: number) => (payload.tasks[i] as VideoEditorTaskIntroPayload | VideoEditorTaskOutroPayload).options.file
|
const filePathFinder = (i: number) => (payload.tasks[i] as VideoStudioTaskIntroPayload | VideoStudioTaskOutroPayload).options.file
|
||||||
|
|
||||||
const additionalBytes = await approximateIntroOutroAdditionalSize(video, payload.tasks, filePathFinder)
|
const additionalBytes = await approximateIntroOutroAdditionalSize(video, payload.tasks, filePathFinder)
|
||||||
if (await isAbleToUploadVideo(user.id, additionalBytes) === false) {
|
if (await isAbleToUploadVideo(user.id, additionalBytes) === false) {
|
|
@ -15,11 +15,11 @@ import {
|
||||||
ManageVideoTorrentPayload,
|
ManageVideoTorrentPayload,
|
||||||
MoveObjectStoragePayload,
|
MoveObjectStoragePayload,
|
||||||
RefreshPayload,
|
RefreshPayload,
|
||||||
VideoEditionPayload,
|
|
||||||
VideoFileImportPayload,
|
VideoFileImportPayload,
|
||||||
VideoImportPayload,
|
VideoImportPayload,
|
||||||
VideoLiveEndingPayload,
|
VideoLiveEndingPayload,
|
||||||
VideoRedundancyPayload,
|
VideoRedundancyPayload,
|
||||||
|
VideoStudioEditionPayload,
|
||||||
VideoTranscodingPayload
|
VideoTranscodingPayload
|
||||||
} from '../../../shared/models'
|
} from '../../../shared/models'
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
||||||
|
@ -34,10 +34,10 @@ import { processActorKeys } from './handlers/actor-keys'
|
||||||
import { processEmail } from './handlers/email'
|
import { processEmail } from './handlers/email'
|
||||||
import { processManageVideoTorrent } from './handlers/manage-video-torrent'
|
import { processManageVideoTorrent } from './handlers/manage-video-torrent'
|
||||||
import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
|
import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
|
||||||
import { processVideoEdition } from './handlers/video-edition'
|
|
||||||
import { processVideoFileImport } from './handlers/video-file-import'
|
import { processVideoFileImport } from './handlers/video-file-import'
|
||||||
import { processVideoImport } from './handlers/video-import'
|
import { processVideoImport } from './handlers/video-import'
|
||||||
import { processVideoLiveEnding } from './handlers/video-live-ending'
|
import { processVideoLiveEnding } from './handlers/video-live-ending'
|
||||||
|
import { processVideoStudioEdition } from './handlers/video-studio-edition'
|
||||||
import { processVideoTranscoding } from './handlers/video-transcoding'
|
import { processVideoTranscoding } from './handlers/video-transcoding'
|
||||||
import { processVideosViewsStats } from './handlers/video-views-stats'
|
import { processVideosViewsStats } from './handlers/video-views-stats'
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ type CreateJobArgument =
|
||||||
{ type: 'actor-keys', payload: ActorKeysPayload } |
|
{ type: 'actor-keys', payload: ActorKeysPayload } |
|
||||||
{ type: 'video-redundancy', payload: VideoRedundancyPayload } |
|
{ type: 'video-redundancy', payload: VideoRedundancyPayload } |
|
||||||
{ type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } |
|
{ type: 'delete-resumable-upload-meta-file', payload: DeleteResumableUploadMetaFilePayload } |
|
||||||
{ type: 'video-edition', payload: VideoEditionPayload } |
|
{ type: 'video-studio-edition', payload: VideoStudioEditionPayload } |
|
||||||
{ type: 'manage-video-torrent', payload: ManageVideoTorrentPayload } |
|
{ type: 'manage-video-torrent', payload: ManageVideoTorrentPayload } |
|
||||||
{ type: 'move-to-object-storage', payload: MoveObjectStoragePayload }
|
{ type: 'move-to-object-storage', payload: MoveObjectStoragePayload }
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ const handlers: { [id in JobType]: (job: Job) => Promise<any> } = {
|
||||||
'video-redundancy': processVideoRedundancy,
|
'video-redundancy': processVideoRedundancy,
|
||||||
'move-to-object-storage': processMoveToObjectStorage,
|
'move-to-object-storage': processMoveToObjectStorage,
|
||||||
'manage-video-torrent': processManageVideoTorrent,
|
'manage-video-torrent': processManageVideoTorrent,
|
||||||
'video-edition': processVideoEdition
|
'video-studio-edition': processVideoStudioEdition
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobTypes: JobType[] = [
|
const jobTypes: JobType[] = [
|
||||||
|
@ -103,7 +103,7 @@ const jobTypes: JobType[] = [
|
||||||
'video-live-ending',
|
'video-live-ending',
|
||||||
'move-to-object-storage',
|
'move-to-object-storage',
|
||||||
'manage-video-torrent',
|
'manage-video-torrent',
|
||||||
'video-edition'
|
'video-studio-edition'
|
||||||
]
|
]
|
||||||
|
|
||||||
class JobQueue {
|
class JobQueue {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
AbuseStateChangeForReporter,
|
AbuseStateChangeForReporter,
|
||||||
AutoFollowForInstance,
|
AutoFollowForInstance,
|
||||||
CommentMention,
|
CommentMention,
|
||||||
EditionFinishedForOwner,
|
StudioEditionFinishedForOwner,
|
||||||
FollowForInstance,
|
FollowForInstance,
|
||||||
FollowForUser,
|
FollowForUser,
|
||||||
ImportFinishedForOwner,
|
ImportFinishedForOwner,
|
||||||
|
@ -55,7 +55,7 @@ class Notifier {
|
||||||
newAbuseMessage: [ NewAbuseMessageForReporter, NewAbuseMessageForModerators ],
|
newAbuseMessage: [ NewAbuseMessageForReporter, NewAbuseMessageForModerators ],
|
||||||
newPeertubeVersion: [ NewPeerTubeVersionForAdmins ],
|
newPeertubeVersion: [ NewPeerTubeVersionForAdmins ],
|
||||||
newPluginVersion: [ NewPluginVersionForAdmins ],
|
newPluginVersion: [ NewPluginVersionForAdmins ],
|
||||||
videoEditionFinished: [ EditionFinishedForOwner ]
|
videoStudioEditionFinished: [ StudioEditionFinishedForOwner ]
|
||||||
}
|
}
|
||||||
|
|
||||||
private static instance: Notifier
|
private static instance: Notifier
|
||||||
|
@ -200,11 +200,11 @@ class Notifier {
|
||||||
.catch(err => logger.error('Cannot notify on new plugin version %s.', plugin.name, { err }))
|
.catch(err => logger.error('Cannot notify on new plugin version %s.', plugin.name, { err }))
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyOfFinishedVideoEdition (video: MVideoFullLight) {
|
notifyOfFinishedVideoStudioEdition (video: MVideoFullLight) {
|
||||||
const models = this.notificationModels.videoEditionFinished
|
const models = this.notificationModels.videoStudioEditionFinished
|
||||||
|
|
||||||
this.sendNotifications(models, video)
|
this.sendNotifications(models, video)
|
||||||
.catch(err => logger.error('Cannot notify on finished edition %s.', video.url, { err }))
|
.catch(err => logger.error('Cannot notify on finished studio edition %s.', video.url, { err }))
|
||||||
}
|
}
|
||||||
|
|
||||||
private async notify <T> (object: AbstractNotification<T>) {
|
private async notify <T> (object: AbstractNotification<T>) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export * from './new-video-for-subscribers'
|
export * from './new-video-for-subscribers'
|
||||||
export * from './edition-finished-for-owner'
|
|
||||||
export * from './import-finished-for-owner'
|
export * from './import-finished-for-owner'
|
||||||
export * from './owned-publication-after-auto-unblacklist'
|
export * from './owned-publication-after-auto-unblacklist'
|
||||||
export * from './owned-publication-after-schedule-update'
|
export * from './owned-publication-after-schedule-update'
|
||||||
export * from './owned-publication-after-transcoding'
|
export * from './owned-publication-after-transcoding'
|
||||||
|
export * from './studio-edition-finished-for-owner'
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { MUserDefault, MUserWithNotificationSetting, MVideoFullLight, UserNotifi
|
||||||
import { UserNotificationType } from '@shared/models'
|
import { UserNotificationType } from '@shared/models'
|
||||||
import { AbstractNotification } from '../common/abstract-notification'
|
import { AbstractNotification } from '../common/abstract-notification'
|
||||||
|
|
||||||
export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLight> {
|
export class StudioEditionFinishedForOwner extends AbstractNotification <MVideoFullLight> {
|
||||||
private user: MUserDefault
|
private user: MUserDefault
|
||||||
|
|
||||||
async prepare () {
|
async prepare () {
|
||||||
|
@ -14,11 +14,11 @@ export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLig
|
||||||
}
|
}
|
||||||
|
|
||||||
log () {
|
log () {
|
||||||
logger.info('Notifying user %s its video edition %s is finished.', this.user.username, this.payload.url)
|
logger.info('Notifying user %s its video studio edition %s is finished.', this.user.username, this.payload.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSetting (user: MUserWithNotificationSetting) {
|
getSetting (user: MUserWithNotificationSetting) {
|
||||||
return user.NotificationSetting.myVideoEditionFinished
|
return user.NotificationSetting.myVideoStudioEditionFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetUsers () {
|
getTargetUsers () {
|
||||||
|
@ -29,7 +29,7 @@ export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLig
|
||||||
|
|
||||||
async createNotification (user: MUserWithNotificationSetting) {
|
async createNotification (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.MY_VIDEO_EDITION_FINISHED,
|
type: UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
videoId: this.payload.id
|
videoId: this.payload.id
|
||||||
})
|
})
|
|
@ -159,8 +159,8 @@ class ServerConfigManager {
|
||||||
port: CONFIG.LIVE.RTMP.PORT
|
port: CONFIG.LIVE.RTMP.PORT
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: CONFIG.VIDEO_EDITOR.ENABLED
|
enabled: CONFIG.VIDEO_STUDIO.ENABLED
|
||||||
},
|
},
|
||||||
import: {
|
import: {
|
||||||
videos: {
|
videos: {
|
||||||
|
|
|
@ -253,7 +253,7 @@ function createDefaultUserNotificationSettings (user: MUserId, t: Transaction |
|
||||||
autoInstanceFollowing: UserNotificationSettingValue.WEB,
|
autoInstanceFollowing: UserNotificationSettingValue.WEB,
|
||||||
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
||||||
newPluginVersion: UserNotificationSettingValue.WEB,
|
newPluginVersion: UserNotificationSettingValue.WEB,
|
||||||
myVideoEditionFinished: UserNotificationSettingValue.WEB
|
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB
|
||||||
}
|
}
|
||||||
|
|
||||||
return UserNotificationSettingModel.create(values, { transaction: t })
|
return UserNotificationSettingModel.create(values, { transaction: t })
|
||||||
|
|
|
@ -135,7 +135,7 @@ async function moveToPublishedState (options: {
|
||||||
await federateVideoIfNeeded(video, isNewVideo, transaction)
|
await federateVideoIfNeeded(video, isNewVideo, transaction)
|
||||||
|
|
||||||
if (previousState === VideoState.TO_EDIT) {
|
if (previousState === VideoState.TO_EDIT) {
|
||||||
Notifier.Instance.notifyOfFinishedVideoEdition(video)
|
Notifier.Instance.notifyOfFinishedVideoStudioEdition(video)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MVideoFullLight } from "@server/types/models"
|
import { MVideoFullLight } from '@server/types/models'
|
||||||
import { getVideoStreamDuration } from "@shared/extra-utils"
|
import { getVideoStreamDuration } from '@shared/extra-utils'
|
||||||
import { VideoEditorTask } from "@shared/models"
|
import { VideoStudioTask } from '@shared/models'
|
||||||
|
|
||||||
function buildTaskFileFieldname (indice: number, fieldName = 'file') {
|
function buildTaskFileFieldname (indice: number, fieldName = 'file') {
|
||||||
return `tasks[${indice}][options][${fieldName}]`
|
return `tasks[${indice}][options][${fieldName}]`
|
||||||
|
@ -10,7 +10,7 @@ function getTaskFile (files: Express.Multer.File[], indice: number, fieldName =
|
||||||
return files.find(f => f.fieldname === buildTaskFileFieldname(indice, fieldName))
|
return files.find(f => f.fieldname === buildTaskFileFieldname(indice, fieldName))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function approximateIntroOutroAdditionalSize (video: MVideoFullLight, tasks: VideoEditorTask[], fileFinder: (i: number) => string) {
|
async function approximateIntroOutroAdditionalSize (video: MVideoFullLight, tasks: VideoStudioTask[], fileFinder: (i: number) => string) {
|
||||||
let additionalDuration = 0
|
let additionalDuration = 0
|
||||||
|
|
||||||
for (let i = 0; i < tasks.length; i++) {
|
for (let i = 0; i < tasks.length; i++) {
|
|
@ -57,7 +57,7 @@ const customConfigUpdateValidator = [
|
||||||
body('transcoding.webtorrent.enabled').isBoolean().withMessage('Should have a valid webtorrent transcoding enabled boolean'),
|
body('transcoding.webtorrent.enabled').isBoolean().withMessage('Should have a valid webtorrent transcoding enabled boolean'),
|
||||||
body('transcoding.hls.enabled').isBoolean().withMessage('Should have a valid hls transcoding enabled boolean'),
|
body('transcoding.hls.enabled').isBoolean().withMessage('Should have a valid hls transcoding enabled boolean'),
|
||||||
|
|
||||||
body('videoEditor.enabled').isBoolean().withMessage('Should have a valid video editor enabled boolean'),
|
body('videoStudio.enabled').isBoolean().withMessage('Should have a valid video studio enabled boolean'),
|
||||||
|
|
||||||
body('import.videos.concurrency').isInt({ min: 0 }).withMessage('Should have a valid import concurrency number'),
|
body('import.videos.concurrency').isInt({ min: 0 }).withMessage('Should have a valid import concurrency number'),
|
||||||
body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'),
|
body('import.videos.http.enabled').isBoolean().withMessage('Should have a valid import video http enabled boolean'),
|
||||||
|
@ -106,7 +106,7 @@ const customConfigUpdateValidator = [
|
||||||
if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
|
if (!checkInvalidConfigIfEmailDisabled(req.body, res)) return
|
||||||
if (!checkInvalidTranscodingConfig(req.body, res)) return
|
if (!checkInvalidTranscodingConfig(req.body, res)) return
|
||||||
if (!checkInvalidLiveConfig(req.body, res)) return
|
if (!checkInvalidLiveConfig(req.body, res)) return
|
||||||
if (!checkInvalidVideoEditorConfig(req.body, res)) return
|
if (!checkInvalidVideoStudioConfig(req.body, res)) return
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
@ -163,11 +163,11 @@ function checkInvalidLiveConfig (customConfig: CustomConfig, res: express.Respon
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInvalidVideoEditorConfig (customConfig: CustomConfig, res: express.Response) {
|
function checkInvalidVideoStudioConfig (customConfig: CustomConfig, res: express.Response) {
|
||||||
if (customConfig.videoEditor.enabled === false) return true
|
if (customConfig.videoStudio.enabled === false) return true
|
||||||
|
|
||||||
if (customConfig.videoEditor.enabled === true && customConfig.transcoding.enabled === false) {
|
if (customConfig.videoStudio.enabled === true && customConfig.transcoding.enabled === false) {
|
||||||
res.fail({ message: 'You cannot enable video editor if transcoding is not enabled' })
|
res.fail({ message: 'You cannot enable video studio if transcoding is not enabled' })
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ export * from './video-blacklist'
|
||||||
export * from './video-captions'
|
export * from './video-captions'
|
||||||
export * from './video-channels'
|
export * from './video-channels'
|
||||||
export * from './video-comments'
|
export * from './video-comments'
|
||||||
export * from './video-editor'
|
|
||||||
export * from './video-files'
|
export * from './video-files'
|
||||||
export * from './video-imports'
|
export * from './video-imports'
|
||||||
export * from './video-live'
|
export * from './video-live'
|
||||||
|
@ -10,5 +9,6 @@ export * from './video-ownership-changes'
|
||||||
export * from './video-watch'
|
export * from './video-watch'
|
||||||
export * from './video-rates'
|
export * from './video-rates'
|
||||||
export * from './video-shares'
|
export * from './video-shares'
|
||||||
|
export * from './video-studio'
|
||||||
export * from './video-transcoding'
|
export * from './video-transcoding'
|
||||||
export * from './videos'
|
export * from './videos'
|
||||||
|
|
|
@ -2,31 +2,31 @@ import express from 'express'
|
||||||
import { body, param } from 'express-validator'
|
import { body, param } from 'express-validator'
|
||||||
import { isIdOrUUIDValid } from '@server/helpers/custom-validators/misc'
|
import { isIdOrUUIDValid } from '@server/helpers/custom-validators/misc'
|
||||||
import {
|
import {
|
||||||
isEditorCutTaskValid,
|
isStudioCutTaskValid,
|
||||||
isEditorTaskAddIntroOutroValid,
|
isStudioTaskAddIntroOutroValid,
|
||||||
isEditorTaskAddWatermarkValid,
|
isStudioTaskAddWatermarkValid,
|
||||||
isValidEditorTasksArray
|
isValidStudioTasksArray
|
||||||
} from '@server/helpers/custom-validators/video-editor'
|
} from '@server/helpers/custom-validators/video-studio'
|
||||||
import { cleanUpReqFiles } from '@server/helpers/express-utils'
|
import { cleanUpReqFiles } from '@server/helpers/express-utils'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { approximateIntroOutroAdditionalSize, getTaskFile } from '@server/lib/video-editor'
|
import { approximateIntroOutroAdditionalSize, getTaskFile } from '@server/lib/video-studio'
|
||||||
import { isAudioFile } from '@shared/extra-utils'
|
import { isAudioFile } from '@shared/extra-utils'
|
||||||
import { HttpStatusCode, UserRight, VideoEditorCreateEdition, VideoEditorTask, VideoState } from '@shared/models'
|
import { HttpStatusCode, UserRight, VideoState, VideoStudioCreateEdition, VideoStudioTask } from '@shared/models'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
import { areValidationErrors, checkUserCanManageVideo, checkUserQuota, doesVideoExist } from '../shared'
|
import { areValidationErrors, checkUserCanManageVideo, checkUserQuota, doesVideoExist } from '../shared'
|
||||||
|
|
||||||
const videosEditorAddEditionValidator = [
|
const videoStudioAddEditionValidator = [
|
||||||
param('videoId').custom(isIdOrUUIDValid).withMessage('Should have a valid video id/uuid'),
|
param('videoId').custom(isIdOrUUIDValid).withMessage('Should have a valid video id/uuid'),
|
||||||
|
|
||||||
body('tasks').custom(isValidEditorTasksArray).withMessage('Should have a valid array of tasks'),
|
body('tasks').custom(isValidStudioTasksArray).withMessage('Should have a valid array of tasks'),
|
||||||
|
|
||||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking videosEditorAddEditionValidator parameters.', { parameters: req.params, body: req.body, files: req.files })
|
logger.debug('Checking videoStudioAddEditionValidator parameters.', { parameters: req.params, body: req.body, files: req.files })
|
||||||
|
|
||||||
if (CONFIG.VIDEO_EDITOR.ENABLED !== true) {
|
if (CONFIG.VIDEO_STUDIO.ENABLED !== true) {
|
||||||
res.fail({
|
res.fail({
|
||||||
status: HttpStatusCode.BAD_REQUEST_400,
|
status: HttpStatusCode.BAD_REQUEST_400,
|
||||||
message: 'Video editor is disabled on this instance'
|
message: 'Video studio is disabled on this instance'
|
||||||
})
|
})
|
||||||
|
|
||||||
return cleanUpReqFiles(req)
|
return cleanUpReqFiles(req)
|
||||||
|
@ -34,7 +34,7 @@ const videosEditorAddEditionValidator = [
|
||||||
|
|
||||||
if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
|
if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
|
||||||
|
|
||||||
const body: VideoEditorCreateEdition = req.body
|
const body: VideoStudioCreateEdition = req.body
|
||||||
const files = req.files as Express.Multer.File[]
|
const files = req.files as Express.Multer.File[]
|
||||||
|
|
||||||
for (let i = 0; i < body.tasks.length; i++) {
|
for (let i = 0; i < body.tasks.length; i++) {
|
||||||
|
@ -90,21 +90,21 @@ const videosEditorAddEditionValidator = [
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
videosEditorAddEditionValidator
|
videoStudioAddEditionValidator
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const taskCheckers: {
|
const taskCheckers: {
|
||||||
[id in VideoEditorTask['name']]: (task: VideoEditorTask, indice?: number, files?: Express.Multer.File[]) => boolean
|
[id in VideoStudioTask['name']]: (task: VideoStudioTask, indice?: number, files?: Express.Multer.File[]) => boolean
|
||||||
} = {
|
} = {
|
||||||
'cut': isEditorCutTaskValid,
|
'cut': isStudioCutTaskValid,
|
||||||
'add-intro': isEditorTaskAddIntroOutroValid,
|
'add-intro': isStudioTaskAddIntroOutroValid,
|
||||||
'add-outro': isEditorTaskAddIntroOutroValid,
|
'add-outro': isStudioTaskAddIntroOutroValid,
|
||||||
'add-watermark': isEditorTaskAddWatermarkValid
|
'add-watermark': isStudioTaskAddWatermarkValid
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkTask (req: express.Request, task: VideoEditorTask, indice?: number) {
|
function checkTask (req: express.Request, task: VideoStudioTask, indice?: number) {
|
||||||
const checker = taskCheckers[task.name]
|
const checker = taskCheckers[task.name]
|
||||||
if (!checker) return false
|
if (!checker) return false
|
||||||
|
|
|
@ -178,11 +178,11 @@ export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<U
|
||||||
@AllowNull(false)
|
@AllowNull(false)
|
||||||
@Default(null)
|
@Default(null)
|
||||||
@Is(
|
@Is(
|
||||||
'UserNotificationSettingMyVideoEditionFinished',
|
'UserNotificationSettingMyVideoStudioEditionFinished',
|
||||||
value => throwIfNotValid(value, isUserNotificationSettingValid, 'myVideoEditionFinished')
|
value => throwIfNotValid(value, isUserNotificationSettingValid, 'myVideoStudioEditionFinished')
|
||||||
)
|
)
|
||||||
@Column
|
@Column
|
||||||
myVideoEditionFinished: UserNotificationSettingValue
|
myVideoStudioEditionFinished: UserNotificationSettingValue
|
||||||
|
|
||||||
@ForeignKey(() => UserModel)
|
@ForeignKey(() => UserModel)
|
||||||
@Column
|
@Column
|
||||||
|
@ -225,7 +225,7 @@ export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<U
|
||||||
abuseNewMessage: this.abuseNewMessage,
|
abuseNewMessage: this.abuseNewMessage,
|
||||||
abuseStateChange: this.abuseStateChange,
|
abuseStateChange: this.abuseStateChange,
|
||||||
newPeerTubeVersion: this.newPeerTubeVersion,
|
newPeerTubeVersion: this.newPeerTubeVersion,
|
||||||
myVideoEditionFinished: this.myVideoEditionFinished,
|
myVideoStudioEditionFinished: this.myVideoStudioEditionFinished,
|
||||||
newPluginVersion: this.newPluginVersion
|
newPluginVersion: this.newPluginVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ describe('Test config API validators', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
import: {
|
import: {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import './video-blacklist'
|
||||||
import './video-captions'
|
import './video-captions'
|
||||||
import './video-channels'
|
import './video-channels'
|
||||||
import './video-comments'
|
import './video-comments'
|
||||||
import './video-editor'
|
import './video-studio'
|
||||||
import './video-imports'
|
import './video-imports'
|
||||||
import './video-playlists'
|
import './video-playlists'
|
||||||
import './videos'
|
import './videos'
|
||||||
|
|
|
@ -171,7 +171,7 @@ describe('Test user notifications API validators', function () {
|
||||||
abuseNewMessage: UserNotificationSettingValue.WEB,
|
abuseNewMessage: UserNotificationSettingValue.WEB,
|
||||||
abuseStateChange: UserNotificationSettingValue.WEB,
|
abuseStateChange: UserNotificationSettingValue.WEB,
|
||||||
newPeerTubeVersion: UserNotificationSettingValue.WEB,
|
newPeerTubeVersion: UserNotificationSettingValue.WEB,
|
||||||
myVideoEditionFinished: UserNotificationSettingValue.WEB,
|
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB,
|
||||||
newPluginVersion: UserNotificationSettingValue.WEB
|
newPluginVersion: UserNotificationSettingValue.WEB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import { HttpStatusCode, VideoEditorTask } from '@shared/models'
|
import { HttpStatusCode, VideoStudioTask } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createSingleServer,
|
createSingleServer,
|
||||||
PeerTubeServer,
|
PeerTubeServer,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
VideoEditorCommand,
|
VideoStudioCommand,
|
||||||
waitJobs
|
waitJobs
|
||||||
} from '@shared/server-commands'
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Test video editor API validator', function () {
|
describe('Test video studio API validator', function () {
|
||||||
let server: PeerTubeServer
|
let server: PeerTubeServer
|
||||||
let command: VideoEditorCommand
|
let command: VideoStudioCommand
|
||||||
let userAccessToken: string
|
let userAccessToken: string
|
||||||
let videoUUID: string
|
let videoUUID: string
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ describe('Test video editor API validator', function () {
|
||||||
const { uuid } = await server.videos.quickUpload({ name: 'video' })
|
const { uuid } = await server.videos.quickUpload({ name: 'video' })
|
||||||
videoUUID = uuid
|
videoUUID = uuid
|
||||||
|
|
||||||
command = server.videoEditor
|
command = server.videoStudio
|
||||||
|
|
||||||
await waitJobs([ server ])
|
await waitJobs([ server ])
|
||||||
})
|
})
|
||||||
|
@ -41,10 +41,10 @@ describe('Test video editor API validator', function () {
|
||||||
|
|
||||||
describe('Config settings', function () {
|
describe('Config settings', function () {
|
||||||
|
|
||||||
it('Should fail if editor is disabled', async function () {
|
it('Should fail if studio is disabled', async function () {
|
||||||
await server.config.updateExistingSubConfig({
|
await server.config.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,15 +52,15 @@ describe('Test video editor API validator', function () {
|
||||||
|
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to enable editor if transcoding is disabled', async function () {
|
it('Should fail to enable studio if transcoding is disabled', async function () {
|
||||||
await server.config.updateExistingSubConfig({
|
await server.config.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
transcoding: {
|
transcoding: {
|
||||||
|
@ -71,10 +71,10 @@ describe('Test video editor API validator', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed to enable video editor', async function () {
|
it('Should succeed to enable video studio', async function () {
|
||||||
await server.config.updateExistingSubConfig({
|
await server.config.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
transcoding: {
|
transcoding: {
|
||||||
|
@ -91,7 +91,7 @@ describe('Test video editor API validator', function () {
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
token: null,
|
token: null,
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
|
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -100,7 +100,7 @@ describe('Test video editor API validator', function () {
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
token: userAccessToken,
|
token: userAccessToken,
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -108,7 +108,7 @@ describe('Test video editor API validator', function () {
|
||||||
it('Should fail with an invalid video', async function () {
|
it('Should fail with an invalid video', async function () {
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: 'tintin',
|
videoId: 'tintin',
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -116,7 +116,7 @@ describe('Test video editor API validator', function () {
|
||||||
it('Should fail with an unknown video', async function () {
|
it('Should fail with an unknown video', async function () {
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: 42,
|
videoId: 42,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.NOT_FOUND_404
|
expectedStatus: HttpStatusCode.NOT_FOUND_404
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -132,7 +132,7 @@ describe('Test video editor API validator', function () {
|
||||||
|
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: uuid,
|
videoId: uuid,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
expectedStatus: HttpStatusCode.CONFLICT_409
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ describe('Test video editor API validator', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with too many tasks', async function () {
|
it('Should fail with too many tasks', async function () {
|
||||||
const tasks: VideoEditorTask[] = []
|
const tasks: VideoStudioTask[] = []
|
||||||
|
|
||||||
for (let i = 0; i < 110; i++) {
|
for (let i = 0; i < 110; i++) {
|
||||||
tasks.push({
|
tasks.push({
|
||||||
|
@ -194,7 +194,7 @@ describe('Test video editor API validator', function () {
|
||||||
|
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
expectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -204,7 +204,7 @@ describe('Test video editor API validator', function () {
|
||||||
|
|
||||||
await command.createEditionTasks({
|
await command.createEditionTasks({
|
||||||
videoId: videoUUID,
|
videoId: videoUUID,
|
||||||
tasks: VideoEditorCommand.getComplexTask(),
|
tasks: VideoStudioCommand.getComplexTask(),
|
||||||
expectedStatus: HttpStatusCode.CONFLICT_409
|
expectedStatus: HttpStatusCode.CONFLICT_409
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
checkMyVideoImportIsFinished,
|
checkMyVideoImportIsFinished,
|
||||||
checkNewActorFollow,
|
checkNewActorFollow,
|
||||||
checkNewVideoFromSubscription,
|
checkNewVideoFromSubscription,
|
||||||
checkVideoEditionIsFinished,
|
checkVideoStudioEditionIsFinished,
|
||||||
checkVideoIsPublished,
|
checkVideoIsPublished,
|
||||||
FIXTURE_URLS,
|
FIXTURE_URLS,
|
||||||
MockSmtpServer,
|
MockSmtpServer,
|
||||||
|
@ -16,7 +16,7 @@ import {
|
||||||
} from '@server/tests/shared'
|
} from '@server/tests/shared'
|
||||||
import { wait } from '@shared/core-utils'
|
import { wait } from '@shared/core-utils'
|
||||||
import { buildUUID } from '@shared/extra-utils'
|
import { buildUUID } from '@shared/extra-utils'
|
||||||
import { UserNotification, UserNotificationType, VideoEditorTask, VideoPrivacy } from '@shared/models'
|
import { UserNotification, UserNotificationType, VideoStudioTask, VideoPrivacy } from '@shared/models'
|
||||||
import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
|
import { cleanupTests, PeerTubeServer, waitJobs } from '@shared/server-commands'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@ -323,7 +323,7 @@ describe('Test user notifications', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Video editor', function () {
|
describe('Video studio', function () {
|
||||||
let baseParams: CheckerBaseParams
|
let baseParams: CheckerBaseParams
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
|
@ -335,7 +335,7 @@ describe('Test user notifications', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should send a notification after editor edition', async function () {
|
it('Should send a notification after studio edition', async function () {
|
||||||
this.timeout(240000)
|
this.timeout(240000)
|
||||||
|
|
||||||
const { name, shortUUID, id } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
|
const { name, shortUUID, id } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
|
||||||
|
@ -343,7 +343,7 @@ describe('Test user notifications', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
|
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
|
||||||
|
|
||||||
const tasks: VideoEditorTask[] = [
|
const tasks: VideoStudioTask[] = [
|
||||||
{
|
{
|
||||||
name: 'cut',
|
name: 'cut',
|
||||||
options: {
|
options: {
|
||||||
|
@ -352,10 +352,10 @@ describe('Test user notifications', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
await servers[1].videoEditor.createEditionTasks({ videoId: id, tasks })
|
await servers[1].videoStudio.createEditionTasks({ videoId: id, tasks })
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideoEditionIsFinished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
|
await checkVideoStudioEditionIsFinished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
|
||||||
expect(data.live.transcoding.resolutions['1440p']).to.be.false
|
expect(data.live.transcoding.resolutions['1440p']).to.be.false
|
||||||
expect(data.live.transcoding.resolutions['2160p']).to.be.false
|
expect(data.live.transcoding.resolutions['2160p']).to.be.false
|
||||||
|
|
||||||
expect(data.videoEditor.enabled).to.be.false
|
expect(data.videoStudio.enabled).to.be.false
|
||||||
|
|
||||||
expect(data.import.videos.concurrency).to.equal(2)
|
expect(data.import.videos.concurrency).to.equal(2)
|
||||||
expect(data.import.videos.http.enabled).to.be.true
|
expect(data.import.videos.http.enabled).to.be.true
|
||||||
|
@ -201,7 +201,7 @@ function checkUpdatedConfig (data: CustomConfig) {
|
||||||
expect(data.live.transcoding.resolutions['1080p']).to.be.true
|
expect(data.live.transcoding.resolutions['1080p']).to.be.true
|
||||||
expect(data.live.transcoding.resolutions['2160p']).to.be.true
|
expect(data.live.transcoding.resolutions['2160p']).to.be.true
|
||||||
|
|
||||||
expect(data.videoEditor.enabled).to.be.true
|
expect(data.videoStudio.enabled).to.be.true
|
||||||
|
|
||||||
expect(data.import.videos.concurrency).to.equal(4)
|
expect(data.import.videos.concurrency).to.equal(4)
|
||||||
expect(data.import.videos.http.enabled).to.be.false
|
expect(data.import.videos.http.enabled).to.be.false
|
||||||
|
@ -350,7 +350,7 @@ const newCustomConfig: CustomConfig = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
import: {
|
import: {
|
||||||
|
|
|
@ -2,4 +2,4 @@ export * from './audio-only'
|
||||||
export * from './create-transcoding'
|
export * from './create-transcoding'
|
||||||
export * from './hls'
|
export * from './hls'
|
||||||
export * from './transcoder'
|
export * from './transcoder'
|
||||||
export * from './video-editor'
|
export * from './video-studio'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { expectStartWith, getAllFiles } from '@server/tests/shared'
|
import { expectStartWith, getAllFiles } from '@server/tests/shared'
|
||||||
import { areObjectStorageTestsDisabled } from '@shared/core-utils'
|
import { areObjectStorageTestsDisabled } from '@shared/core-utils'
|
||||||
import { VideoEditorTask } from '@shared/models'
|
import { VideoStudioTask } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createMultipleServers,
|
createMultipleServers,
|
||||||
|
@ -10,11 +10,11 @@ import {
|
||||||
PeerTubeServer,
|
PeerTubeServer,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
VideoEditorCommand,
|
VideoStudioCommand,
|
||||||
waitJobs
|
waitJobs
|
||||||
} from '@shared/server-commands'
|
} from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Test video editor', function () {
|
describe('Test video studio', function () {
|
||||||
let servers: PeerTubeServer[] = []
|
let servers: PeerTubeServer[] = []
|
||||||
let videoUUID: string
|
let videoUUID: string
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ describe('Test video editor', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTasks (tasks: VideoEditorTask[]) {
|
async function createTasks (tasks: VideoStudioTask[]) {
|
||||||
await servers[0].videoEditor.createEditionTasks({ videoId: videoUUID, tasks })
|
await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks })
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ describe('Test video editor', function () {
|
||||||
|
|
||||||
await servers[0].config.enableMinimumTranscoding()
|
await servers[0].config.enableMinimumTranscoding()
|
||||||
|
|
||||||
await servers[0].config.enableEditor()
|
await servers[0].config.enableStudio()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Cutting', function () {
|
describe('Cutting', function () {
|
||||||
|
@ -276,7 +276,7 @@ describe('Test video editor', function () {
|
||||||
this.timeout(240_000)
|
this.timeout(240_000)
|
||||||
await renewVideo()
|
await renewVideo()
|
||||||
|
|
||||||
await createTasks(VideoEditorCommand.getComplexTask())
|
await createTasks(VideoStudioCommand.getComplexTask())
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await checkDuration(server, 9)
|
await checkDuration(server, 9)
|
||||||
|
@ -303,7 +303,7 @@ describe('Test video editor', function () {
|
||||||
this.timeout(240_000)
|
this.timeout(240_000)
|
||||||
await renewVideo()
|
await renewVideo()
|
||||||
|
|
||||||
await createTasks(VideoEditorCommand.getComplexTask())
|
await createTasks(VideoStudioCommand.getComplexTask())
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
const video = await server.videos.get({ id: videoUUID })
|
const video = await server.videos.get({ id: videoUUID })
|
||||||
|
@ -333,7 +333,7 @@ describe('Test video editor', function () {
|
||||||
const video = await servers[0].videos.get({ id: videoUUID })
|
const video = await servers[0].videos.get({ id: videoUUID })
|
||||||
const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
|
const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
|
||||||
|
|
||||||
await createTasks(VideoEditorCommand.getComplexTask())
|
await createTasks(VideoStudioCommand.getComplexTask())
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
const video = await server.videos.get({ id: videoUUID })
|
const video = await server.videos.get({ id: videoUUID })
|
|
@ -47,7 +47,7 @@ function getAllNotificationsSettings (): UserNotificationSetting {
|
||||||
abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
||||||
autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
||||||
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
||||||
myVideoEditionFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
|
||||||
newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
|
newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,13 +110,13 @@ async function checkVideoIsPublished (options: CheckerBaseParams & {
|
||||||
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkVideoEditionIsFinished (options: CheckerBaseParams & {
|
async function checkVideoStudioEditionIsFinished (options: CheckerBaseParams & {
|
||||||
videoName: string
|
videoName: string
|
||||||
shortUUID: string
|
shortUUID: string
|
||||||
checkType: CheckerType
|
checkType: CheckerType
|
||||||
}) {
|
}) {
|
||||||
const { videoName, shortUUID } = options
|
const { videoName, shortUUID } = options
|
||||||
const notificationType = UserNotificationType.MY_VIDEO_EDITION_FINISHED
|
const notificationType = UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED
|
||||||
|
|
||||||
function notificationChecker (notification: UserNotification, checkType: CheckerType) {
|
function notificationChecker (notification: UserNotification, checkType: CheckerType) {
|
||||||
if (checkType === 'presence') {
|
if (checkType === 'presence') {
|
||||||
|
@ -685,7 +685,7 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
|
||||||
await setDefaultChannelAvatar(servers)
|
await setDefaultChannelAvatar(servers)
|
||||||
await setDefaultAccountAvatar(servers)
|
await setDefaultAccountAvatar(servers)
|
||||||
|
|
||||||
await servers[1].config.enableEditor()
|
await servers[1].config.enableStudio()
|
||||||
|
|
||||||
if (serversCount > 1) {
|
if (serversCount > 1) {
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
@ -756,7 +756,7 @@ export {
|
||||||
checkNewAccountAbuseForModerators,
|
checkNewAccountAbuseForModerators,
|
||||||
checkNewPeerTubeVersion,
|
checkNewPeerTubeVersion,
|
||||||
checkNewPluginVersion,
|
checkNewPluginVersion,
|
||||||
checkVideoEditionIsFinished
|
checkVideoStudioEditionIsFinished
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -147,7 +147,7 @@ export interface CustomConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ContextType } from '../activitypub/context'
|
import { ContextType } from '../activitypub/context'
|
||||||
import { VideoState } from '../videos'
|
import { VideoState } from '../videos'
|
||||||
import { VideoEditorTaskCut } from '../videos/editor'
|
import { VideoStudioTaskCut } from '../videos/studio'
|
||||||
import { VideoResolution } from '../videos/file/video-resolution.enum'
|
import { VideoResolution } from '../videos/file/video-resolution.enum'
|
||||||
import { SendEmailOptions } from './emailer.model'
|
import { SendEmailOptions } from './emailer.model'
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export type JobType =
|
||||||
| 'actor-keys'
|
| 'actor-keys'
|
||||||
| 'manage-video-torrent'
|
| 'manage-video-torrent'
|
||||||
| 'move-to-object-storage'
|
| 'move-to-object-storage'
|
||||||
| 'video-edition'
|
| 'video-studio-edition'
|
||||||
|
|
||||||
export interface Job {
|
export interface Job {
|
||||||
id: number
|
id: number
|
||||||
|
@ -117,9 +117,6 @@ export type ManageVideoTorrentPayload =
|
||||||
interface BaseTranscodingPayload {
|
interface BaseTranscodingPayload {
|
||||||
videoUUID: string
|
videoUUID: string
|
||||||
isNewVideo?: boolean
|
isNewVideo?: boolean
|
||||||
|
|
||||||
// Custom notification when the task is finished
|
|
||||||
notification?: 'default' | 'video-edition'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HLSTranscodingPayload extends BaseTranscodingPayload {
|
export interface HLSTranscodingPayload extends BaseTranscodingPayload {
|
||||||
|
@ -178,9 +175,9 @@ export interface MoveObjectStoragePayload {
|
||||||
previousVideoState: VideoState
|
previousVideoState: VideoState
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VideoEditorTaskCutPayload = VideoEditorTaskCut
|
export type VideoStudioTaskCutPayload = VideoStudioTaskCut
|
||||||
|
|
||||||
export type VideoEditorTaskIntroPayload = {
|
export type VideoStudioTaskIntroPayload = {
|
||||||
name: 'add-intro'
|
name: 'add-intro'
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
|
@ -188,7 +185,7 @@ export type VideoEditorTaskIntroPayload = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VideoEditorTaskOutroPayload = {
|
export type VideoStudioTaskOutroPayload = {
|
||||||
name: 'add-outro'
|
name: 'add-outro'
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
|
@ -196,7 +193,7 @@ export type VideoEditorTaskOutroPayload = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VideoEditorTaskWatermarkPayload = {
|
export type VideoStudioTaskWatermarkPayload = {
|
||||||
name: 'add-watermark'
|
name: 'add-watermark'
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
|
@ -204,13 +201,13 @@ export type VideoEditorTaskWatermarkPayload = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VideoEditionTaskPayload =
|
export type VideoStudioTaskPayload =
|
||||||
VideoEditorTaskCutPayload |
|
VideoStudioTaskCutPayload |
|
||||||
VideoEditorTaskIntroPayload |
|
VideoStudioTaskIntroPayload |
|
||||||
VideoEditorTaskOutroPayload |
|
VideoStudioTaskOutroPayload |
|
||||||
VideoEditorTaskWatermarkPayload
|
VideoStudioTaskWatermarkPayload
|
||||||
|
|
||||||
export interface VideoEditionPayload {
|
export interface VideoStudioEditionPayload {
|
||||||
videoUUID: string
|
videoUUID: string
|
||||||
tasks: VideoEditionTaskPayload[]
|
tasks: VideoStudioTaskPayload[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ export interface ServerConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,5 +28,5 @@ export interface UserNotificationSetting {
|
||||||
newPeerTubeVersion: UserNotificationSettingValue
|
newPeerTubeVersion: UserNotificationSettingValue
|
||||||
newPluginVersion: UserNotificationSettingValue
|
newPluginVersion: UserNotificationSettingValue
|
||||||
|
|
||||||
myVideoEditionFinished: UserNotificationSettingValue
|
myVideoStudioEditionFinished: UserNotificationSettingValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const enum UserNotificationType {
|
||||||
NEW_PLUGIN_VERSION = 17,
|
NEW_PLUGIN_VERSION = 17,
|
||||||
NEW_PEERTUBE_VERSION = 18,
|
NEW_PEERTUBE_VERSION = 18,
|
||||||
|
|
||||||
MY_VIDEO_EDITION_FINISHED = 19
|
MY_VIDEO_STUDIO_EDITION_FINISHED = 19
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoInfo {
|
export interface VideoInfo {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './video-editor-create-edit.model'
|
|
|
@ -1,42 +0,0 @@
|
||||||
export interface VideoEditorCreateEdition {
|
|
||||||
tasks: VideoEditorTask[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type VideoEditorTask =
|
|
||||||
VideoEditorTaskCut |
|
|
||||||
VideoEditorTaskIntro |
|
|
||||||
VideoEditorTaskOutro |
|
|
||||||
VideoEditorTaskWatermark
|
|
||||||
|
|
||||||
export interface VideoEditorTaskCut {
|
|
||||||
name: 'cut'
|
|
||||||
|
|
||||||
options: {
|
|
||||||
start?: number
|
|
||||||
end?: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VideoEditorTaskIntro {
|
|
||||||
name: 'add-intro'
|
|
||||||
|
|
||||||
options: {
|
|
||||||
file: Blob | string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VideoEditorTaskOutro {
|
|
||||||
name: 'add-outro'
|
|
||||||
|
|
||||||
options: {
|
|
||||||
file: Blob | string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VideoEditorTaskWatermark {
|
|
||||||
name: 'add-watermark'
|
|
||||||
|
|
||||||
options: {
|
|
||||||
file: Blob | string
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ export * from './caption'
|
||||||
export * from './change-ownership'
|
export * from './change-ownership'
|
||||||
export * from './channel'
|
export * from './channel'
|
||||||
export * from './comment'
|
export * from './comment'
|
||||||
export * from './editor'
|
export * from './studio'
|
||||||
export * from './live'
|
export * from './live'
|
||||||
export * from './file'
|
export * from './file'
|
||||||
export * from './import'
|
export * from './import'
|
||||||
|
|
1
shared/models/videos/studio/index.ts
Normal file
1
shared/models/videos/studio/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './video-studio-create-edit.model'
|
|
@ -0,0 +1,42 @@
|
||||||
|
export interface VideoStudioCreateEdition {
|
||||||
|
tasks: VideoStudioTask[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VideoStudioTask =
|
||||||
|
VideoStudioTaskCut |
|
||||||
|
VideoStudioTaskIntro |
|
||||||
|
VideoStudioTaskOutro |
|
||||||
|
VideoStudioTaskWatermark
|
||||||
|
|
||||||
|
export interface VideoStudioTaskCut {
|
||||||
|
name: 'cut'
|
||||||
|
|
||||||
|
options: {
|
||||||
|
start?: number
|
||||||
|
end?: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoStudioTaskIntro {
|
||||||
|
name: 'add-intro'
|
||||||
|
|
||||||
|
options: {
|
||||||
|
file: Blob | string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoStudioTaskOutro {
|
||||||
|
name: 'add-outro'
|
||||||
|
|
||||||
|
options: {
|
||||||
|
file: Blob | string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VideoStudioTaskWatermark {
|
||||||
|
name: 'add-watermark'
|
||||||
|
|
||||||
|
options: {
|
||||||
|
file: Blob | string
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,7 +60,7 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
transcoding: {
|
transcoding: {
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,10 +111,10 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
enableEditor () {
|
enableStudio () {
|
||||||
return this.updateExistingSubConfig({
|
return this.updateExistingSubConfig({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ export class ConfigCommand extends AbstractCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoEditor: {
|
videoStudio: {
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
import: {
|
import: {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
PlaylistsCommand,
|
PlaylistsCommand,
|
||||||
ServicesCommand,
|
ServicesCommand,
|
||||||
StreamingPlaylistsCommand,
|
StreamingPlaylistsCommand,
|
||||||
VideoEditorCommand,
|
VideoStudioCommand,
|
||||||
VideosCommand
|
VideosCommand
|
||||||
} from '../videos'
|
} from '../videos'
|
||||||
import { CommentsCommand } from '../videos/comments-command'
|
import { CommentsCommand } from '../videos/comments-command'
|
||||||
|
@ -125,7 +125,7 @@ export class PeerTubeServer {
|
||||||
login?: LoginCommand
|
login?: LoginCommand
|
||||||
users?: UsersCommand
|
users?: UsersCommand
|
||||||
objectStorage?: ObjectStorageCommand
|
objectStorage?: ObjectStorageCommand
|
||||||
videoEditor?: VideoEditorCommand
|
videoStudio?: VideoStudioCommand
|
||||||
videos?: VideosCommand
|
videos?: VideosCommand
|
||||||
|
|
||||||
constructor (options: { serverNumber: number } | { url: string }) {
|
constructor (options: { serverNumber: number } | { url: string }) {
|
||||||
|
@ -396,6 +396,6 @@ export class PeerTubeServer {
|
||||||
this.users = new UsersCommand(this)
|
this.users = new UsersCommand(this)
|
||||||
this.videos = new VideosCommand(this)
|
this.videos = new VideosCommand(this)
|
||||||
this.objectStorage = new ObjectStorageCommand(this)
|
this.objectStorage = new ObjectStorageCommand(this)
|
||||||
this.videoEditor = new VideoEditorCommand(this)
|
this.videoStudio = new VideoStudioCommand(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ export * from './playlists-command'
|
||||||
export * from './services-command'
|
export * from './services-command'
|
||||||
export * from './streaming-playlists-command'
|
export * from './streaming-playlists-command'
|
||||||
export * from './comments-command'
|
export * from './comments-command'
|
||||||
export * from './video-editor-command'
|
export * from './video-studio-command'
|
||||||
export * from './videos-command'
|
export * from './videos-command'
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { HttpStatusCode, VideoEditorTask } from '@shared/models'
|
import { HttpStatusCode, VideoStudioTask } from '@shared/models'
|
||||||
import { AbstractCommand, OverrideCommandOptions } from '../shared'
|
import { AbstractCommand, OverrideCommandOptions } from '../shared'
|
||||||
|
|
||||||
export class VideoEditorCommand extends AbstractCommand {
|
export class VideoStudioCommand extends AbstractCommand {
|
||||||
|
|
||||||
static getComplexTask (): VideoEditorTask[] {
|
static getComplexTask (): VideoStudioTask[] {
|
||||||
return [
|
return [
|
||||||
// Total duration: 2
|
// Total duration: 2
|
||||||
{
|
{
|
||||||
|
@ -41,9 +41,9 @@ export class VideoEditorCommand extends AbstractCommand {
|
||||||
|
|
||||||
createEditionTasks (options: OverrideCommandOptions & {
|
createEditionTasks (options: OverrideCommandOptions & {
|
||||||
videoId: number | string
|
videoId: number | string
|
||||||
tasks: VideoEditorTask[]
|
tasks: VideoStudioTask[]
|
||||||
}) {
|
}) {
|
||||||
const path = '/api/v1/videos/' + options.videoId + '/editor/edit'
|
const path = '/api/v1/videos/' + options.videoId + '/studio/edit'
|
||||||
const attaches: { [id: string]: any } = {}
|
const attaches: { [id: string]: any } = {}
|
||||||
|
|
||||||
for (let i = 0; i < options.tasks.length; i++) {
|
for (let i = 0; i < options.tasks.length; i++) {
|
|
@ -85,7 +85,7 @@ server {
|
||||||
try_files /dev/null @api;
|
try_files /dev/null @api;
|
||||||
}
|
}
|
||||||
|
|
||||||
location ~ ^/api/v1/videos/(upload|([^/]+/editor/edit))$ {
|
location ~ ^/api/v1/videos/(upload|([^/]+/studio/edit))$ {
|
||||||
limit_except POST HEAD { deny all; }
|
limit_except POST HEAD { deny all; }
|
||||||
|
|
||||||
# This is the maximum upload size, which roughly matches the maximum size of a video file.
|
# This is the maximum upload size, which roughly matches the maximum size of a video file.
|
||||||
|
|
Loading…
Add table
Reference in a new issue