diff options
author | Chocobozzz <me@florianbigard.com> | 2018-07-12 19:02:00 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-07-16 11:50:08 +0200 |
commit | 40e87e9ecc54e3513fb586928330a7855eb192c6 (patch) | |
tree | af1111ecba85f9cd8286811ff332a67cf21be2f6 /server/lib/activitypub | |
parent | d4557fd3ecc8d4ed4fb0e5c868929bc36c959ed2 (diff) | |
download | PeerTube-40e87e9ecc54e3513fb586928330a7855eb192c6.tar.gz PeerTube-40e87e9ecc54e3513fb586928330a7855eb192c6.tar.zst PeerTube-40e87e9ecc54e3513fb586928330a7855eb192c6.zip |
Implement captions/subtitles
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r-- | server/lib/activitypub/process/process-update.ts | 12 | ||||
-rw-r--r-- | server/lib/activitypub/videos.ts | 29 |
2 files changed, 34 insertions, 7 deletions
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index 73db461c3..62791ff1b 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -19,6 +19,7 @@ import { | |||
19 | videoFileActivityUrlToDBAttributes | 19 | videoFileActivityUrlToDBAttributes |
20 | } from '../videos' | 20 | } from '../videos' |
21 | import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos' | 21 | import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos' |
22 | import { VideoCaptionModel } from '../../../models/video/video-caption' | ||
22 | 23 | ||
23 | async function processUpdateActivity (activity: ActivityUpdate) { | 24 | async function processUpdateActivity (activity: ActivityUpdate) { |
24 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) | 25 | const actor = await getOrCreateActorAndServerAndModel(activity.actor) |
@@ -110,9 +111,18 @@ async function processUpdateVideo (actor: ActorModel, activity: ActivityUpdate) | |||
110 | const tasks = videoFileAttributes.map(f => VideoFileModel.create(f)) | 111 | const tasks = videoFileAttributes.map(f => VideoFileModel.create(f)) |
111 | await Promise.all(tasks) | 112 | await Promise.all(tasks) |
112 | 113 | ||
113 | const tags = videoObject.tag.map(t => t.name) | 114 | // Update Tags |
115 | const tags = videoObject.tag.map(tag => tag.name) | ||
114 | const tagInstances = await TagModel.findOrCreateTags(tags, t) | 116 | const tagInstances = await TagModel.findOrCreateTags(tags, t) |
115 | await videoInstance.$set('Tags', tagInstances, sequelizeOptions) | 117 | await videoInstance.$set('Tags', tagInstances, sequelizeOptions) |
118 | |||
119 | // Update captions | ||
120 | await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(videoInstance.id, t) | ||
121 | |||
122 | const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => { | ||
123 | return VideoCaptionModel.insertOrReplaceLanguage(videoInstance.id, c.identifier, t) | ||
124 | }) | ||
125 | await Promise.all(videoCaptionsPromises) | ||
116 | }) | 126 | }) |
117 | 127 | ||
118 | logger.info('Remote video with uuid %s updated', videoObject.uuid) | 128 | logger.info('Remote video with uuid %s updated', videoObject.uuid) |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index a16828fda..fdc082b61 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -24,10 +24,20 @@ import { addVideoComments } from './video-comments' | |||
24 | import { crawlCollectionPage } from './crawl' | 24 | import { crawlCollectionPage } from './crawl' |
25 | import { sendCreateVideo, sendUpdateVideo } from './send' | 25 | import { sendCreateVideo, sendUpdateVideo } from './send' |
26 | import { shareVideoByServerAndChannel } from './index' | 26 | import { shareVideoByServerAndChannel } from './index' |
27 | import { isArray } from '../../helpers/custom-validators/misc' | ||
28 | import { VideoCaptionModel } from '../../models/video/video-caption' | ||
27 | 29 | ||
28 | async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) { | 30 | async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) { |
29 | // If the video is not private and published, we federate it | 31 | // If the video is not private and published, we federate it |
30 | if (video.privacy !== VideoPrivacy.PRIVATE && video.state === VideoState.PUBLISHED) { | 32 | if (video.privacy !== VideoPrivacy.PRIVATE && video.state === VideoState.PUBLISHED) { |
33 | // Fetch more attributes that we will need to serialize in AP object | ||
34 | if (isArray(video.VideoCaptions) === false) { | ||
35 | video.VideoCaptions = await video.$get('VideoCaptions', { | ||
36 | attributes: [ 'language' ], | ||
37 | transaction | ||
38 | }) as VideoCaptionModel[] | ||
39 | } | ||
40 | |||
31 | if (isNewVideo === true) { | 41 | if (isNewVideo === true) { |
32 | // Now we'll add the video's meta data to our followers | 42 | // Now we'll add the video's meta data to our followers |
33 | await sendCreateVideo(video, transaction) | 43 | await sendCreateVideo(video, transaction) |
@@ -38,9 +48,8 @@ async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, tr | |||
38 | } | 48 | } |
39 | } | 49 | } |
40 | 50 | ||
41 | function fetchRemoteVideoPreview (video: VideoModel, reject: Function) { | 51 | function fetchRemoteVideoStaticFile (video: VideoModel, path: string, reject: Function) { |
42 | const host = video.VideoChannel.Account.Actor.Server.host | 52 | const host = video.VideoChannel.Account.Actor.Server.host |
43 | const path = join(STATIC_PATHS.PREVIEWS, video.getPreviewName()) | ||
44 | 53 | ||
45 | // We need to provide a callback, if no we could have an uncaught exception | 54 | // We need to provide a callback, if no we could have an uncaught exception |
46 | return request.get(REMOTE_SCHEME.HTTP + '://' + host + path, err => { | 55 | return request.get(REMOTE_SCHEME.HTTP + '://' + host + path, err => { |
@@ -179,24 +188,32 @@ async function getOrCreateVideo (videoObject: VideoTorrentObject, channelActor: | |||
179 | const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoObject, videoObject.to) | 188 | const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoObject, videoObject.to) |
180 | const video = VideoModel.build(videoData) | 189 | const video = VideoModel.build(videoData) |
181 | 190 | ||
182 | // Don't block on request | 191 | // Don't block on remote HTTP request (we are in a transaction!) |
183 | generateThumbnailFromUrl(video, videoObject.icon) | 192 | generateThumbnailFromUrl(video, videoObject.icon) |
184 | .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err })) | 193 | .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoObject.id, { err })) |
185 | 194 | ||
186 | const videoCreated = await video.save(sequelizeOptions) | 195 | const videoCreated = await video.save(sequelizeOptions) |
187 | 196 | ||
197 | // Process files | ||
188 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject) | 198 | const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoObject) |
189 | if (videoFileAttributes.length === 0) { | 199 | if (videoFileAttributes.length === 0) { |
190 | throw new Error('Cannot find valid files for video %s ' + videoObject.url) | 200 | throw new Error('Cannot find valid files for video %s ' + videoObject.url) |
191 | } | 201 | } |
192 | 202 | ||
193 | const tasks = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) | 203 | const videoFilePromises = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t })) |
194 | await Promise.all(tasks) | 204 | await Promise.all(videoFilePromises) |
195 | 205 | ||
206 | // Process tags | ||
196 | const tags = videoObject.tag.map(t => t.name) | 207 | const tags = videoObject.tag.map(t => t.name) |
197 | const tagInstances = await TagModel.findOrCreateTags(tags, t) | 208 | const tagInstances = await TagModel.findOrCreateTags(tags, t) |
198 | await videoCreated.$set('Tags', tagInstances, sequelizeOptions) | 209 | await videoCreated.$set('Tags', tagInstances, sequelizeOptions) |
199 | 210 | ||
211 | // Process captions | ||
212 | const videoCaptionsPromises = videoObject.subtitleLanguage.map(c => { | ||
213 | return VideoCaptionModel.insertOrReplaceLanguage(videoCreated.id, c.identifier, t) | ||
214 | }) | ||
215 | await Promise.all(videoCaptionsPromises) | ||
216 | |||
200 | logger.info('Remote video with uuid %s inserted.', videoObject.uuid) | 217 | logger.info('Remote video with uuid %s inserted.', videoObject.uuid) |
201 | 218 | ||
202 | videoCreated.VideoChannel = channelActor.VideoChannel | 219 | videoCreated.VideoChannel = channelActor.VideoChannel |
@@ -328,7 +345,7 @@ export { | |||
328 | federateVideoIfNeeded, | 345 | federateVideoIfNeeded, |
329 | fetchRemoteVideo, | 346 | fetchRemoteVideo, |
330 | getOrCreateAccountAndVideoAndChannel, | 347 | getOrCreateAccountAndVideoAndChannel, |
331 | fetchRemoteVideoPreview, | 348 | fetchRemoteVideoStaticFile, |
332 | fetchRemoteVideoDescription, | 349 | fetchRemoteVideoDescription, |
333 | generateThumbnailFromUrl, | 350 | generateThumbnailFromUrl, |
334 | videoActivityObjectToDBAttributes, | 351 | videoActivityObjectToDBAttributes, |