aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts21
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts27
-rw-r--r--server/middlewares/validators/videos/videos.ts2
-rw-r--r--server/models/video/video-job-info.ts6
5 files changed, 38 insertions, 20 deletions
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
index 048f7908d..1158f027b 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html
@@ -51,7 +51,7 @@
51 i18n-labelText labelText="Allow additional extensions" 51 i18n-labelText labelText="Allow additional extensions"
52 > 52 >
53 <ng-container ngProjectAs="description"> 53 <ng-container ngProjectAs="description">
54 <span i18n>Allows users to upload {{ additionalVideoExtensions }} videos.</span> 54 <span i18n>Allows users to upload videos with additional extensions than .mp4, .ogv and .webm (for example: .avi, .mov, .mkv etc).</span>
55 </ng-container> 55 </ng-container>
56 </my-peertube-checkbox> 56 </my-peertube-checkbox>
57 </div> 57 </div>
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
index 76205db44..28d7ec458 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
@@ -1,4 +1,6 @@
1import { truncate } from 'lodash-es'
1import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' 2import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx'
3import { isIOS } from 'src/assets/player/utils'
2import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' 4import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http'
3import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' 5import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
4import { Router } from '@angular/router' 6import { Router } from '@angular/router'
@@ -10,7 +12,6 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
10import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models' 12import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models'
11import { UploaderXFormData } from './uploaderx-form-data' 13import { UploaderXFormData } from './uploaderx-form-data'
12import { VideoSend } from './video-send' 14import { VideoSend } from './video-send'
13import { isIOS } from 'src/assets/player/utils'
14 15
15@Component({ 16@Component({
16 selector: 'my-video-upload', 17 selector: 'my-video-upload',
@@ -281,6 +282,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
281 channelId: this.firstStepChannelId, 282 channelId: this.firstStepChannelId,
282 nsfw: this.serverConfig.instance.isNSFW, 283 nsfw: this.serverConfig.instance.isNSFW,
283 privacy: this.highestPrivacy.toString(), 284 privacy: this.highestPrivacy.toString(),
285 name: this.buildVideoFilename(file.name),
284 filename: file.name, 286 filename: file.name,
285 previewfile: previewfile as any 287 previewfile: previewfile as any
286 } 288 }
@@ -311,8 +313,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
311 } 313 }
312 314
313 private closeFirstStep (filename: string) { 315 private closeFirstStep (filename: string) {
314 const nameWithoutExtension = filename.replace(/\.[^/.]+$/, '') 316 const name = this.buildVideoFilename(filename)
315 const name = nameWithoutExtension.length < 3 ? filename : nameWithoutExtension
316 317
317 this.form.patchValue({ 318 this.form.patchValue({
318 name, 319 name,
@@ -369,4 +370,18 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
369 370
370 return extensions.some(e => filename.endsWith(e)) 371 return extensions.some(e => filename.endsWith(e))
371 } 372 }
373
374 private buildVideoFilename (filename: string) {
375 const nameWithoutExtension = filename.replace(/\.[^/.]+$/, '')
376 let name = nameWithoutExtension.length < 3
377 ? filename
378 : nameWithoutExtension
379
380 const videoNameMaxSize = 110
381 if (name.length > videoNameMaxSize) {
382 name = truncate(name, { length: videoNameMaxSize, omission: '' })
383 }
384
385 return name
386 }
372} 387}
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts
index 0d80eb6c5..0edcdcba3 100644
--- a/server/lib/job-queue/handlers/video-transcoding.ts
+++ b/server/lib/job-queue/handlers/video-transcoding.ts
@@ -53,6 +53,7 @@ async function processVideoTranscoding (job: Job) {
53 53
54 if (!handler) { 54 if (!handler) {
55 await moveToFailedTranscodingState(video) 55 await moveToFailedTranscodingState(video)
56 await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
56 57
57 throw new Error('Cannot find transcoding handler for ' + payload.type) 58 throw new Error('Cannot find transcoding handler for ' + payload.type)
58 } 59 }
@@ -62,6 +63,8 @@ async function processVideoTranscoding (job: Job) {
62 } catch (error) { 63 } catch (error) {
63 await moveToFailedTranscodingState(video) 64 await moveToFailedTranscodingState(video)
64 65
66 await VideoJobInfoModel.decrease(video.uuid, 'pendingTranscode')
67
65 throw error 68 throw error
66 } 69 }
67 70
@@ -69,6 +72,12 @@ async function processVideoTranscoding (job: Job) {
69} 72}
70 73
71// --------------------------------------------------------------------------- 74// ---------------------------------------------------------------------------
75
76export {
77 processVideoTranscoding
78}
79
80// ---------------------------------------------------------------------------
72// Job handlers 81// Job handlers
73// --------------------------------------------------------------------------- 82// ---------------------------------------------------------------------------
74 83
@@ -119,7 +128,7 @@ async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTrans
119 128
120 logger.info('Merge audio transcoding job for %s ended.', video.uuid, lTags(video.uuid)) 129 logger.info('Merge audio transcoding job for %s ended.', video.uuid, lTags(video.uuid))
121 130
122 await onVideoFileOptimizer(video, payload, 'video', user) 131 await onVideoFirstWebTorrentTranscoding(video, payload, 'video', user)
123} 132}
124 133
125async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) { 134async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
@@ -129,7 +138,7 @@ async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodi
129 138
130 logger.info('Optimize transcoding job for %s ended.', video.uuid, lTags(video.uuid)) 139 logger.info('Optimize transcoding job for %s ended.', video.uuid, lTags(video.uuid))
131 140
132 await onVideoFileOptimizer(video, payload, transcodeType, user) 141 await onVideoFirstWebTorrentTranscoding(video, payload, transcodeType, user)
133} 142}
134 143
135// --------------------------------------------------------------------------- 144// ---------------------------------------------------------------------------
@@ -159,7 +168,7 @@ async function onHlsPlaylistGeneration (video: MVideoFullLight, user: MUser, pay
159 await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo) 168 await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo)
160} 169}
161 170
162async function onVideoFileOptimizer ( 171async function onVideoFirstWebTorrentTranscoding (
163 videoArg: MVideoWithFile, 172 videoArg: MVideoWithFile,
164 payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload, 173 payload: OptimizeTranscodingPayload | MergeAudioTranscodingPayload,
165 transcodeType: TranscodeOptionsType, 174 transcodeType: TranscodeOptionsType,
@@ -211,6 +220,8 @@ async function onNewWebTorrentFileResolution (
211 await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo) 220 await retryTransactionWrapper(moveToNextState, video, payload.isNewVideo)
212} 221}
213 222
223// ---------------------------------------------------------------------------
224
214async function createHlsJobIfEnabled (user: MUserId, payload: { 225async function createHlsJobIfEnabled (user: MUserId, payload: {
215 videoUUID: string 226 videoUUID: string
216 resolution: number 227 resolution: number
@@ -241,16 +252,6 @@ async function createHlsJobIfEnabled (user: MUserId, payload: {
241 return true 252 return true
242} 253}
243 254
244// ---------------------------------------------------------------------------
245
246export {
247 processVideoTranscoding,
248 createHlsJobIfEnabled,
249 onNewWebTorrentFileResolution
250}
251
252// ---------------------------------------------------------------------------
253
254async function createLowerResolutionsJobs (options: { 255async function createLowerResolutionsJobs (options: {
255 video: MVideoFullLight 256 video: MVideoFullLight
256 user: MUserId 257 user: MUserId
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index 4916decbf..3ebdbc33d 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -211,7 +211,7 @@ const videosAddResumableInitValidator = getCommonVideoEditAttributes().concat([
211 const videoFileMetadata = { 211 const videoFileMetadata = {
212 mimetype: req.headers['x-upload-content-type'] as string, 212 mimetype: req.headers['x-upload-content-type'] as string,
213 size: +req.headers['x-upload-content-length'], 213 size: +req.headers['x-upload-content-length'],
214 originalname: req.body.name 214 originalname: req.body.filename
215 } 215 }
216 216
217 const user = res.locals.oauth.token.User 217 const user = res.locals.oauth.token.User
diff --git a/server/models/video/video-job-info.ts b/server/models/video/video-job-info.ts
index cb1f3f2f0..7da5128d7 100644
--- a/server/models/video/video-job-info.ts
+++ b/server/models/video/video-job-info.ts
@@ -3,6 +3,8 @@ import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Mo
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/core-utils'
4import { VideoModel } from './video' 4import { VideoModel } from './video'
5 5
6export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
7
6@Table({ 8@Table({
7 tableName: 'videoJobInfo', 9 tableName: 'videoJobInfo',
8 indexes: [ 10 indexes: [
@@ -57,7 +59,7 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
57 return VideoJobInfoModel.findOne({ where, transaction }) 59 return VideoJobInfoModel.findOne({ where, transaction })
58 } 60 }
59 61
60 static async increaseOrCreate (videoUUID: string, column: 'pendingMove' | 'pendingTranscode'): Promise<number> { 62 static async increaseOrCreate (videoUUID: string, column: VideoJobInfoColumnType): Promise<number> {
61 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } } 63 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
62 64
63 const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(` 65 const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(`
@@ -79,7 +81,7 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
79 return pendingMove 81 return pendingMove
80 } 82 }
81 83
82 static async decrease (videoUUID: string, column: 'pendingMove' | 'pendingTranscode'): Promise<number> { 84 static async decrease (videoUUID: string, column: VideoJobInfoColumnType): Promise<number> {
83 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } } 85 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
84 86
85 const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(` 87 const [ { pendingMove } ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(`