Rename studio to editor

This commit is contained in:
Chocobozzz 2022-03-22 16:58:49 +01:00
parent 1808a1f8e4
commit 92e66e04f7
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
81 changed files with 368 additions and 370 deletions

View File

@ -200,7 +200,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
resolutions: {}
}
},
videoEditor: {
videoStudio: {
enabled: null
},
autoBlacklist: {

View File

@ -193,9 +193,9 @@
</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 i18n class="inner-form-title">VIDEO EDITOR</div>
<div i18n class="inner-form-title">VIDEO STUDIO</div>
<div i18n class="inner-form-description">
Allows your users to edit their video (cut, add intro/outro, add a watermark etc)
</div>
@ -203,14 +203,14 @@
<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()">
<my-peertube-checkbox
inputName="videoEditorEnabled" formControlName="enabled"
i18n-labelText labelText="Enable video editor"
inputName="videoStudioEnabled" formControlName="enabled"
i18n-labelText labelText="Enable video studio"
>
<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>
</my-peertube-checkbox>
</div>

View File

@ -72,7 +72,7 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
private checkTranscodingFields () {
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 webtorrentControl = this.form.get('transcoding.webtorrent.enabled')
@ -101,7 +101,7 @@ export class EditVODTranscodingComponent implements OnInit, OnChanges {
transcodingControl.valueChanges
.subscribe(newValue => {
if (newValue === false) {
videoEditorControl.setValue(false)
videoStudioControl.setValue(false)
}
})
}

View File

@ -45,7 +45,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
abuseStateChange: $localize`One of your abuse reports has been accepted or rejected by moderators`,
newPeerTubeVersion: $localize`A new PeerTube version is available`,
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 = [
{
@ -64,7 +64,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit {
'blacklistOnMyVideo',
'myVideoPublished',
'myVideoImportFinished',
'myVideoEditionFinished'
'myVideoStudioEditionFinished'
]
},

View File

@ -205,9 +205,9 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
private buildActions () {
this.videoActions = [
{
label: $localize`Editor`,
linkBuilder: ({ video }) => [ '/video-editor/edit', video.uuid ],
isDisplayed: ({ video }) => video.isEditableBy(this.authService.getUser(), this.serverService.getHTMLConfig().videoEditor.enabled),
label: $localize`Studio`,
linkBuilder: ({ video }) => [ '/studio/edit', video.uuid ],
isDisplayed: ({ video }) => video.isEditableBy(this.authService.getUser(), this.serverService.getHTMLConfig().videoStudio.enabled),
iconName: 'film'
},
{

View File

@ -1,2 +0,0 @@
export * from './video-editor-edit.component'
export * from './video-editor-edit.resolver'

View File

@ -1 +0,0 @@
export * from './video-editor.module'

View File

@ -1 +0,0 @@
export * from './video-editor.service'

View File

@ -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 {}

View File

@ -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 { }

View File

@ -0,0 +1,2 @@
export * from './video-studio-edit.component'
export * from './video-studio-edit.resolver'

View File

@ -1,5 +1,5 @@
<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">
<form role="form" [formGroup]="form">

View File

@ -2,18 +2,18 @@ import { Component, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ConfirmService, Notifier, ServerService } from '@app/core'
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 { secondsToTime } from '@shared/core-utils'
import { VideoEditorTask, VideoEditorTaskCut } from '@shared/models'
import { VideoEditorService } from '../shared'
import { VideoStudioTask, VideoStudioTaskCut } from '@shared/models'
import { VideoStudioService } from '../shared'
@Component({
selector: 'my-video-editor-edit',
templateUrl: './video-editor-edit.component.html',
styleUrls: [ './video-editor-edit.component.scss' ]
selector: 'my-video-studio-edit',
templateUrl: './video-studio-edit.component.html',
styleUrls: [ './video-studio-edit.component.scss' ]
})
export class VideoEditorEditComponent extends FormReactive implements OnInit {
export class VideoStudioEditComponent extends FormReactive implements OnInit {
isRunningEdition = false
video: VideoDetails
@ -24,7 +24,7 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
private notifier: Notifier,
private router: Router,
private route: ActivatedRoute,
private videoEditorService: VideoEditorService,
private videoStudioService: VideoStudioService,
private loadingBar: LoadingBarService,
private confirmService: ConfirmService
) {
@ -84,11 +84,13 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
this.loadingBar.useRef().start()
return this.videoEditorService.editVideo(this.video.uuid, tasks)
return this.videoStudioService.editVideo(this.video.uuid, tasks)
.subscribe({
next: () => {
this.notifier.success($localize`Video updated.`)
this.router.navigateByUrl(Video.buildWatchUrl(this.video))
this.notifier.success($localize`Edition tasks created.`)
// Don't redirect to old video version watch page that could be confusing for users
this.router.navigateByUrl('/my-library/videos')
},
error: err => {
@ -153,13 +155,13 @@ export class VideoEditorEditComponent extends FormReactive implements OnInit {
}
private buildTasks () {
const tasks: VideoEditorTask[] = []
const tasks: VideoStudioTask[] = []
const value = this.form.value
const cut = value['cut']
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['end'] !== this.video.duration) options.end = cut['end']

View File

@ -4,7 +4,7 @@ import { ActivatedRouteSnapshot, Resolve } from '@angular/router'
import { VideoService } from '@app/shared/shared-main'
@Injectable()
export class VideoEditorEditResolver implements Resolve<any> {
export class VideoStudioEditResolver implements Resolve<any> {
constructor (
private videoService: VideoService
) {

View File

@ -0,0 +1 @@
export * from './video-studio.module'

View File

@ -0,0 +1 @@
export * from './video-studio.service'

View File

@ -4,19 +4,19 @@ import { Injectable } from '@angular/core'
import { RestExtractor } from '@app/core'
import { objectToFormData } from '@app/helpers'
import { VideoService } from '@app/shared/shared-main'
import { VideoEditorCreateEdition, VideoEditorTask } from '@shared/models'
import { VideoStudioCreateEdition, VideoStudioTask } from '@shared/models'
@Injectable()
export class VideoEditorService {
export class VideoStudioService {
constructor (
private authHttp: HttpClient,
private restExtractor: RestExtractor
) {}
editVideo (videoId: number | string, tasks: VideoEditorTask[]) {
const url = VideoService.BASE_VIDEO_URL + '/' + videoId + '/editor/edit'
const body: VideoEditorCreateEdition = {
editVideo (videoId: number | string, tasks: VideoStudioTask[]) {
const url = VideoService.BASE_VIDEO_URL + '/' + videoId + '/studio/edit'
const body: VideoStudioCreateEdition = {
tasks
}

View 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 {}

View 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 { }

View File

@ -35,7 +35,7 @@ export class ActionButtonsComponent implements OnInit, OnChanges {
playlist: false,
download: true,
update: true,
editor: true,
studio: true,
blacklist: true,
delete: true,
report: true,

View File

@ -144,8 +144,8 @@ const routes: Routes = [
},
{
path: 'video-editor',
loadChildren: () => import('./+video-editor/video-editor.module').then(m => m.VideoEditorModule),
path: 'studio',
loadChildren: () => import('./+video-studio/video-studio.module').then(m => m.VideoStudioModule),
canActivateChild: [ MetaGuard ]
},

View File

@ -228,7 +228,7 @@ export class UserNotification implements UserNotificationServer {
this.pluginQueryParams.pluginType = this.plugin.type + ''
break
case UserNotificationType.MY_VIDEO_EDITION_FINISHED:
case UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED:
this.videoUrl = this.buildVideoUrl(this.video)
break
}

View File

@ -207,7 +207,7 @@
</div>
</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>
<div class="message" i18n>

View File

@ -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))
}
isEditableBy (user: AuthUser, videoEditorEnabled: boolean) {
return videoEditorEnabled &&
isEditableBy (user: AuthUser, videoStudioEnabled: boolean) {
return videoStudioEnabled &&
this.state?.id === VideoState.PUBLISHED &&
this.isUpdatableBy(user)
}

View File

@ -29,7 +29,7 @@ export type VideoActionsDisplayType = {
liveInfo?: boolean
removeFiles?: boolean
transcoding?: boolean
editor?: boolean
studio?: boolean
}
@Component({
@ -61,7 +61,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
liveInfo: false,
removeFiles: false,
transcoding: false,
editor: true
studio: true
}
@Input() placement = 'left'
@ -153,7 +153,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
}
isVideoEditable () {
return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoEditor.enabled)
return this.video.isEditableBy(this.user, this.serverService.getHTMLConfig().videoStudio.enabled)
}
isVideoRemovable () {
@ -337,10 +337,10 @@ export class VideoActionsDropdownComponent implements OnChanges {
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
},
{
label: $localize`Editor`,
linkBuilder: ({ video }) => [ '/video-editor/edit', video.uuid ],
label: $localize`Studio`,
linkBuilder: ({ video }) => [ '/studio/edit', video.uuid ],
iconName: 'film',
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.editor && this.isVideoEditable()
isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.studio && this.isVideoEditable()
},
{
label: $localize`Block`,

View File

@ -436,7 +436,7 @@ live:
1440p: false
2160p: false
video_editor:
video_studio:
# Enable video edition by users (cut, add intro/outro, add watermark etc)
enabled: false

View File

@ -444,7 +444,7 @@ live:
1440p: false
2160p: false
video_editor:
video_studio:
# Enable video edition by users (cut, add intro/outro, add watermark etc)
enabled: false

View File

@ -37,7 +37,7 @@ signup:
transcoding:
enabled: false
video_editor:
video_studio:
enabled: false
live:

View File

@ -31,5 +31,5 @@ admin:
transcoding:
enabled: false
video_editor:
video_studio:
enabled: false

View File

@ -31,5 +31,5 @@ admin:
transcoding:
enabled: false
video_editor:
video_studio:
enabled: false

View File

@ -31,5 +31,5 @@ admin:
transcoding:
enabled: false
video_editor:
video_studio:
enabled: false

View File

@ -31,5 +31,5 @@ admin:
transcoding:
enabled: false
video_editor:
video_studio:
enabled: false

View File

@ -168,5 +168,5 @@ views:
local_buffer_update_interval: '5 seconds'
ip_view_expiration: '1 second'
video_editor:
video_studio:
enabled: true

View File

@ -259,8 +259,8 @@ function customConfig (): CustomConfig {
}
}
},
videoEditor: {
enabled: CONFIG.VIDEO_EDITOR.ENABLED
videoStudio: {
enabled: CONFIG.VIDEO_STUDIO.ENABLED
},
import: {
videos: {

View File

@ -83,7 +83,7 @@ async function updateNotificationSettings (req: express.Request, res: express.Re
abuseStateChange: body.abuseStateChange,
newPeerTubeVersion: body.newPeerTubeVersion,
newPluginVersion: body.newPluginVersion,
myVideoEditionFinished: body.myVideoEditionFinished
myVideoStudioEditionFinished: body.myVideoStudioEditionFinished
}
await UserNotificationSettingModel.update(values, query)

View File

@ -35,7 +35,7 @@ import { VideoModel } from '../../../models/video/video'
import { blacklistRouter } from './blacklist'
import { videoCaptionsRouter } from './captions'
import { videoCommentRouter } from './comment'
import { editorRouter } from './editor'
import { studioRouter } from './studio'
import { filesRouter } from './files'
import { videoImportsRouter } from './import'
import { liveRouter } from './live'
@ -52,7 +52,7 @@ const videosRouter = express.Router()
videosRouter.use('/', blacklistRouter)
videosRouter.use('/', rateVideoRouter)
videosRouter.use('/', videoCommentRouter)
videosRouter.use('/', editorRouter)
videosRouter.use('/', studioRouter)
videosRouter.use('/', videoCaptionsRouter)
videosRouter.use('/', videoImportsRouter)
videosRouter.use('/', ownershipVideoRouter)

View File

@ -2,26 +2,26 @@ import express from 'express'
import { createAnyReqFiles } from '@server/helpers/express-utils'
import { MIMETYPES } from '@server/initializers/constants'
import { JobQueue } from '@server/lib/job-queue'
import { buildTaskFileFieldname, getTaskFile } from '@server/lib/video-editor'
import { buildTaskFileFieldname, getTaskFile } from '@server/lib/video-studio'
import {
HttpStatusCode,
VideoEditionTaskPayload,
VideoEditorCreateEdition,
VideoEditorTask,
VideoEditorTaskCut,
VideoEditorTaskIntro,
VideoEditorTaskOutro,
VideoEditorTaskWatermark,
VideoState
VideoState,
VideoStudioCreateEdition,
VideoStudioTask,
VideoStudioTaskCut,
VideoStudioTaskIntro,
VideoStudioTaskOutro,
VideoStudioTaskPayload,
VideoStudioTaskWatermark
} 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(
MIMETYPES.VIDEO.MIMETYPE_EXT,
(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
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,
tasksFiles,
asyncMiddleware(videosEditorAddEditionValidator),
asyncMiddleware(videoStudioAddEditionValidator),
asyncMiddleware(createEditionTasks)
)
// ---------------------------------------------------------------------------
export {
editorRouter
studioRouter
}
// ---------------------------------------------------------------------------
async function createEditionTasks (req: express.Request, res: express.Response) {
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
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))
}
JobQueue.Instance.createJob({ type: 'video-edition', payload })
JobQueue.Instance.createJob({ type: 'video-studio-edition', payload })
return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
}
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-outro': buildIntroOutroTask,
@ -85,11 +85,11 @@ const taskPayloadBuilders: {
'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)
}
function buildIntroOutroTask (task: VideoEditorTaskIntro | VideoEditorTaskOutro, indice: number, files: Express.Multer.File[]) {
function buildIntroOutroTask (task: VideoStudioTaskIntro | VideoStudioTaskOutro, indice: number, files: Express.Multer.File[]) {
return {
name: task.name,
options: {
@ -98,7 +98,7 @@ function buildIntroOutroTask (task: VideoEditorTaskIntro | VideoEditorTaskOutro,
}
}
function buildCutTask (task: VideoEditorTaskCut) {
function buildCutTask (task: VideoStudioTaskCut) {
return {
name: task.name,
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 {
name: task.name,
options: {

View File

@ -1,40 +1,40 @@
import validator from 'validator'
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
import { buildTaskFileFieldname } from '@server/lib/video-editor'
import { VideoEditorTask } from '@shared/models'
import { buildTaskFileFieldname } from '@server/lib/video-studio'
import { VideoStudioTask } from '@shared/models'
import { isArray } from './misc'
import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos'
function isValidEditorTasksArray (tasks: any) {
function isValidStudioTasksArray (tasks: any) {
if (!isArray(tasks)) return false
return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.min &&
tasks.length <= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.max
return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_STUDIO.TASKS.min &&
tasks.length <= CONSTRAINTS_FIELDS.VIDEO_STUDIO.TASKS.max
}
function isEditorCutTaskValid (task: VideoEditorTask) {
function isStudioCutTaskValid (task: VideoStudioTask) {
if (task.name !== 'cut') return false
if (!task.options) return false
const { start, end } = task.options
if (!start && !end) return false
if (start && !validator.isInt(start + '', CONSTRAINTS_FIELDS.VIDEO_EDITOR.CUT_TIME)) return false
if (end && !validator.isInt(end + '', 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_STUDIO.CUT_TIME)) return false
if (!start || !end) return true
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'))
return (task.name === 'add-intro' || task.name === 'add-outro') &&
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'))
return task.name === 'add-watermark' &&
@ -44,9 +44,9 @@ function isEditorTaskAddWatermarkValid (task: VideoEditorTask, indice: number, f
// ---------------------------------------------------------------------------
export {
isValidEditorTasksArray,
isValidStudioTasksArray,
isEditorCutTaskValid,
isEditorTaskAddIntroOutroValid,
isEditorTaskAddWatermarkValid
isStudioCutTaskValid,
isStudioTaskAddIntroOutroValid,
isStudioTaskAddWatermarkValid
}

View File

@ -49,7 +49,7 @@ function checkConfig () {
checkSearchConfig()
checkLiveConfig()
checkObjectStorageConfig()
checkVideoEditorConfig()
checkVideoStudioConfig()
}
// We get db by param to not import it in this file (import orders)
@ -260,8 +260,8 @@ function checkObjectStorageConfig () {
}
}
function checkVideoEditorConfig () {
if (CONFIG.VIDEO_EDITOR.ENABLED === true && CONFIG.TRANSCODING.ENABLED === false) {
throw new Error('Video editor cannot be enabled if transcoding is disabled')
function checkVideoStudioConfig () {
if (CONFIG.VIDEO_STUDIO.ENABLED === true && CONFIG.TRANSCODING.ENABLED === false) {
throw new Error('Video studio cannot be enabled if transcoding is disabled')
}
}

View File

@ -30,7 +30,7 @@ function checkMissedConfig () {
'transcoding.profile', 'transcoding.concurrency',
'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.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',
'trending.videos.interval_days',
'client.videos.miniature.display_author_avatar',

View File

@ -335,8 +335,8 @@ const CONFIG = {
}
}
},
VIDEO_EDITOR: {
get ENABLED () { return config.get<boolean>('video_editor.enabled') }
VIDEO_STUDIO: {
get ENABLED () { return config.get<boolean>('video_studio.enabled') }
},
IMPORT: {
VIDEOS: {

View File

@ -152,7 +152,7 @@ const JOB_ATTEMPTS: { [id in JobType]: number } = {
'activitypub-refresher': 1,
'video-redundancy': 1,
'video-live-ending': 1,
'video-edition': 1,
'video-studio-edition': 1,
'manage-video-torrent': 1,
'move-to-object-storage': 3
}
@ -170,7 +170,7 @@ const JOB_CONCURRENCY: { [id in Exclude<JobType, 'video-transcoding' | 'video-im
'activitypub-refresher': 1,
'video-redundancy': 1,
'video-live-ending': 10,
'video-edition': 1,
'video-studio-edition': 1,
'manage-video-torrent': 1,
'move-to-object-storage': 1
}
@ -182,7 +182,7 @@ const JOB_TTL: { [id in JobType]: number } = {
'activitypub-cleaner': 1000 * 3600, // 1 hour
'video-file-import': 1000 * 3600, // 1 hour
'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
'email': 60000 * 10, // 10 minutes
'actor-keys': 60000 * 20, // 20 minutes
@ -358,7 +358,7 @@ const CONSTRAINTS_FIELDS = {
COMMONS: {
URL: { min: 5, max: 2000 } // Length
},
VIDEO_EDITOR: {
VIDEO_STUDIO: {
TASKS: { min: 1, max: 10 }, // Number of tasks
CUT_TIME: { min: 0 } // Value
}

View File

@ -14,11 +14,11 @@ async function up (utils: {
defaultValue: null,
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 })
}
@ -28,7 +28,7 @@ async function up (utils: {
defaultValue: null,
allowNull: false
}
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoEditionFinished', data, { transaction })
await utils.queryInterface.changeColumn('userNotificationSetting', 'myVideoStudioEditionFinished', data, { transaction })
}
}

View File

@ -9,8 +9,8 @@ import { generateWebTorrentVideoFilename } from '@server/lib/paths'
import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/default-transcoding-profiles'
import { isAbleToUploadVideo } from '@server/lib/user'
import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
import { approximateIntroOutroAdditionalSize } from '@server/lib/video-editor'
import { VideoPathManager } from '@server/lib/video-path-manager'
import { approximateIntroOutroAdditionalSize } from '@server/lib/video-studio'
import { UserModel } from '@server/models/user/user'
import { VideoModel } from '@server/models/video/video'
import { VideoFileModel } from '@server/models/video/video-file'
@ -26,23 +26,23 @@ import {
getVideoStreamFPS
} from '@shared/extra-utils'
import {
VideoEditionPayload,
VideoEditionTaskPayload,
VideoEditorTask,
VideoEditorTaskCutPayload,
VideoEditorTaskIntroPayload,
VideoEditorTaskOutroPayload,
VideoEditorTaskWatermarkPayload
VideoStudioEditionPayload,
VideoStudioTaskPayload,
VideoStudioTaskCutPayload,
VideoStudioTaskIntroPayload,
VideoStudioTaskOutroPayload,
VideoStudioTaskWatermarkPayload,
VideoStudioTask
} from '@shared/models'
import { logger, loggerTagsFactory } from '../../../helpers/logger'
const lTagsBase = loggerTagsFactory('video-edition')
async function processVideoEdition (job: Job) {
const payload = job.data as VideoEditionPayload
async function processVideoStudioEdition (job: Job) {
const payload = job.data as VideoStudioEditionPayload
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)
@ -106,12 +106,12 @@ async function processVideoEdition (job: Job) {
// ---------------------------------------------------------------------------
export {
processVideoEdition
processVideoStudioEdition
}
// ---------------------------------------------------------------------------
type TaskProcessorOptions <T extends VideoEditionTaskPayload = VideoEditionTaskPayload> = {
type TaskProcessorOptions <T extends VideoStudioTaskPayload = VideoStudioTaskPayload> = {
inputPath: string
outputPath: string
video: MVideo
@ -119,7 +119,7 @@ type TaskProcessorOptions <T extends VideoEditionTaskPayload = VideoEditionTaskP
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-outro': processAddIntroOutro,
'cut': processCut,
@ -137,7 +137,7 @@ async function processTask (options: TaskProcessorOptions) {
return processor(options)
}
function processAddIntroOutro (options: TaskProcessorOptions<VideoEditorTaskIntroPayload | VideoEditorTaskOutroPayload>) {
function processAddIntroOutro (options: TaskProcessorOptions<VideoStudioTaskIntroPayload | VideoStudioTaskOutroPayload>) {
const { task } = options
return addIntroOutro({
@ -153,7 +153,7 @@ function processAddIntroOutro (options: TaskProcessorOptions<VideoEditorTaskIntr
})
}
function processCut (options: TaskProcessorOptions<VideoEditorTaskCutPayload>) {
function processCut (options: TaskProcessorOptions<VideoStudioTaskCutPayload>) {
const { task } = options
return cutVideo({
@ -164,7 +164,7 @@ function processCut (options: TaskProcessorOptions<VideoEditorTaskCutPayload>) {
})
}
function processAddWatermark (options: TaskProcessorOptions<VideoEditorTaskWatermarkPayload>) {
function processAddWatermark (options: TaskProcessorOptions<VideoStudioTaskWatermarkPayload>) {
const { task } = options
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 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)
if (await isAbleToUploadVideo(user.id, additionalBytes) === false) {

View File

@ -15,11 +15,11 @@ import {
ManageVideoTorrentPayload,
MoveObjectStoragePayload,
RefreshPayload,
VideoEditionPayload,
VideoFileImportPayload,
VideoImportPayload,
VideoLiveEndingPayload,
VideoRedundancyPayload,
VideoStudioEditionPayload,
VideoTranscodingPayload
} from '../../../shared/models'
import { logger } from '../../helpers/logger'
@ -34,10 +34,10 @@ import { processActorKeys } from './handlers/actor-keys'
import { processEmail } from './handlers/email'
import { processManageVideoTorrent } from './handlers/manage-video-torrent'
import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
import { processVideoEdition } from './handlers/video-edition'
import { processVideoFileImport } from './handlers/video-file-import'
import { processVideoImport } from './handlers/video-import'
import { processVideoLiveEnding } from './handlers/video-live-ending'
import { processVideoStudioEdition } from './handlers/video-studio-edition'
import { processVideoTranscoding } from './handlers/video-transcoding'
import { processVideosViewsStats } from './handlers/video-views-stats'
@ -57,7 +57,7 @@ type CreateJobArgument =
{ type: 'actor-keys', payload: ActorKeysPayload } |
{ type: 'video-redundancy', payload: VideoRedundancyPayload } |
{ 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: 'move-to-object-storage', payload: MoveObjectStoragePayload }
@ -83,7 +83,7 @@ const handlers: { [id in JobType]: (job: Job) => Promise<any> } = {
'video-redundancy': processVideoRedundancy,
'move-to-object-storage': processMoveToObjectStorage,
'manage-video-torrent': processManageVideoTorrent,
'video-edition': processVideoEdition
'video-studio-edition': processVideoStudioEdition
}
const jobTypes: JobType[] = [
@ -103,7 +103,7 @@ const jobTypes: JobType[] = [
'video-live-ending',
'move-to-object-storage',
'manage-video-torrent',
'video-edition'
'video-studio-edition'
]
class JobQueue {

View File

@ -12,7 +12,7 @@ import {
AbuseStateChangeForReporter,
AutoFollowForInstance,
CommentMention,
EditionFinishedForOwner,
StudioEditionFinishedForOwner,
FollowForInstance,
FollowForUser,
ImportFinishedForOwner,
@ -55,7 +55,7 @@ class Notifier {
newAbuseMessage: [ NewAbuseMessageForReporter, NewAbuseMessageForModerators ],
newPeertubeVersion: [ NewPeerTubeVersionForAdmins ],
newPluginVersion: [ NewPluginVersionForAdmins ],
videoEditionFinished: [ EditionFinishedForOwner ]
videoStudioEditionFinished: [ StudioEditionFinishedForOwner ]
}
private static instance: Notifier
@ -200,11 +200,11 @@ class Notifier {
.catch(err => logger.error('Cannot notify on new plugin version %s.', plugin.name, { err }))
}
notifyOfFinishedVideoEdition (video: MVideoFullLight) {
const models = this.notificationModels.videoEditionFinished
notifyOfFinishedVideoStudioEdition (video: MVideoFullLight) {
const models = this.notificationModels.videoStudioEditionFinished
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>) {

View File

@ -1,6 +1,6 @@
export * from './new-video-for-subscribers'
export * from './edition-finished-for-owner'
export * from './import-finished-for-owner'
export * from './owned-publication-after-auto-unblacklist'
export * from './owned-publication-after-schedule-update'
export * from './owned-publication-after-transcoding'
export * from './studio-edition-finished-for-owner'

View File

@ -6,7 +6,7 @@ import { MUserDefault, MUserWithNotificationSetting, MVideoFullLight, UserNotifi
import { UserNotificationType } from '@shared/models'
import { AbstractNotification } from '../common/abstract-notification'
export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLight> {
export class StudioEditionFinishedForOwner extends AbstractNotification <MVideoFullLight> {
private user: MUserDefault
async prepare () {
@ -14,11 +14,11 @@ export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLig
}
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) {
return user.NotificationSetting.myVideoEditionFinished
return user.NotificationSetting.myVideoStudioEditionFinished
}
getTargetUsers () {
@ -29,7 +29,7 @@ export class EditionFinishedForOwner extends AbstractNotification <MVideoFullLig
async createNotification (user: MUserWithNotificationSetting) {
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
type: UserNotificationType.MY_VIDEO_EDITION_FINISHED,
type: UserNotificationType.MY_VIDEO_STUDIO_EDITION_FINISHED,
userId: user.id,
videoId: this.payload.id
})

View File

@ -159,8 +159,8 @@ class ServerConfigManager {
port: CONFIG.LIVE.RTMP.PORT
}
},
videoEditor: {
enabled: CONFIG.VIDEO_EDITOR.ENABLED
videoStudio: {
enabled: CONFIG.VIDEO_STUDIO.ENABLED
},
import: {
videos: {

View File

@ -253,7 +253,7 @@ function createDefaultUserNotificationSettings (user: MUserId, t: Transaction |
autoInstanceFollowing: UserNotificationSettingValue.WEB,
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
newPluginVersion: UserNotificationSettingValue.WEB,
myVideoEditionFinished: UserNotificationSettingValue.WEB
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB
}
return UserNotificationSettingModel.create(values, { transaction: t })

View File

@ -135,7 +135,7 @@ async function moveToPublishedState (options: {
await federateVideoIfNeeded(video, isNewVideo, transaction)
if (previousState === VideoState.TO_EDIT) {
Notifier.Instance.notifyOfFinishedVideoEdition(video)
Notifier.Instance.notifyOfFinishedVideoStudioEdition(video)
return
}

View File

@ -1,6 +1,6 @@
import { MVideoFullLight } from "@server/types/models"
import { getVideoStreamDuration } from "@shared/extra-utils"
import { VideoEditorTask } from "@shared/models"
import { MVideoFullLight } from '@server/types/models'
import { getVideoStreamDuration } from '@shared/extra-utils'
import { VideoStudioTask } from '@shared/models'
function buildTaskFileFieldname (indice: number, fieldName = 'file') {
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))
}
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
for (let i = 0; i < tasks.length; i++) {

View File

@ -57,7 +57,7 @@ const customConfigUpdateValidator = [
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('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.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 (!checkInvalidTranscodingConfig(req.body, res)) return
if (!checkInvalidLiveConfig(req.body, res)) return
if (!checkInvalidVideoEditorConfig(req.body, res)) return
if (!checkInvalidVideoStudioConfig(req.body, res)) return
return next()
}
@ -163,11 +163,11 @@ function checkInvalidLiveConfig (customConfig: CustomConfig, res: express.Respon
return true
}
function checkInvalidVideoEditorConfig (customConfig: CustomConfig, res: express.Response) {
if (customConfig.videoEditor.enabled === false) return true
function checkInvalidVideoStudioConfig (customConfig: CustomConfig, res: express.Response) {
if (customConfig.videoStudio.enabled === false) return true
if (customConfig.videoEditor.enabled === true && customConfig.transcoding.enabled === false) {
res.fail({ message: 'You cannot enable video editor if transcoding is not enabled' })
if (customConfig.videoStudio.enabled === true && customConfig.transcoding.enabled === false) {
res.fail({ message: 'You cannot enable video studio if transcoding is not enabled' })
return false
}

View File

@ -2,7 +2,6 @@ export * from './video-blacklist'
export * from './video-captions'
export * from './video-channels'
export * from './video-comments'
export * from './video-editor'
export * from './video-files'
export * from './video-imports'
export * from './video-live'
@ -10,5 +9,6 @@ export * from './video-ownership-changes'
export * from './video-watch'
export * from './video-rates'
export * from './video-shares'
export * from './video-studio'
export * from './video-transcoding'
export * from './videos'

View File

@ -2,31 +2,31 @@ import express from 'express'
import { body, param } from 'express-validator'
import { isIdOrUUIDValid } from '@server/helpers/custom-validators/misc'
import {
isEditorCutTaskValid,
isEditorTaskAddIntroOutroValid,
isEditorTaskAddWatermarkValid,
isValidEditorTasksArray
} from '@server/helpers/custom-validators/video-editor'
isStudioCutTaskValid,
isStudioTaskAddIntroOutroValid,
isStudioTaskAddWatermarkValid,
isValidStudioTasksArray
} from '@server/helpers/custom-validators/video-studio'
import { cleanUpReqFiles } from '@server/helpers/express-utils'
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 { HttpStatusCode, UserRight, VideoEditorCreateEdition, VideoEditorTask, VideoState } from '@shared/models'
import { HttpStatusCode, UserRight, VideoState, VideoStudioCreateEdition, VideoStudioTask } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { areValidationErrors, checkUserCanManageVideo, checkUserQuota, doesVideoExist } from '../shared'
const videosEditorAddEditionValidator = [
const videoStudioAddEditionValidator = [
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) => {
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({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'Video editor is disabled on this instance'
message: 'Video studio is disabled on this instance'
})
return cleanUpReqFiles(req)
@ -34,7 +34,7 @@ const videosEditorAddEditionValidator = [
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[]
for (let i = 0; i < body.tasks.length; i++) {
@ -90,21 +90,21 @@ const videosEditorAddEditionValidator = [
// ---------------------------------------------------------------------------
export {
videosEditorAddEditionValidator
videoStudioAddEditionValidator
}
// ---------------------------------------------------------------------------
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,
'add-intro': isEditorTaskAddIntroOutroValid,
'add-outro': isEditorTaskAddIntroOutroValid,
'add-watermark': isEditorTaskAddWatermarkValid
'cut': isStudioCutTaskValid,
'add-intro': isStudioTaskAddIntroOutroValid,
'add-outro': isStudioTaskAddIntroOutroValid,
'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]
if (!checker) return false

View File

@ -178,11 +178,11 @@ export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<U
@AllowNull(false)
@Default(null)
@Is(
'UserNotificationSettingMyVideoEditionFinished',
value => throwIfNotValid(value, isUserNotificationSettingValid, 'myVideoEditionFinished')
'UserNotificationSettingMyVideoStudioEditionFinished',
value => throwIfNotValid(value, isUserNotificationSettingValid, 'myVideoStudioEditionFinished')
)
@Column
myVideoEditionFinished: UserNotificationSettingValue
myVideoStudioEditionFinished: UserNotificationSettingValue
@ForeignKey(() => UserModel)
@Column
@ -225,7 +225,7 @@ export class UserNotificationSettingModel extends Model<Partial<AttributesOnly<U
abuseNewMessage: this.abuseNewMessage,
abuseStateChange: this.abuseStateChange,
newPeerTubeVersion: this.newPeerTubeVersion,
myVideoEditionFinished: this.myVideoEditionFinished,
myVideoStudioEditionFinished: this.myVideoStudioEditionFinished,
newPluginVersion: this.newPluginVersion
}
}

View File

@ -148,7 +148,7 @@ describe('Test config API validators', function () {
}
}
},
videoEditor: {
videoStudio: {
enabled: true
},
import: {

View File

@ -25,7 +25,7 @@ import './video-blacklist'
import './video-captions'
import './video-channels'
import './video-comments'
import './video-editor'
import './video-studio'
import './video-imports'
import './video-playlists'
import './videos'

View File

@ -171,7 +171,7 @@ describe('Test user notifications API validators', function () {
abuseNewMessage: UserNotificationSettingValue.WEB,
abuseStateChange: UserNotificationSettingValue.WEB,
newPeerTubeVersion: UserNotificationSettingValue.WEB,
myVideoEditionFinished: UserNotificationSettingValue.WEB,
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB,
newPluginVersion: UserNotificationSettingValue.WEB
}

View File

@ -1,19 +1,19 @@
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
import { HttpStatusCode, VideoEditorTask } from '@shared/models'
import { HttpStatusCode, VideoStudioTask } from '@shared/models'
import {
cleanupTests,
createSingleServer,
PeerTubeServer,
setAccessTokensToServers,
VideoEditorCommand,
VideoStudioCommand,
waitJobs
} from '@shared/server-commands'
describe('Test video editor API validator', function () {
describe('Test video studio API validator', function () {
let server: PeerTubeServer
let command: VideoEditorCommand
let command: VideoStudioCommand
let userAccessToken: string
let videoUUID: string
@ -32,7 +32,7 @@ describe('Test video editor API validator', function () {
const { uuid } = await server.videos.quickUpload({ name: 'video' })
videoUUID = uuid
command = server.videoEditor
command = server.videoStudio
await waitJobs([ server ])
})
@ -41,10 +41,10 @@ describe('Test video editor API validator', 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({
newConfig: {
videoEditor: {
videoStudio: {
enabled: false
}
}
@ -52,15 +52,15 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
videoId: videoUUID,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
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({
newConfig: {
videoEditor: {
videoStudio: {
enabled: true
},
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({
newConfig: {
videoEditor: {
videoStudio: {
enabled: true
},
transcoding: {
@ -91,7 +91,7 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
token: null,
videoId: videoUUID,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.UNAUTHORIZED_401
})
})
@ -100,7 +100,7 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
token: userAccessToken,
videoId: videoUUID,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.FORBIDDEN_403
})
})
@ -108,7 +108,7 @@ describe('Test video editor API validator', function () {
it('Should fail with an invalid video', async function () {
await command.createEditionTasks({
videoId: 'tintin',
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
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 () {
await command.createEditionTasks({
videoId: 42,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.NOT_FOUND_404
})
})
@ -132,7 +132,7 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
videoId: uuid,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.CONFLICT_409
})
@ -171,7 +171,7 @@ describe('Test video editor API validator', function () {
})
it('Should fail with too many tasks', async function () {
const tasks: VideoEditorTask[] = []
const tasks: VideoStudioTask[] = []
for (let i = 0; i < 110; i++) {
tasks.push({
@ -194,7 +194,7 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
videoId: videoUUID,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.NO_CONTENT_204
})
})
@ -204,7 +204,7 @@ describe('Test video editor API validator', function () {
await command.createEditionTasks({
videoId: videoUUID,
tasks: VideoEditorCommand.getComplexTask(),
tasks: VideoStudioCommand.getComplexTask(),
expectedStatus: HttpStatusCode.CONFLICT_409
})

View File

@ -7,7 +7,7 @@ import {
checkMyVideoImportIsFinished,
checkNewActorFollow,
checkNewVideoFromSubscription,
checkVideoEditionIsFinished,
checkVideoStudioEditionIsFinished,
checkVideoIsPublished,
FIXTURE_URLS,
MockSmtpServer,
@ -16,7 +16,7 @@ import {
} from '@server/tests/shared'
import { wait } from '@shared/core-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'
const expect = chai.expect
@ -323,7 +323,7 @@ describe('Test user notifications', function () {
})
})
describe('Video editor', function () {
describe('Video studio', function () {
let baseParams: CheckerBaseParams
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)
const { name, shortUUID, id } = await uploadRandomVideoOnServers(servers, 2, { waitTranscoding: true })
@ -343,7 +343,7 @@ describe('Test user notifications', function () {
await waitJobs(servers)
await checkVideoIsPublished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
const tasks: VideoEditorTask[] = [
const tasks: VideoStudioTask[] = [
{
name: 'cut',
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 checkVideoEditionIsFinished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
await checkVideoStudioEditionIsFinished({ ...baseParams, videoName: name, shortUUID, checkType: 'presence' })
})
})

View File

@ -98,7 +98,7 @@ function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
expect(data.live.transcoding.resolutions['1440p']).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.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['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.http.enabled).to.be.false
@ -350,7 +350,7 @@ const newCustomConfig: CustomConfig = {
}
}
},
videoEditor: {
videoStudio: {
enabled: true
},
import: {

View File

@ -2,4 +2,4 @@ export * from './audio-only'
export * from './create-transcoding'
export * from './hls'
export * from './transcoder'
export * from './video-editor'
export * from './video-studio'

View File

@ -1,7 +1,7 @@
import { expect } from 'chai'
import { expectStartWith, getAllFiles } from '@server/tests/shared'
import { areObjectStorageTestsDisabled } from '@shared/core-utils'
import { VideoEditorTask } from '@shared/models'
import { VideoStudioTask } from '@shared/models'
import {
cleanupTests,
createMultipleServers,
@ -10,11 +10,11 @@ import {
PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
VideoEditorCommand,
VideoStudioCommand,
waitJobs
} from '@shared/server-commands'
describe('Test video editor', function () {
describe('Test video studio', function () {
let servers: PeerTubeServer[] = []
let videoUUID: string
@ -39,8 +39,8 @@ describe('Test video editor', function () {
await waitJobs(servers)
}
async function createTasks (tasks: VideoEditorTask[]) {
await servers[0].videoEditor.createEditionTasks({ videoId: videoUUID, tasks })
async function createTasks (tasks: VideoStudioTask[]) {
await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks })
await waitJobs(servers)
}
@ -56,7 +56,7 @@ describe('Test video editor', function () {
await servers[0].config.enableMinimumTranscoding()
await servers[0].config.enableEditor()
await servers[0].config.enableStudio()
})
describe('Cutting', function () {
@ -276,7 +276,7 @@ describe('Test video editor', function () {
this.timeout(240_000)
await renewVideo()
await createTasks(VideoEditorCommand.getComplexTask())
await createTasks(VideoStudioCommand.getComplexTask())
for (const server of servers) {
await checkDuration(server, 9)
@ -303,7 +303,7 @@ describe('Test video editor', function () {
this.timeout(240_000)
await renewVideo()
await createTasks(VideoEditorCommand.getComplexTask())
await createTasks(VideoStudioCommand.getComplexTask())
for (const server of servers) {
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 oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
await createTasks(VideoEditorCommand.getComplexTask())
await createTasks(VideoStudioCommand.getComplexTask())
for (const server of servers) {
const video = await server.videos.get({ id: videoUUID })

View File

@ -47,7 +47,7 @@ function getAllNotificationsSettings (): UserNotificationSetting {
abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
myVideoEditionFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
myVideoStudioEditionFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
}
}
@ -110,13 +110,13 @@ async function checkVideoIsPublished (options: CheckerBaseParams & {
await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
}
async function checkVideoEditionIsFinished (options: CheckerBaseParams & {
async function checkVideoStudioEditionIsFinished (options: CheckerBaseParams & {
videoName: string
shortUUID: string
checkType: CheckerType
}) {
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) {
if (checkType === 'presence') {
@ -685,7 +685,7 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
await setDefaultChannelAvatar(servers)
await setDefaultAccountAvatar(servers)
await servers[1].config.enableEditor()
await servers[1].config.enableStudio()
if (serversCount > 1) {
await doubleFollow(servers[0], servers[1])
@ -756,7 +756,7 @@ export {
checkNewAccountAbuseForModerators,
checkNewPeerTubeVersion,
checkNewPluginVersion,
checkVideoEditionIsFinished
checkVideoStudioEditionIsFinished
}
// ---------------------------------------------------------------------------

View File

@ -147,7 +147,7 @@ export interface CustomConfig {
}
}
videoEditor: {
videoStudio: {
enabled: boolean
}

View File

@ -1,6 +1,6 @@
import { ContextType } from '../activitypub/context'
import { VideoState } from '../videos'
import { VideoEditorTaskCut } from '../videos/editor'
import { VideoStudioTaskCut } from '../videos/studio'
import { VideoResolution } from '../videos/file/video-resolution.enum'
import { SendEmailOptions } from './emailer.model'
@ -23,7 +23,7 @@ export type JobType =
| 'actor-keys'
| 'manage-video-torrent'
| 'move-to-object-storage'
| 'video-edition'
| 'video-studio-edition'
export interface Job {
id: number
@ -117,9 +117,6 @@ export type ManageVideoTorrentPayload =
interface BaseTranscodingPayload {
videoUUID: string
isNewVideo?: boolean
// Custom notification when the task is finished
notification?: 'default' | 'video-edition'
}
export interface HLSTranscodingPayload extends BaseTranscodingPayload {
@ -178,9 +175,9 @@ export interface MoveObjectStoragePayload {
previousVideoState: VideoState
}
export type VideoEditorTaskCutPayload = VideoEditorTaskCut
export type VideoStudioTaskCutPayload = VideoStudioTaskCut
export type VideoEditorTaskIntroPayload = {
export type VideoStudioTaskIntroPayload = {
name: 'add-intro'
options: {
@ -188,7 +185,7 @@ export type VideoEditorTaskIntroPayload = {
}
}
export type VideoEditorTaskOutroPayload = {
export type VideoStudioTaskOutroPayload = {
name: 'add-outro'
options: {
@ -196,7 +193,7 @@ export type VideoEditorTaskOutroPayload = {
}
}
export type VideoEditorTaskWatermarkPayload = {
export type VideoStudioTaskWatermarkPayload = {
name: 'add-watermark'
options: {
@ -204,13 +201,13 @@ export type VideoEditorTaskWatermarkPayload = {
}
}
export type VideoEditionTaskPayload =
VideoEditorTaskCutPayload |
VideoEditorTaskIntroPayload |
VideoEditorTaskOutroPayload |
VideoEditorTaskWatermarkPayload
export type VideoStudioTaskPayload =
VideoStudioTaskCutPayload |
VideoStudioTaskIntroPayload |
VideoStudioTaskOutroPayload |
VideoStudioTaskWatermarkPayload
export interface VideoEditionPayload {
export interface VideoStudioEditionPayload {
videoUUID: string
tasks: VideoEditionTaskPayload[]
tasks: VideoStudioTaskPayload[]
}

View File

@ -175,7 +175,7 @@ export interface ServerConfig {
}
}
videoEditor: {
videoStudio: {
enabled: boolean
}

View File

@ -28,5 +28,5 @@ export interface UserNotificationSetting {
newPeerTubeVersion: UserNotificationSettingValue
newPluginVersion: UserNotificationSettingValue
myVideoEditionFinished: UserNotificationSettingValue
myVideoStudioEditionFinished: UserNotificationSettingValue
}

View File

@ -32,7 +32,7 @@ export const enum UserNotificationType {
NEW_PLUGIN_VERSION = 17,
NEW_PEERTUBE_VERSION = 18,
MY_VIDEO_EDITION_FINISHED = 19
MY_VIDEO_STUDIO_EDITION_FINISHED = 19
}
export interface VideoInfo {

View File

@ -1 +0,0 @@
export * from './video-editor-create-edit.model'

View File

@ -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
}
}

View File

@ -3,7 +3,7 @@ export * from './caption'
export * from './change-ownership'
export * from './channel'
export * from './comment'
export * from './editor'
export * from './studio'
export * from './live'
export * from './file'
export * from './import'

View File

@ -0,0 +1 @@
export * from './video-studio-create-edit.model'

View File

@ -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
}
}

View File

@ -60,7 +60,7 @@ export class ConfigCommand extends AbstractCommand {
transcoding: {
enabled: false
},
videoEditor: {
videoStudio: {
enabled: false
}
}
@ -111,10 +111,10 @@ export class ConfigCommand extends AbstractCommand {
})
}
enableEditor () {
enableStudio () {
return this.updateExistingSubConfig({
newConfig: {
videoEditor: {
videoStudio: {
enabled: true
}
}
@ -339,7 +339,7 @@ export class ConfigCommand extends AbstractCommand {
}
}
},
videoEditor: {
videoStudio: {
enabled: false
},
import: {

View File

@ -25,7 +25,7 @@ import {
PlaylistsCommand,
ServicesCommand,
StreamingPlaylistsCommand,
VideoEditorCommand,
VideoStudioCommand,
VideosCommand
} from '../videos'
import { CommentsCommand } from '../videos/comments-command'
@ -125,7 +125,7 @@ export class PeerTubeServer {
login?: LoginCommand
users?: UsersCommand
objectStorage?: ObjectStorageCommand
videoEditor?: VideoEditorCommand
videoStudio?: VideoStudioCommand
videos?: VideosCommand
constructor (options: { serverNumber: number } | { url: string }) {
@ -396,6 +396,6 @@ export class PeerTubeServer {
this.users = new UsersCommand(this)
this.videos = new VideosCommand(this)
this.objectStorage = new ObjectStorageCommand(this)
this.videoEditor = new VideoEditorCommand(this)
this.videoStudio = new VideoStudioCommand(this)
}
}

View File

@ -12,5 +12,5 @@ export * from './playlists-command'
export * from './services-command'
export * from './streaming-playlists-command'
export * from './comments-command'
export * from './video-editor-command'
export * from './video-studio-command'
export * from './videos-command'

View File

@ -1,9 +1,9 @@
import { HttpStatusCode, VideoEditorTask } from '@shared/models'
import { HttpStatusCode, VideoStudioTask } from '@shared/models'
import { AbstractCommand, OverrideCommandOptions } from '../shared'
export class VideoEditorCommand extends AbstractCommand {
export class VideoStudioCommand extends AbstractCommand {
static getComplexTask (): VideoEditorTask[] {
static getComplexTask (): VideoStudioTask[] {
return [
// Total duration: 2
{
@ -41,9 +41,9 @@ export class VideoEditorCommand extends AbstractCommand {
createEditionTasks (options: OverrideCommandOptions & {
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 } = {}
for (let i = 0; i < options.tasks.length; i++) {

View File

@ -85,7 +85,7 @@ server {
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; }
# This is the maximum upload size, which roughly matches the maximum size of a video file.