aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video/video-format-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/video/video-format-utils.ts')
-rw-r--r--server/models/video/video-format-utils.ts127
1 files changed, 74 insertions, 53 deletions
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts
index 2987aa780..9fed2d49d 100644
--- a/server/models/video/video-format-utils.ts
+++ b/server/models/video/video-format-utils.ts
@@ -1,11 +1,6 @@
1import { Video, VideoDetails, VideoFile } from '../../../shared/models/videos' 1import { Video, VideoDetails } from '../../../shared/models/videos'
2import { VideoModel } from './video' 2import { VideoModel } from './video'
3import { 3import { ActivityTagObject, ActivityUrlObject, VideoTorrentObject } from '../../../shared/models/activitypub/objects'
4 ActivityPlaylistInfohashesObject,
5 ActivityPlaylistSegmentHashesObject,
6 ActivityUrlObject,
7 VideoTorrentObject
8} from '../../../shared/models/activitypub/objects'
9import { MIMETYPES, WEBSERVER } from '../../initializers/constants' 4import { MIMETYPES, WEBSERVER } from '../../initializers/constants'
10import { VideoCaptionModel } from './video-caption' 5import { VideoCaptionModel } from './video-caption'
11import { 6import {
@@ -16,9 +11,18 @@ import {
16} from '../../lib/activitypub' 11} from '../../lib/activitypub'
17import { isArray } from '../../helpers/custom-validators/misc' 12import { isArray } from '../../helpers/custom-validators/misc'
18import { VideoStreamingPlaylist } from '../../../shared/models/videos/video-streaming-playlist.model' 13import { VideoStreamingPlaylist } from '../../../shared/models/videos/video-streaming-playlist.model'
19import { MStreamingPlaylistRedundanciesOpt, MVideo, MVideoAP, MVideoFormattable, MVideoFormattableDetails } from '../../typings/models' 14import {
20import { MStreamingPlaylistRedundancies } from '../../typings/models/video/video-streaming-playlist' 15 MStreamingPlaylistRedundanciesOpt,
16 MStreamingPlaylistVideo,
17 MVideo,
18 MVideoAP,
19 MVideoFile,
20 MVideoFormattable,
21 MVideoFormattableDetails
22} from '../../typings/models'
21import { MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file' 23import { MVideoFileRedundanciesOpt } from '../../typings/models/video/video-file'
24import { VideoFile } from '@shared/models/videos/video-file.model'
25import { generateMagnetUri } from '@server/helpers/webtorrent'
22 26
23export type VideoFormattingJSONOptions = { 27export type VideoFormattingJSONOptions = {
24 completeDescription?: boolean 28 completeDescription?: boolean
@@ -115,7 +119,7 @@ function videoModelToFormattedDetailsJSON (video: MVideoFormattableDetails): Vid
115 119
116 const tags = video.Tags ? video.Tags.map(t => t.name) : [] 120 const tags = video.Tags ? video.Tags.map(t => t.name) : []
117 121
118 const streamingPlaylists = streamingPlaylistsModelToFormattedJSON(video.VideoStreamingPlaylists) 122 const streamingPlaylists = streamingPlaylistsModelToFormattedJSON(video, video.VideoStreamingPlaylists)
119 123
120 const detailsJson = { 124 const detailsJson = {
121 support: video.support, 125 support: video.support,
@@ -138,33 +142,43 @@ function videoModelToFormattedDetailsJSON (video: MVideoFormattableDetails): Vid
138 } 142 }
139 143
140 // Format and sort video files 144 // Format and sort video files
141 detailsJson.files = videoFilesModelToFormattedJSON(video, video.VideoFiles) 145 detailsJson.files = videoFilesModelToFormattedJSON(video, baseUrlHttp, baseUrlWs, video.VideoFiles)
142 146
143 return Object.assign(formattedJson, detailsJson) 147 return Object.assign(formattedJson, detailsJson)
144} 148}
145 149
146function streamingPlaylistsModelToFormattedJSON (playlists: MStreamingPlaylistRedundanciesOpt[]): VideoStreamingPlaylist[] { 150function streamingPlaylistsModelToFormattedJSON (video: MVideo, playlists: MStreamingPlaylistRedundanciesOpt[]): VideoStreamingPlaylist[] {
147 if (isArray(playlists) === false) return [] 151 if (isArray(playlists) === false) return []
148 152
153 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
154
149 return playlists 155 return playlists
150 .map(playlist => { 156 .map(playlist => {
157 const playlistWithVideo = Object.assign(playlist, { Video: video })
158
151 const redundancies = isArray(playlist.RedundancyVideos) 159 const redundancies = isArray(playlist.RedundancyVideos)
152 ? playlist.RedundancyVideos.map(r => ({ baseUrl: r.fileUrl })) 160 ? playlist.RedundancyVideos.map(r => ({ baseUrl: r.fileUrl }))
153 : [] 161 : []
154 162
163 const files = videoFilesModelToFormattedJSON(playlistWithVideo, baseUrlHttp, baseUrlWs, playlist.VideoFiles)
164
155 return { 165 return {
156 id: playlist.id, 166 id: playlist.id,
157 type: playlist.type, 167 type: playlist.type,
158 playlistUrl: playlist.playlistUrl, 168 playlistUrl: playlist.playlistUrl,
159 segmentsSha256Url: playlist.segmentsSha256Url, 169 segmentsSha256Url: playlist.segmentsSha256Url,
160 redundancies 170 redundancies,
161 } as VideoStreamingPlaylist 171 files
172 }
162 }) 173 })
163} 174}
164 175
165function videoFilesModelToFormattedJSON (video: MVideo, videoFiles: MVideoFileRedundanciesOpt[]): VideoFile[] { 176function videoFilesModelToFormattedJSON (
166 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls() 177 model: MVideo | MStreamingPlaylistVideo,
167 178 baseUrlHttp: string,
179 baseUrlWs: string,
180 videoFiles: MVideoFileRedundanciesOpt[]
181): VideoFile[] {
168 return videoFiles 182 return videoFiles
169 .map(videoFile => { 183 .map(videoFile => {
170 let resolutionLabel = videoFile.resolution + 'p' 184 let resolutionLabel = videoFile.resolution + 'p'
@@ -174,13 +188,13 @@ function videoFilesModelToFormattedJSON (video: MVideo, videoFiles: MVideoFileRe
174 id: videoFile.resolution, 188 id: videoFile.resolution,
175 label: resolutionLabel 189 label: resolutionLabel
176 }, 190 },
177 magnetUri: video.generateMagnetUri(videoFile, baseUrlHttp, baseUrlWs), 191 magnetUri: generateMagnetUri(model, videoFile, baseUrlHttp, baseUrlWs),
178 size: videoFile.size, 192 size: videoFile.size,
179 fps: videoFile.fps, 193 fps: videoFile.fps,
180 torrentUrl: video.getTorrentUrl(videoFile, baseUrlHttp), 194 torrentUrl: model.getTorrentUrl(videoFile, baseUrlHttp),
181 torrentDownloadUrl: video.getTorrentDownloadUrl(videoFile, baseUrlHttp), 195 torrentDownloadUrl: model.getTorrentDownloadUrl(videoFile, baseUrlHttp),
182 fileUrl: video.getVideoFileUrl(videoFile, baseUrlHttp), 196 fileUrl: model.getVideoFileUrl(videoFile, baseUrlHttp),
183 fileDownloadUrl: video.getVideoFileDownloadUrl(videoFile, baseUrlHttp) 197 fileDownloadUrl: model.getVideoFileDownloadUrl(videoFile, baseUrlHttp)
184 } as VideoFile 198 } as VideoFile
185 }) 199 })
186 .sort((a, b) => { 200 .sort((a, b) => {
@@ -190,6 +204,39 @@ function videoFilesModelToFormattedJSON (video: MVideo, videoFiles: MVideoFileRe
190 }) 204 })
191} 205}
192 206
207function addVideoFilesInAPAcc (
208 acc: ActivityUrlObject[] | ActivityTagObject[],
209 model: MVideoAP | MStreamingPlaylistVideo,
210 baseUrlHttp: string,
211 baseUrlWs: string,
212 files: MVideoFile[]
213) {
214 for (const file of files) {
215 acc.push({
216 type: 'Link',
217 mediaType: MIMETYPES.VIDEO.EXT_MIMETYPE[ file.extname ] as any,
218 href: model.getVideoFileUrl(file, baseUrlHttp),
219 height: file.resolution,
220 size: file.size,
221 fps: file.fps
222 })
223
224 acc.push({
225 type: 'Link',
226 mediaType: 'application/x-bittorrent' as 'application/x-bittorrent',
227 href: model.getTorrentUrl(file, baseUrlHttp),
228 height: file.resolution
229 })
230
231 acc.push({
232 type: 'Link',
233 mediaType: 'application/x-bittorrent;x-scheme-handler/magnet' as 'application/x-bittorrent;x-scheme-handler/magnet',
234 href: generateMagnetUri(model, file, baseUrlHttp, baseUrlWs),
235 height: file.resolution
236 })
237 }
238}
239
193function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject { 240function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
194 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls() 241 const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
195 if (!video.Tags) video.Tags = [] 242 if (!video.Tags) video.Tags = []
@@ -224,50 +271,25 @@ function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
224 } 271 }
225 272
226 const url: ActivityUrlObject[] = [] 273 const url: ActivityUrlObject[] = []
227 for (const file of video.VideoFiles) { 274 addVideoFilesInAPAcc(url, video, baseUrlHttp, baseUrlWs, video.VideoFiles || [])
228 url.push({
229 type: 'Link',
230 mimeType: MIMETYPES.VIDEO.EXT_MIMETYPE[ file.extname ] as any,
231 mediaType: MIMETYPES.VIDEO.EXT_MIMETYPE[ file.extname ] as any,
232 href: video.getVideoFileUrl(file, baseUrlHttp),
233 height: file.resolution,
234 size: file.size,
235 fps: file.fps
236 })
237
238 url.push({
239 type: 'Link',
240 mimeType: 'application/x-bittorrent' as 'application/x-bittorrent',
241 mediaType: 'application/x-bittorrent' as 'application/x-bittorrent',
242 href: video.getTorrentUrl(file, baseUrlHttp),
243 height: file.resolution
244 })
245
246 url.push({
247 type: 'Link',
248 mimeType: 'application/x-bittorrent;x-scheme-handler/magnet' as 'application/x-bittorrent;x-scheme-handler/magnet',
249 mediaType: 'application/x-bittorrent;x-scheme-handler/magnet' as 'application/x-bittorrent;x-scheme-handler/magnet',
250 href: video.generateMagnetUri(file, baseUrlHttp, baseUrlWs),
251 height: file.resolution
252 })
253 }
254 275
255 for (const playlist of (video.VideoStreamingPlaylists || [])) { 276 for (const playlist of (video.VideoStreamingPlaylists || [])) {
256 let tag: (ActivityPlaylistSegmentHashesObject | ActivityPlaylistInfohashesObject)[] 277 let tag: ActivityTagObject[]
257 278
258 tag = playlist.p2pMediaLoaderInfohashes 279 tag = playlist.p2pMediaLoaderInfohashes
259 .map(i => ({ type: 'Infohash' as 'Infohash', name: i })) 280 .map(i => ({ type: 'Infohash' as 'Infohash', name: i }))
260 tag.push({ 281 tag.push({
261 type: 'Link', 282 type: 'Link',
262 name: 'sha256', 283 name: 'sha256',
263 mimeType: 'application/json' as 'application/json',
264 mediaType: 'application/json' as 'application/json', 284 mediaType: 'application/json' as 'application/json',
265 href: playlist.segmentsSha256Url 285 href: playlist.segmentsSha256Url
266 }) 286 })
267 287
288 const playlistWithVideo = Object.assign(playlist, { Video: video })
289 addVideoFilesInAPAcc(tag, playlistWithVideo, baseUrlHttp, baseUrlWs, playlist.VideoFiles || [])
290
268 url.push({ 291 url.push({
269 type: 'Link', 292 type: 'Link',
270 mimeType: 'application/x-mpegURL' as 'application/x-mpegURL',
271 mediaType: 'application/x-mpegURL' as 'application/x-mpegURL', 293 mediaType: 'application/x-mpegURL' as 'application/x-mpegURL',
272 href: playlist.playlistUrl, 294 href: playlist.playlistUrl,
273 tag 295 tag
@@ -277,7 +299,6 @@ function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
277 // Add video url too 299 // Add video url too
278 url.push({ 300 url.push({
279 type: 'Link', 301 type: 'Link',
280 mimeType: 'text/html',
281 mediaType: 'text/html', 302 mediaType: 'text/html',
282 href: WEBSERVER.URL + '/videos/watch/' + video.uuid 303 href: WEBSERVER.URL + '/videos/watch/' + video.uuid
283 }) 304 })