aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--server/controllers/api/videos/index.ts1
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts1
-rw-r--r--server/lib/activitypub/process/process-create.ts4
-rw-r--r--server/lib/activitypub/process/process-update.ts4
-rw-r--r--server/lib/activitypub/videos.ts22
-rw-r--r--server/lib/moderation.ts4
-rw-r--r--server/models/video/video-format-utils.ts5
-rw-r--r--server/models/video/video.ts4
-rw-r--r--shared/models/activitypub/activity.ts6
-rw-r--r--shared/models/activitypub/objects/video-torrent-object.ts5
10 files changed, 30 insertions, 26 deletions
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts
index 1539afc35..6357062bc 100644
--- a/server/controllers/api/videos/index.ts
+++ b/server/controllers/api/videos/index.ts
@@ -55,7 +55,6 @@ import {
55 videosUpdateValidator 55 videosUpdateValidator
56} from '../../../middlewares' 56} from '../../../middlewares'
57import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' 57import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
58import { TagModel } from '../../../models/video/tag'
59import { VideoModel } from '../../../models/video/video' 58import { VideoModel } from '../../../models/video/video'
60import { VideoFileModel } from '../../../models/video/video-file' 59import { VideoFileModel } from '../../../models/video/video-file'
61import { abuseVideoRouter } from './abuse' 60import { abuseVideoRouter } from './abuse'
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index 876cc7f50..7ff551ecd 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -62,6 +62,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) {
62 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false 62 if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
63 if (!isBooleanValid(video.downloadEnabled)) video.downloadEnabled = true 63 if (!isBooleanValid(video.downloadEnabled)) video.downloadEnabled = true
64 if (!isBooleanValid(video.commentsEnabled)) video.commentsEnabled = false 64 if (!isBooleanValid(video.commentsEnabled)) video.commentsEnabled = false
65 if (!isBooleanValid(video.isLiveBroadcast)) video.isLiveBroadcast = false
65 66
66 return isActivityPubUrlValid(video.id) && 67 return isActivityPubUrlValid(video.id) &&
67 isVideoNameValid(video.name) && 68 isVideoNameValid(video.name) &&
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index 74f1032e2..f84992489 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -1,5 +1,5 @@
1import { isRedundancyAccepted } from '@server/lib/redundancy' 1import { isRedundancyAccepted } from '@server/lib/redundancy'
2import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared' 2import { ActivityCreate, CacheFileObject, VideoObject } from '../../../../shared'
3import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' 3import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
4import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' 4import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
5import { retryTransactionWrapper } from '../../../helpers/database-utils' 5import { retryTransactionWrapper } from '../../../helpers/database-utils'
@@ -52,7 +52,7 @@ export {
52// --------------------------------------------------------------------------- 52// ---------------------------------------------------------------------------
53 53
54async function processCreateVideo (activity: ActivityCreate, notify: boolean) { 54async function processCreateVideo (activity: ActivityCreate, notify: boolean) {
55 const videoToCreateData = activity.object as VideoTorrentObject 55 const videoToCreateData = activity.object as VideoObject
56 56
57 const syncParam = { likes: false, dislikes: false, shares: false, comments: false, thumbnail: true, refreshVideo: false } 57 const syncParam = { likes: false, dislikes: false, shares: false, comments: false, thumbnail: true, refreshVideo: false }
58 const { video, created } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoToCreateData, syncParam }) 58 const { video, created } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoToCreateData, syncParam })
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts
index 1bdf23d6f..6d2fff3fe 100644
--- a/server/lib/activitypub/process/process-update.ts
+++ b/server/lib/activitypub/process/process-update.ts
@@ -1,4 +1,4 @@
1import { ActivityUpdate, CacheFileObject, VideoTorrentObject } from '../../../../shared/models/activitypub' 1import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub'
2import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' 2import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor'
3import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' 3import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
@@ -55,7 +55,7 @@ export {
55// --------------------------------------------------------------------------- 55// ---------------------------------------------------------------------------
56 56
57async function processUpdateVideo (actor: MActorSignature, activity: ActivityUpdate) { 57async function processUpdateVideo (actor: MActorSignature, activity: ActivityUpdate) {
58 const videoObject = activity.object as VideoTorrentObject 58 const videoObject = activity.object as VideoObject
59 59
60 if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) { 60 if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) {
61 logger.debug('Video sent by update is not valid.', { videoObject }) 61 logger.debug('Video sent by update is not valid.', { videoObject })
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 096884776..049e06cff 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -15,7 +15,7 @@ import {
15 ActivityVideoUrlObject, 15 ActivityVideoUrlObject,
16 VideoState 16 VideoState
17} from '../../../shared/index' 17} from '../../../shared/index'
18import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' 18import { VideoObject } from '../../../shared/models/activitypub/objects'
19import { VideoPrivacy } from '../../../shared/models/videos' 19import { VideoPrivacy } from '../../../shared/models/videos'
20import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 20import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
21import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' 21import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
@@ -38,7 +38,6 @@ import {
38} from '../../initializers/constants' 38} from '../../initializers/constants'
39import { sequelizeTypescript } from '../../initializers/database' 39import { sequelizeTypescript } from '../../initializers/database'
40import { AccountVideoRateModel } from '../../models/account/account-video-rate' 40import { AccountVideoRateModel } from '../../models/account/account-video-rate'
41import { TagModel } from '../../models/video/tag'
42import { VideoModel } from '../../models/video/video' 41import { VideoModel } from '../../models/video/video'
43import { VideoCaptionModel } from '../../models/video/video-caption' 42import { VideoCaptionModel } from '../../models/video/video-caption'
44import { VideoCommentModel } from '../../models/video/video-comment' 43import { VideoCommentModel } from '../../models/video/video-comment'
@@ -104,7 +103,7 @@ async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVid
104 } 103 }
105} 104}
106 105
107async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.RequestResponse, videoObject: VideoTorrentObject }> { 106async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.RequestResponse, videoObject: VideoObject }> {
108 const options = { 107 const options = {
109 uri: videoUrl, 108 uri: videoUrl,
110 method: 'GET', 109 method: 'GET',
@@ -136,7 +135,7 @@ async function fetchRemoteVideoDescription (video: MVideoAccountLight) {
136 return body.description ? body.description : '' 135 return body.description ? body.description : ''
137} 136}
138 137
139function getOrCreateVideoChannelFromVideoObject (videoObject: VideoTorrentObject) { 138function getOrCreateVideoChannelFromVideoObject (videoObject: VideoObject) {
140 const channel = videoObject.attributedTo.find(a => a.type === 'Group') 139 const channel = videoObject.attributedTo.find(a => a.type === 'Group')
141 if (!channel) throw new Error('Cannot find associated video channel to video ' + videoObject.url) 140 if (!channel) throw new Error('Cannot find associated video channel to video ' + videoObject.url)
142 141
@@ -155,7 +154,7 @@ type SyncParam = {
155 thumbnail: boolean 154 thumbnail: boolean
156 refreshVideo?: boolean 155 refreshVideo?: boolean
157} 156}
158async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) { 157async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoObject, syncParam: SyncParam) {
159 logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid) 158 logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid)
160 159
161 const jobPayloads: ActivitypubHttpFetcherPayload[] = [] 160 const jobPayloads: ActivitypubHttpFetcherPayload[] = []
@@ -294,7 +293,7 @@ async function getOrCreateVideoAndAccountAndChannel (
294 293
295async function updateVideoFromAP (options: { 294async function updateVideoFromAP (options: {
296 video: MVideoAccountLightBlacklistAllFiles 295 video: MVideoAccountLightBlacklistAllFiles
297 videoObject: VideoTorrentObject 296 videoObject: VideoObject
298 account: MAccountIdActor 297 account: MAccountIdActor
299 channel: MChannelDefault 298 channel: MChannelDefault
300 overrideTo?: string[] 299 overrideTo?: string[]
@@ -538,7 +537,7 @@ function isAPHashTagObject (url: any): url is ActivityHashTagObject {
538 return url && url.type === 'Hashtag' 537 return url && url.type === 'Hashtag'
539} 538}
540 539
541async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAccountLight, waitThumbnail = false) { 540async function createVideo (videoObject: VideoObject, channel: MChannelAccountLight, waitThumbnail = false) {
542 logger.debug('Adding remote video %s.', videoObject.id) 541 logger.debug('Adding remote video %s.', videoObject.id)
543 542
544 const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to) 543 const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to)
@@ -632,7 +631,7 @@ async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAc
632 return { autoBlacklisted, videoCreated } 631 return { autoBlacklisted, videoCreated }
633} 632}
634 633
635function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) { 634function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoObject, to: string[] = []) {
636 const privacy = to.includes(ACTIVITY_PUB.PUBLIC) 635 const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
637 ? VideoPrivacy.PUBLIC 636 ? VideoPrivacy.PUBLIC
638 : VideoPrivacy.UNLISTED 637 : VideoPrivacy.UNLISTED
@@ -664,6 +663,7 @@ function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObjec
664 commentsEnabled: videoObject.commentsEnabled, 663 commentsEnabled: videoObject.commentsEnabled,
665 downloadEnabled: videoObject.downloadEnabled, 664 downloadEnabled: videoObject.downloadEnabled,
666 waitTranscoding: videoObject.waitTranscoding, 665 waitTranscoding: videoObject.waitTranscoding,
666 isLive: videoObject.isLiveBroadcast,
667 state: videoObject.state, 667 state: videoObject.state,
668 channelId: videoChannel.id, 668 channelId: videoChannel.id,
669 duration: parseInt(duration, 10), 669 duration: parseInt(duration, 10),
@@ -732,7 +732,7 @@ function videoFileActivityUrlToDBAttributes (
732 return attributes 732 return attributes
733} 733}
734 734
735function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObject: VideoTorrentObject, videoFiles: MVideoFile[]) { 735function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObject: VideoObject, videoFiles: MVideoFile[]) {
736 const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[] 736 const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[]
737 if (playlistUrls.length === 0) return [] 737 if (playlistUrls.length === 0) return []
738 738
@@ -766,7 +766,7 @@ function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObjec
766 return attributes 766 return attributes
767} 767}
768 768
769function getThumbnailFromIcons (videoObject: VideoTorrentObject) { 769function getThumbnailFromIcons (videoObject: VideoObject) {
770 let validIcons = videoObject.icon.filter(i => i.width > THUMBNAILS_SIZE.minWidth) 770 let validIcons = videoObject.icon.filter(i => i.width > THUMBNAILS_SIZE.minWidth)
771 // Fallback if there are not valid icons 771 // Fallback if there are not valid icons
772 if (validIcons.length === 0) validIcons = videoObject.icon 772 if (validIcons.length === 0) validIcons = videoObject.icon
@@ -774,7 +774,7 @@ function getThumbnailFromIcons (videoObject: VideoTorrentObject) {
774 return minBy(validIcons, 'width') 774 return minBy(validIcons, 'width')
775} 775}
776 776
777function getPreviewFromIcons (videoObject: VideoTorrentObject) { 777function getPreviewFromIcons (videoObject: VideoObject) {
778 const validIcons = videoObject.icon.filter(i => i.width > PREVIEWS_SIZE.minWidth) 778 const validIcons = videoObject.icon.filter(i => i.width > PREVIEWS_SIZE.minWidth)
779 779
780 // FIXME: don't put a fallback here for compatibility with PeerTube <2.2 780 // FIXME: don't put a fallback here for compatibility with PeerTube <2.2
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts
index b140d5aa9..0ef26d53d 100644
--- a/server/lib/moderation.ts
+++ b/server/lib/moderation.ts
@@ -18,7 +18,7 @@ import {
18 MVideoAccountLightBlacklistAllFiles 18 MVideoAccountLightBlacklistAllFiles
19} from '@server/types/models' 19} from '@server/types/models'
20import { ActivityCreate } from '../../shared/models/activitypub' 20import { ActivityCreate } from '../../shared/models/activitypub'
21import { VideoTorrentObject } from '../../shared/models/activitypub/objects' 21import { VideoObject } from '../../shared/models/activitypub/objects'
22import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' 22import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
23import { VideoCreate, VideoImportCreate } from '../../shared/models/videos' 23import { VideoCreate, VideoImportCreate } from '../../shared/models/videos'
24import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' 24import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model'
@@ -62,7 +62,7 @@ function isLocalVideoCommentReplyAccepted (_object: {
62 62
63function isRemoteVideoAccepted (_object: { 63function isRemoteVideoAccepted (_object: {
64 activity: ActivityCreate 64 activity: ActivityCreate
65 videoAP: VideoTorrentObject 65 videoAP: VideoObject
66 byActor: ActorModel 66 byActor: ActorModel
67}): AcceptResult { 67}): AcceptResult {
68 return { accepted: true } 68 return { accepted: true }
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts
index 0dbd92a43..92bde7773 100644
--- a/server/models/video/video-format-utils.ts
+++ b/server/models/video/video-format-utils.ts
@@ -1,6 +1,6 @@
1import { Video, VideoDetails } from '../../../shared/models/videos' 1import { Video, VideoDetails } from '../../../shared/models/videos'
2import { VideoModel } from './video' 2import { VideoModel } from './video'
3import { ActivityTagObject, ActivityUrlObject, VideoTorrentObject } from '../../../shared/models/activitypub/objects' 3import { ActivityTagObject, ActivityUrlObject, VideoObject } from '../../../shared/models/activitypub/objects'
4import { MIMETYPES, WEBSERVER } from '../../initializers/constants' 4import { MIMETYPES, WEBSERVER } from '../../initializers/constants'
5import { VideoCaptionModel } from './video-caption' 5import { VideoCaptionModel } from './video-caption'
6import { 6import {
@@ -262,7 +262,7 @@ function addVideoFilesInAPAcc (
262 } 262 }
263} 263}
264 264
265function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject { 265function videoModelToActivityPubObject (video: MVideoAP): VideoObject {
266 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls() 266 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
267 if (!video.Tags) video.Tags = [] 267 if (!video.Tags) video.Tags = []
268 268
@@ -351,6 +351,7 @@ function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
351 views: video.views, 351 views: video.views,
352 sensitive: video.nsfw, 352 sensitive: video.nsfw,
353 waitTranscoding: video.waitTranscoding, 353 waitTranscoding: video.waitTranscoding,
354 isLiveBroadcast: video.isLive,
354 state: video.state, 355 state: video.state,
355 commentsEnabled: video.commentsEnabled, 356 commentsEnabled: video.commentsEnabled,
356 downloadEnabled: video.downloadEnabled, 357 downloadEnabled: video.downloadEnabled,
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 1037730e3..a3e3b6cfe 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -31,7 +31,7 @@ import { getServerActor } from '@server/models/application/application'
31import { ModelCache } from '@server/models/model-cache' 31import { ModelCache } from '@server/models/model-cache'
32import { VideoFile } from '@shared/models/videos/video-file.model' 32import { VideoFile } from '@shared/models/videos/video-file.model'
33import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' 33import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
34import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' 34import { VideoObject } from '../../../shared/models/activitypub/objects'
35import { Video, VideoDetails } from '../../../shared/models/videos' 35import { Video, VideoDetails } from '../../../shared/models/videos'
36import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 36import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
37import { VideoFilter } from '../../../shared/models/videos/video-query.type' 37import { VideoFilter } from '../../../shared/models/videos/video-query.type'
@@ -1763,7 +1763,7 @@ export class VideoModel extends Model<VideoModel> {
1763 return videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, files) 1763 return videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, files)
1764 } 1764 }
1765 1765
1766 toActivityPubObject (this: MVideoAP): VideoTorrentObject { 1766 toActivityPubObject (this: MVideoAP): VideoObject {
1767 return videoModelToActivityPubObject(this) 1767 return videoModelToActivityPubObject(this)
1768 } 1768 }
1769 1769
diff --git a/shared/models/activitypub/activity.ts b/shared/models/activitypub/activity.ts
index 5b4ce214a..548d8858e 100644
--- a/shared/models/activitypub/activity.ts
+++ b/shared/models/activitypub/activity.ts
@@ -1,6 +1,6 @@
1import { ActivityPubActor } from './activitypub-actor' 1import { ActivityPubActor } from './activitypub-actor'
2import { ActivityPubSignature } from './activitypub-signature' 2import { ActivityPubSignature } from './activitypub-signature'
3import { ActivityFlagReasonObject, CacheFileObject, VideoTorrentObject } from './objects' 3import { ActivityFlagReasonObject, CacheFileObject, VideoObject } from './objects'
4import { AbuseObject } from './objects/abuse-object' 4import { AbuseObject } from './objects/abuse-object'
5import { DislikeObject } from './objects/dislike-object' 5import { DislikeObject } from './objects/dislike-object'
6import { APObject } from './objects/object.model' 6import { APObject } from './objects/object.model'
@@ -53,12 +53,12 @@ export interface BaseActivity {
53 53
54export interface ActivityCreate extends BaseActivity { 54export interface ActivityCreate extends BaseActivity {
55 type: 'Create' 55 type: 'Create'
56 object: VideoTorrentObject | AbuseObject | ViewObject | DislikeObject | VideoCommentObject | CacheFileObject | PlaylistObject 56 object: VideoObject | AbuseObject | ViewObject | DislikeObject | VideoCommentObject | CacheFileObject | PlaylistObject
57} 57}
58 58
59export interface ActivityUpdate extends BaseActivity { 59export interface ActivityUpdate extends BaseActivity {
60 type: 'Update' 60 type: 'Update'
61 object: VideoTorrentObject | ActivityPubActor | CacheFileObject | PlaylistObject 61 object: VideoObject | ActivityPubActor | CacheFileObject | PlaylistObject
62} 62}
63 63
64export interface ActivityDelete extends BaseActivity { 64export interface ActivityDelete extends BaseActivity {
diff --git a/shared/models/activitypub/objects/video-torrent-object.ts b/shared/models/activitypub/objects/video-torrent-object.ts
index 11de8fc56..5b035a371 100644
--- a/shared/models/activitypub/objects/video-torrent-object.ts
+++ b/shared/models/activitypub/objects/video-torrent-object.ts
@@ -7,7 +7,7 @@ import {
7} from './common-objects' 7} from './common-objects'
8import { VideoState } from '../../videos' 8import { VideoState } from '../../videos'
9 9
10export interface VideoTorrentObject { 10export interface VideoObject {
11 type: 'Video' 11 type: 'Video'
12 id: string 12 id: string
13 name: string 13 name: string
@@ -19,7 +19,10 @@ export interface VideoTorrentObject {
19 language: ActivityIdentifierObject 19 language: ActivityIdentifierObject
20 subtitleLanguage: ActivityIdentifierObject[] 20 subtitleLanguage: ActivityIdentifierObject[]
21 views: number 21 views: number
22
22 sensitive: boolean 23 sensitive: boolean
24 isLiveBroadcast: boolean
25
23 commentsEnabled: boolean 26 commentsEnabled: boolean
24 downloadEnabled: boolean 27 downloadEnabled: boolean
25 waitTranscoding: boolean 28 waitTranscoding: boolean