Merge branch 'release/4.0.0' into develop

pull/4605/head
Chocobozzz 2021-12-03 14:40:52 +01:00
commit 9ea02c48a7
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
5 changed files with 38 additions and 20 deletions

View File

@ -51,7 +51,7 @@
i18n-labelText labelText="Allow additional extensions" i18n-labelText labelText="Allow additional extensions"
> >
<ng-container ngProjectAs="description"> <ng-container ngProjectAs="description">
<span i18n>Allows users to upload {{ additionalVideoExtensions }} videos.</span> <span i18n>Allows users to upload videos with additional extensions than .mp4, .ogv and .webm (for example: .avi, .mov, .mkv etc).</span>
</ng-container> </ng-container>
</my-peertube-checkbox> </my-peertube-checkbox>
</div> </div>

View File

@ -1,4 +1,6 @@
import { truncate } from 'lodash-es'
import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx'
import { isIOS } from 'src/assets/player/utils'
import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http'
import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
@ -10,7 +12,6 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models' import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
import { UploaderXFormData } from './uploaderx-form-data' import { UploaderXFormData } from './uploaderx-form-data'
import { VideoSend } from './video-send' import { VideoSend } from './video-send'
import { isIOS } from 'src/assets/player/utils'
@Component({ @Component({
selector: 'my-video-upload', selector: 'my-video-upload',
@ -281,6 +282,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
channelId: this.firstStepChannelId, channelId: this.firstStepChannelId,
nsfw: this.serverConfig.instance.isNSFW, nsfw: this.serverConfig.instance.isNSFW,
privacy: this.highestPrivacy.toString(), privacy: this.highestPrivacy.toString(),
name: this.buildVideoFilename(file.name),
filename: file.name, filename: file.name,
previewfile: previewfile as any previewfile: previewfile as any
} }
@ -311,8 +313,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
} }
private closeFirstStep (filename: string) { private closeFirstStep (filename: string) {
const nameWithoutExtension = filename.replace(/\.[^/.]+$/, '') const name = this.buildVideoFilename(filename)
const name = nameWithoutExtension.length < 3 ? filename : nameWithoutExtension
this.form.patchValue({ this.form.patchValue({
name, name,
@ -369,4 +370,18 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
return extensions.some(e => filename.endsWith(e)) return extensions.some(e => filename.endsWith(e))
} }
private buildVideoFilename (filename: string) {
const nameWithoutExtension = filename.replace(/\.[^/.]+$/, '')
let name = nameWithoutExtension.length < 3
? filename
: nameWithoutExtension
const videoNameMaxSize = 110
if (name.length > videoNameMaxSize) {
name = truncate(name, { length: videoNameMaxSize, omission: '' })
}
return name
}
} }

View File

@ -53,6 +53,7 @@ async function processVideoTranscoding (job: Job) {
if (!handler) { if (!handler) {
await moveToFailedTranscodingState(video) await moveToFailedTranscodingState(video)
await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
throw new Error('Cannot find transcoding handler for ' + payload.type) throw new Error('Cannot find transcoding handler for ' + payload.type)
} }
@ -62,12 +63,20 @@ async function processVideoTranscoding (job: Job) {
} catch (error) { } catch (error) {
await moveToFailedTranscodingState(video) await moveToFailedTranscodingState(video)
await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
throw error throw error
} }
return video return video
} }
// ---------------------------------------------------------------------------
export {
processVideoTranscoding
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Job handlers // Job handlers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -119,7 +128,7 @@ async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTrans
logger.info('Merge audio transcoding job for %s ended.', video.uuid, lTags(video.uuid)) logger.info('Merge audio transcoding job for %s ended.', video.uuid, lTags(video.uuid))
await onVideoFileOptimizer(video, payload, 'video', user) await onVideoFirstWebTorrentTranscoding(video, payload, 'video', user)
} }
async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) { async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
@ -129,7 +138,7 @@ async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodi
logger.info('Optimize transcoding job for %s ended.', video.uuid, lTags(video.uuid)) logger.info('Optimize transcoding job for %s ended.', video.uuid, lTags(video.uuid))
await onVideoFileOptimizer(video, payload, transcodeType, user) await onVideoFirstWebTorrentTranscoding(video, payload, transcodeType, user)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -159,7 +168,7 @@ async function onHlsPlaylistGeneration (video: MVideoFullLight, user: MUser, pay
await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo) await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo)
} }
async function onVideoFileOptimizer ( async function onVideoFirstWebTorrentTranscoding (
videoArg: MVideoWithFile, videoArg: MVideoWithFile,
payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload, payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload,
transcodeType: TranscodeOptionsType, transcodeType: TranscodeOptionsType,
@ -211,6 +220,8 @@ async function onNewWebTorrentFileResolution (
await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo) await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo)
} }
// ---------------------------------------------------------------------------
async function createHlsJobIfEnabled (user: MUserId, payload: { async function createHlsJobIfEnabled (user: MUserId, payload: {
videoUUID: string videoUUID: string
resolution: number resolution: number
@ -241,16 +252,6 @@ async function createHlsJobIfEnabled (user: MUserId, payload: {
return true return true
} }
// ---------------------------------------------------------------------------
export {
processVideoTranscoding,
createHlsJobIfEnabled,
onNewWebTorrentFileResolution
}
// ---------------------------------------------------------------------------
async function createLowerResolutionsJobs (options: { async function createLowerResolutionsJobs (options: {
video: MVideoFullLight video: MVideoFullLight
user: MUserId user: MUserId

View File

@ -211,7 +211,7 @@ const videosAddResumableInitValidator = getCommonVideoEditAttributes().concat([
const videoFileMetadata = { const videoFileMetadata = {
mimetype: req.headers['x-upload-content-type'] as string, mimetype: req.headers['x-upload-content-type'] as string,
size: +req.headers['x-upload-content-length'], size: +req.headers['x-upload-content-length'],
originalname: req.body.name originalname: req.body.filename
} }
const user = res.locals.oauth.token.User const user = res.locals.oauth.token.User

View File

@ -3,6 +3,8 @@ import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Mo
import { AttributesOnly } from '@shared/core-utils' import { AttributesOnly } from '@shared/core-utils'
import { VideoModel } from './video' import { VideoModel } from './video'
export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
@Table({ @Table({
tableName: 'videoJobInfo', tableName: 'videoJobInfo',
indexes: [ indexes: [
@ -57,7 +59,7 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
return VideoJobInfoModel.findOne({ where, transaction }) return VideoJobInfoModel.findOne({ where, transaction })
} }
static async increaseOrCreate (videoUUID: string, column: 'pendingMove' | 'pendingTranscode'): Promise<number> { static async increaseOrCreate (videoUUID: string, column: VideoJobInfoColumnType): Promise<number> {
const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } } const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(` const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(`
@ -79,7 +81,7 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
return pendingMove return pendingMove
} }
static async decrease (videoUUID: string, column: 'pendingMove' | 'pendingTranscode'): Promise<number> { static async decrease (videoUUID: string, column: VideoJobInfoColumnType): Promise<number> {
const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } } const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(` const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(`