diff options
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 @@ | |||
1 | import { truncate } from 'lodash-es' | ||
1 | import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' | 2 | import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' |
3 | import { isIOS } from 'src/assets/player/utils' | ||
2 | import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' | 4 | import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' |
3 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' | 5 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' |
4 | import { Router } from '@angular/router' | 6 | import { Router } from '@angular/router' |
@@ -10,7 +12,6 @@ import { LoadingBarService } from '@ngx-loading-bar/core' | |||
10 | import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models' | 12 | import { HttpStatusCode, VideoCreateResult, VideoPrivacy } from '@shared/models' |
11 | import { UploaderXFormData } from './uploaderx-form-data' | 13 | import { UploaderXFormData } from './uploaderx-form-data' |
12 | import { VideoSend } from './video-send' | 14 | import { VideoSend } from './video-send' |
13 | import { 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 | |||
76 | export { | ||
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 | ||
125 | async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) { | 134 | async 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 | ||
162 | async function onVideoFileOptimizer ( | 171 | async 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 | |||
214 | async function createHlsJobIfEnabled (user: MUserId, payload: { | 225 | async 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 | |||
246 | export { | ||
247 | processVideoTranscoding, | ||
248 | createHlsJobIfEnabled, | ||
249 | onNewWebTorrentFileResolution | ||
250 | } | ||
251 | |||
252 | // --------------------------------------------------------------------------- | ||
253 | |||
254 | async function createLowerResolutionsJobs (options: { | 255 | async 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 | |||
3 | import { AttributesOnly } from '@shared/core-utils' | 3 | import { AttributesOnly } from '@shared/core-utils' |
4 | import { VideoModel } from './video' | 4 | import { VideoModel } from './video' |
5 | 5 | ||
6 | export 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 }>(` |