1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-05 02:39:33 +02:00

Add basic video editor support

This commit is contained in:
Chocobozzz 2022-02-11 10:51:33 +01:00 committed by Chocobozzz
parent a24bf4dc65
commit c729caf6cc
130 changed files with 3969 additions and 1353 deletions

View file

@ -1,4 +1,5 @@
import { UploadFilesForCheck } from 'express'
import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
import { isFileValid } from './misc'
@ -6,8 +7,14 @@ const imageMimeTypes = CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME
.map(v => v.replace('.', ''))
.join('|')
const imageMimeTypesRegex = `image/(${imageMimeTypes})`
function isActorImageFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], fieldname: string) {
return isFileValid(files, imageMimeTypesRegex, fieldname, CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max)
function isActorImageFile (files: UploadFilesForCheck, fieldname: string) {
return isFileValid({
files,
mimeTypeRegex: imageMimeTypesRegex,
field: fieldname,
maxSize: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max
})
}
// ---------------------------------------------------------------------------

View file

@ -61,75 +61,43 @@ function isIntOrNull (value: any) {
// ---------------------------------------------------------------------------
function isFileFieldValid (
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
field: string,
optional = false
) {
function isFileValid (options: {
files: UploadFilesForCheck
maxSize: number | null
mimeTypeRegex: string | null
field?: string
optional?: boolean // Default false
}) {
const { files, mimeTypeRegex, field, maxSize, optional = false } = options
// Should have files
if (!files) return optional
if (isArray(files)) return optional
// Should have a file
const fileArray = files[field]
if (!fileArray || fileArray.length === 0) {
const fileArray = isArray(files)
? files
: files[field]
if (!fileArray || !isArray(fileArray) || fileArray.length === 0) {
return optional
}
// The file should exist
const file = fileArray[0]
if (!file || !file.originalname) return false
return file
}
function isFileMimeTypeValid (
files: UploadFilesForCheck,
mimeTypeRegex: string,
field: string,
optional = false
) {
// Should have files
if (!files) return optional
if (isArray(files)) return optional
// Should have a file
const fileArray = files[field]
if (!fileArray || fileArray.length === 0) {
return optional
}
// The file should exist
const file = fileArray[0]
if (!file || !file.originalname) return false
return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
}
function isFileValid (
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
mimeTypeRegex: string,
field: string,
maxSize: number | null,
optional = false
) {
// Should have files
if (!files) return optional
if (isArray(files)) return optional
// Should have a file
const fileArray = files[field]
if (!fileArray || fileArray.length === 0) {
return optional
}
// The file should exist
// The file exists
const file = fileArray[0]
if (!file || !file.originalname) return false
// Check size
if ((maxSize !== null) && file.size > maxSize) return false
return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
if (mimeTypeRegex === null) return true
return checkMimetypeRegex(file.mimetype, mimeTypeRegex)
}
function checkMimetypeRegex (fileMimeType: string, mimeTypeRegex: string) {
return new RegExp(`^${mimeTypeRegex}$`, 'i').test(fileMimeType)
}
// ---------------------------------------------------------------------------
@ -204,7 +172,6 @@ export {
areUUIDsValid,
toArray,
toIntArray,
isFileFieldValid,
isFileMimeTypeValid,
isFileValid
isFileValid,
checkMimetypeRegex
}

View file

@ -1,5 +1,6 @@
import { getFileSize } from '@shared/extra-utils'
import { UploadFilesForCheck } from 'express'
import { readFile } from 'fs-extra'
import { getFileSize } from '@shared/extra-utils'
import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_LANGUAGES } from '../../initializers/constants'
import { exists, isFileValid } from './misc'
@ -11,8 +12,13 @@ const videoCaptionTypesRegex = Object.keys(MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT
.concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream
.map(m => `(${m})`)
.join('|')
function isVideoCaptionFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
return isFileValid(files, videoCaptionTypesRegex, field, CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max)
function isVideoCaptionFile (files: UploadFilesForCheck, field: string) {
return isFileValid({
files,
mimeTypeRegex: videoCaptionTypesRegex,
field,
maxSize: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max
})
}
async function isVTTFileValid (filePath: string) {

View file

@ -0,0 +1,52 @@
import validator from 'validator'
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
import { buildTaskFileFieldname } from '@server/lib/video-editor'
import { VideoEditorTask } from '@shared/models'
import { isArray } from './misc'
import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos'
function isValidEditorTasksArray (tasks: any) {
if (!isArray(tasks)) return false
return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.min &&
tasks.length <= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.max
}
function isEditorCutTaskValid (task: VideoEditorTask) {
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 || !end) return true
return parseInt(start + '') < parseInt(end + '')
}
function isEditorTaskAddIntroOutroValid (task: VideoEditorTask, 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[]) {
const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file'))
return task.name === 'add-watermark' &&
file && isVideoImageValid([ file ], null, true)
}
// ---------------------------------------------------------------------------
export {
isValidEditorTasksArray,
isEditorCutTaskValid,
isEditorTaskAddIntroOutroValid,
isEditorTaskAddWatermarkValid
}

View file

@ -1,4 +1,5 @@
import 'multer'
import { UploadFilesForCheck } from 'express'
import validator from 'validator'
import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants'
import { exists, isFileValid } from './misc'
@ -25,8 +26,14 @@ const videoTorrentImportRegex = Object.keys(MIMETYPES.TORRENT.MIMETYPE_EXT)
.concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream
.map(m => `(${m})`)
.join('|')
function isVideoImportTorrentFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
return isFileValid(files, videoTorrentImportRegex, 'torrentfile', CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, true)
function isVideoImportTorrentFile (files: UploadFilesForCheck) {
return isFileValid({
files,
mimeTypeRegex: videoTorrentImportRegex,
field: 'torrentfile',
maxSize: CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max,
optional: true
})
}
// ---------------------------------------------------------------------------

View file

@ -13,7 +13,7 @@ import {
VIDEO_RATE_TYPES,
VIDEO_STATES
} from '../../initializers/constants'
import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc'
import { exists, isArray, isDateValid, isFileValid } from './misc'
const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
@ -66,7 +66,7 @@ function isVideoTagValid (tag: string) {
return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
}
function isVideoTagsValid (tags: string[]) {
function areVideoTagsValid (tags: string[]) {
return tags === null || (
isArray(tags) &&
validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
@ -86,8 +86,13 @@ function isVideoFileExtnameValid (value: string) {
return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
}
function isVideoFileMimeTypeValid (files: UploadFilesForCheck) {
return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile')
function isVideoFileMimeTypeValid (files: UploadFilesForCheck, field = 'videofile') {
return isFileValid({
files,
mimeTypeRegex: MIMETYPES.VIDEO.MIMETYPES_REGEX,
field,
maxSize: null
})
}
const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
@ -95,8 +100,14 @@ const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
.join('|')
const videoImageTypesRegex = `image/(${videoImageTypes})`
function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
function isVideoImageValid (files: UploadFilesForCheck, field: string, optional = true) {
return isFileValid({
files,
mimeTypeRegex: videoImageTypesRegex,
field,
maxSize: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max,
optional
})
}
function isVideoPrivacyValid (value: number) {
@ -144,7 +155,7 @@ export {
isVideoDescriptionValid,
isVideoFileInfoHashValid,
isVideoNameValid,
isVideoTagsValid,
areVideoTagsValid,
isVideoFPSResolutionValid,
isScheduleVideoUpdatePrivacyValid,
isVideoOriginallyPublishedAtValid,
@ -160,7 +171,7 @@ export {
isVideoPrivacyValid,
isVideoFileResolutionValid,
isVideoFileSizeValid,
isVideoImage,
isVideoImageValid,
isVideoSupportValid,
isVideoFilterValid
}