aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-06-12 20:04:58 +0200
committerChocobozzz <me@florianbigard.com>2018-06-12 20:37:51 +0200
commit2186386cca113506791583cb07d6ccacba7af4e0 (patch)
tree3c214c0b5fbd64332624267fa6e51fd4a9cf6474 /server/models/video
parent6ccdf3a23ecec5ba2eeaf487fd1fafdc7606b4bf (diff)
downloadPeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.gz
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.zst
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.zip
Add concept of video state, and add ability to wait transcoding before
publishing a video
Diffstat (limited to 'server/models/video')
-rw-r--r--server/models/video/video.ts132
1 files changed, 67 insertions, 65 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 1cb1e6798..59c378efa 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -25,7 +25,7 @@ import {
25 Table, 25 Table,
26 UpdatedAt 26 UpdatedAt
27} from 'sequelize-typescript' 27} from 'sequelize-typescript'
28import { VideoPrivacy, VideoResolution } from '../../../shared' 28import { VideoPrivacy, VideoResolution, VideoState } from '../../../shared'
29import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' 29import { VideoTorrentObject } from '../../../shared/models/activitypub/objects'
30import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos' 30import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos'
31import { VideoFilter } from '../../../shared/models/videos/video-query.type' 31import { VideoFilter } from '../../../shared/models/videos/video-query.type'
@@ -47,7 +47,7 @@ import {
47 isVideoLanguageValid, 47 isVideoLanguageValid,
48 isVideoLicenceValid, 48 isVideoLicenceValid,
49 isVideoNameValid, 49 isVideoNameValid,
50 isVideoPrivacyValid, 50 isVideoPrivacyValid, isVideoStateValid,
51 isVideoSupportValid 51 isVideoSupportValid
52} from '../../helpers/custom-validators/videos' 52} from '../../helpers/custom-validators/videos'
53import { generateImageFromVideoFile, getVideoFileResolution, transcode } from '../../helpers/ffmpeg-utils' 53import { generateImageFromVideoFile, getVideoFileResolution, transcode } from '../../helpers/ffmpeg-utils'
@@ -66,7 +66,7 @@ import {
66 VIDEO_EXT_MIMETYPE, 66 VIDEO_EXT_MIMETYPE,
67 VIDEO_LANGUAGES, 67 VIDEO_LANGUAGES,
68 VIDEO_LICENCES, 68 VIDEO_LICENCES,
69 VIDEO_PRIVACIES 69 VIDEO_PRIVACIES, VIDEO_STATES
70} from '../../initializers' 70} from '../../initializers'
71import { 71import {
72 getVideoCommentsActivityPubUrl, 72 getVideoCommentsActivityPubUrl,
@@ -93,10 +93,7 @@ enum ScopeNames {
93 AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST', 93 AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
94 WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS', 94 WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS',
95 WITH_TAGS = 'WITH_TAGS', 95 WITH_TAGS = 'WITH_TAGS',
96 WITH_FILES = 'WITH_FILES', 96 WITH_FILES = 'WITH_FILES'
97 WITH_SHARES = 'WITH_SHARES',
98 WITH_RATES = 'WITH_RATES',
99 WITH_COMMENTS = 'WITH_COMMENTS'
100} 97}
101 98
102@Scopes({ 99@Scopes({
@@ -183,7 +180,20 @@ enum ScopeNames {
183 ')' 180 ')'
184 ) 181 )
185 }, 182 },
186 privacy: VideoPrivacy.PUBLIC 183 // Always list public videos
184 privacy: VideoPrivacy.PUBLIC,
185 // Always list published videos, or videos that are being transcoded but on which we don't want to wait for transcoding
186 [ Sequelize.Op.or ]: [
187 {
188 state: VideoState.PUBLISHED
189 },
190 {
191 [ Sequelize.Op.and ]: {
192 state: VideoState.TO_TRANSCODE,
193 waitTranscoding: false
194 }
195 }
196 ]
187 }, 197 },
188 include: [ videoChannelInclude ] 198 include: [ videoChannelInclude ]
189 } 199 }
@@ -272,42 +282,6 @@ enum ScopeNames {
272 required: true 282 required: true
273 } 283 }
274 ] 284 ]
275 },
276 [ScopeNames.WITH_SHARES]: {
277 include: [
278 {
279 ['separate' as any]: true,
280 model: () => VideoShareModel.unscoped()
281 }
282 ]
283 },
284 [ScopeNames.WITH_RATES]: {
285 include: [
286 {
287 ['separate' as any]: true,
288 model: () => AccountVideoRateModel,
289 include: [
290 {
291 model: () => AccountModel.unscoped(),
292 required: true,
293 include: [
294 {
295 attributes: [ 'url' ],
296 model: () => ActorModel.unscoped()
297 }
298 ]
299 }
300 ]
301 }
302 ]
303 },
304 [ScopeNames.WITH_COMMENTS]: {
305 include: [
306 {
307 ['separate' as any]: true,
308 model: () => VideoCommentModel.unscoped()
309 }
310 ]
311 } 285 }
312}) 286})
313@Table({ 287@Table({
@@ -335,7 +309,7 @@ enum ScopeNames {
335 fields: [ 'channelId' ] 309 fields: [ 'channelId' ]
336 }, 310 },
337 { 311 {
338 fields: [ 'id', 'privacy' ] 312 fields: [ 'id', 'privacy', 'state', 'waitTranscoding' ]
339 }, 313 },
340 { 314 {
341 fields: [ 'url'], 315 fields: [ 'url'],
@@ -435,6 +409,16 @@ export class VideoModel extends Model<VideoModel> {
435 @Column 409 @Column
436 commentsEnabled: boolean 410 commentsEnabled: boolean
437 411
412 @AllowNull(false)
413 @Column
414 waitTranscoding: boolean
415
416 @AllowNull(false)
417 @Default(null)
418 @Is('VideoState', value => throwIfNotValid(value, isVideoStateValid, 'state'))
419 @Column
420 state: VideoState
421
438 @CreatedAt 422 @CreatedAt
439 createdAt: Date 423 createdAt: Date
440 424
@@ -671,7 +655,7 @@ export class VideoModel extends Model<VideoModel> {
671 }) 655 })
672 } 656 }
673 657
674 static listAccountVideosForApi (accountId: number, start: number, count: number, sort: string, hideNSFW: boolean, withFiles = false) { 658 static listUserVideosForApi (accountId: number, start: number, count: number, sort: string, hideNSFW: boolean, withFiles = false) {
675 const query: IFindOptions<VideoModel> = { 659 const query: IFindOptions<VideoModel> = {
676 offset: start, 660 offset: start,
677 limit: count, 661 limit: count,
@@ -858,12 +842,13 @@ export class VideoModel extends Model<VideoModel> {
858 .findOne(options) 842 .findOne(options)
859 } 843 }
860 844
861 static loadByUUIDAndPopulateAccountAndServerAndTags (uuid: string) { 845 static loadByUUIDAndPopulateAccountAndServerAndTags (uuid: string, t?: Sequelize.Transaction) {
862 const options = { 846 const options = {
863 order: [ [ 'Tags', 'name', 'ASC' ] ], 847 order: [ [ 'Tags', 'name', 'ASC' ] ],
864 where: { 848 where: {
865 uuid 849 uuid
866 } 850 },
851 transaction: t
867 } 852 }
868 853
869 return VideoModel 854 return VideoModel
@@ -905,31 +890,23 @@ export class VideoModel extends Model<VideoModel> {
905 } 890 }
906 891
907 private static getCategoryLabel (id: number) { 892 private static getCategoryLabel (id: number) {
908 let categoryLabel = VIDEO_CATEGORIES[id] 893 return VIDEO_CATEGORIES[id] || 'Misc'
909 if (!categoryLabel) categoryLabel = 'Misc'
910
911 return categoryLabel
912 } 894 }
913 895
914 private static getLicenceLabel (id: number) { 896 private static getLicenceLabel (id: number) {
915 let licenceLabel = VIDEO_LICENCES[id] 897 return VIDEO_LICENCES[id] || 'Unknown'
916 if (!licenceLabel) licenceLabel = 'Unknown'
917
918 return licenceLabel
919 } 898 }
920 899
921 private static getLanguageLabel (id: string) { 900 private static getLanguageLabel (id: string) {
922 let languageLabel = VIDEO_LANGUAGES[id] 901 return VIDEO_LANGUAGES[id] || 'Unknown'
923 if (!languageLabel) languageLabel = 'Unknown'
924
925 return languageLabel
926 } 902 }
927 903
928 private static getPrivacyLabel (id: number) { 904 private static getPrivacyLabel (id: number) {
929 let privacyLabel = VIDEO_PRIVACIES[id] 905 return VIDEO_PRIVACIES[id] || 'Unknown'
930 if (!privacyLabel) privacyLabel = 'Unknown' 906 }
931 907
932 return privacyLabel 908 private static getStateLabel (id: number) {
909 return VIDEO_STATES[id] || 'Unknown'
933 } 910 }
934 911
935 getOriginalFile () { 912 getOriginalFile () {
@@ -1026,11 +1003,16 @@ export class VideoModel extends Model<VideoModel> {
1026 return join(STATIC_PATHS.PREVIEWS, this.getPreviewName()) 1003 return join(STATIC_PATHS.PREVIEWS, this.getPreviewName())
1027 } 1004 }
1028 1005
1029 toFormattedJSON (): Video { 1006 toFormattedJSON (options?: {
1007 additionalAttributes: {
1008 state: boolean,
1009 waitTranscoding: boolean
1010 }
1011 }): Video {
1030 const formattedAccount = this.VideoChannel.Account.toFormattedJSON() 1012 const formattedAccount = this.VideoChannel.Account.toFormattedJSON()
1031 const formattedVideoChannel = this.VideoChannel.toFormattedJSON() 1013 const formattedVideoChannel = this.VideoChannel.toFormattedJSON()
1032 1014
1033 return { 1015 const videoObject: Video = {
1034 id: this.id, 1016 id: this.id,
1035 uuid: this.uuid, 1017 uuid: this.uuid,
1036 name: this.name, 1018 name: this.name,
@@ -1082,6 +1064,19 @@ export class VideoModel extends Model<VideoModel> {
1082 avatar: formattedVideoChannel.avatar 1064 avatar: formattedVideoChannel.avatar
1083 } 1065 }
1084 } 1066 }
1067
1068 if (options) {
1069 if (options.additionalAttributes.state) {
1070 videoObject.state = {
1071 id: this.state,
1072 label: VideoModel.getStateLabel(this.state)
1073 }
1074 }
1075
1076 if (options.additionalAttributes.waitTranscoding) videoObject.waitTranscoding = this.waitTranscoding
1077 }
1078
1079 return videoObject
1085 } 1080 }
1086 1081
1087 toFormattedDetailsJSON (): VideoDetails { 1082 toFormattedDetailsJSON (): VideoDetails {
@@ -1094,6 +1089,11 @@ export class VideoModel extends Model<VideoModel> {
1094 account: this.VideoChannel.Account.toFormattedJSON(), 1089 account: this.VideoChannel.Account.toFormattedJSON(),
1095 tags: map(this.Tags, 'name'), 1090 tags: map(this.Tags, 'name'),
1096 commentsEnabled: this.commentsEnabled, 1091 commentsEnabled: this.commentsEnabled,
1092 waitTranscoding: this.waitTranscoding,
1093 state: {
1094 id: this.state,
1095 label: VideoModel.getStateLabel(this.state)
1096 },
1097 files: [] 1097 files: []
1098 } 1098 }
1099 1099
@@ -1207,6 +1207,8 @@ export class VideoModel extends Model<VideoModel> {
1207 language, 1207 language,
1208 views: this.views, 1208 views: this.views,
1209 sensitive: this.nsfw, 1209 sensitive: this.nsfw,
1210 waitTranscoding: this.waitTranscoding,
1211 state: this.state,
1210 commentsEnabled: this.commentsEnabled, 1212 commentsEnabled: this.commentsEnabled,
1211 published: this.publishedAt.toISOString(), 1213 published: this.publishedAt.toISOString(),
1212 updated: this.updatedAt.toISOString(), 1214 updated: this.updatedAt.toISOString(),