mirror of https://github.com/Chocobozzz/PeerTube
Merge branch 'release/4.0.0' into develop
commit
9ea02c48a7
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }>(`
|
||||||
|
|
Loading…
Reference in New Issue