aboutsummaryrefslogtreecommitdiffhomepage
path: root/shared/utils/videos
diff options
context:
space:
mode:
Diffstat (limited to 'shared/utils/videos')
-rw-r--r--shared/utils/videos/video-playlists.ts198
-rw-r--r--shared/utils/videos/video-streaming-playlists.ts51
-rw-r--r--shared/utils/videos/videos.ts25
3 files changed, 241 insertions, 33 deletions
diff --git a/shared/utils/videos/video-playlists.ts b/shared/utils/videos/video-playlists.ts
index eb25011cb..5186d9c4f 100644
--- a/shared/utils/videos/video-playlists.ts
+++ b/shared/utils/videos/video-playlists.ts
@@ -1,51 +1,185 @@
1import { makeRawRequest } from '../requests/requests' 1import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
2import { sha256 } from '../../../server/helpers/core-utils' 2import { VideoPlaylistCreate } from '../../models/videos/playlist/video-playlist-create.model'
3import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model' 3import { omit } from 'lodash'
4import { expect } from 'chai' 4import { VideoPlaylistUpdate } from '../../models/videos/playlist/video-playlist-update.model'
5import { VideoPlaylistElementCreate } from '../../models/videos/playlist/video-playlist-element-create.model'
6import { VideoPlaylistElementUpdate } from '../../models/videos/playlist/video-playlist-element-update.model'
5 7
6function getPlaylist (url: string, statusCodeExpected = 200) { 8function getVideoPlaylistsList (url: string, start: number, count: number, sort?: string) {
7 return makeRawRequest(url, statusCodeExpected) 9 const path = '/api/v1/video-playlists'
10
11 const query = {
12 start,
13 count,
14 sort
15 }
16
17 return makeGetRequest({
18 url,
19 path,
20 query
21 })
8} 22}
9 23
10function getSegment (url: string, statusCodeExpected = 200, range?: string) { 24function getVideoPlaylist (url: string, playlistId: number | string, statusCodeExpected = 200) {
11 return makeRawRequest(url, statusCodeExpected, range) 25 const path = '/api/v1/video-playlists/' + playlistId
26
27 return makeGetRequest({
28 url,
29 path,
30 statusCodeExpected
31 })
12} 32}
13 33
14function getSegmentSha256 (url: string, statusCodeExpected = 200) { 34function deleteVideoPlaylist (url: string, token: string, playlistId: number | string, statusCodeExpected = 200) {
15 return makeRawRequest(url, statusCodeExpected) 35 const path = '/api/v1/video-playlists/' + playlistId
36
37 return makeDeleteRequest({
38 url,
39 path,
40 token,
41 statusCodeExpected
42 })
16} 43}
17 44
18async function checkSegmentHash ( 45function createVideoPlaylist (options: {
19 baseUrlPlaylist: string, 46 url: string,
20 baseUrlSegment: string, 47 token: string,
21 videoUUID: string, 48 playlistAttrs: VideoPlaylistCreate,
22 resolution: number, 49 expectedStatus: number
23 hlsPlaylist: VideoStreamingPlaylist 50}) {
24) { 51 const path = '/api/v1/video-playlists/'
25 const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`) 52
26 const playlist = res.text 53 const fields = omit(options.playlistAttrs, 'thumbnailfile')
27 54
28 const videoName = `${videoUUID}-${resolution}-fragmented.mp4` 55 const attaches = options.playlistAttrs.thumbnailfile
56 ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
57 : {}
29 58
30 const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) 59 return makeUploadRequest({
60 method: 'POST',
61 url: options.url,
62 path,
63 token: options.token,
64 fields,
65 attaches,
66 statusCodeExpected: options.expectedStatus
67 })
68}
31 69
32 const length = parseInt(matches[1], 10) 70function updateVideoPlaylist (options: {
33 const offset = parseInt(matches[2], 10) 71 url: string,
34 const range = `${offset}-${offset + length - 1}` 72 token: string,
73 playlistAttrs: VideoPlaylistUpdate,
74 expectedStatus: number
75}) {
76 const path = '/api/v1/video-playlists/'
35 77
36 const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, 206, `bytes=${range}`) 78 const fields = omit(options.playlistAttrs, 'thumbnailfile')
37 79
38 const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) 80 const attaches = options.playlistAttrs.thumbnailfile
81 ? { thumbnailfile: options.playlistAttrs.thumbnailfile }
82 : {}
39 83
40 const sha256Server = resSha.body[ videoName ][range] 84 return makeUploadRequest({
41 expect(sha256(res2.body)).to.equal(sha256Server) 85 method: 'PUT',
86 url: options.url,
87 path,
88 token: options.token,
89 fields,
90 attaches,
91 statusCodeExpected: options.expectedStatus
92 })
93}
94
95function addVideoInPlaylist (options: {
96 url: string,
97 token: string,
98 playlistId: number | string,
99 elementAttrs: VideoPlaylistElementCreate
100 expectedStatus: number
101}) {
102 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
103
104 return makePostBodyRequest({
105 url: options.url,
106 path,
107 token: options.token,
108 fields: options.elementAttrs,
109 statusCodeExpected: options.expectedStatus
110 })
111}
112
113function updateVideoPlaylistElement (options: {
114 url: string,
115 token: string,
116 playlistId: number | string,
117 videoId: number | string,
118 elementAttrs: VideoPlaylistElementUpdate,
119 expectedStatus: number
120}) {
121 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.videoId
122
123 return makePutBodyRequest({
124 url: options.url,
125 path,
126 token: options.token,
127 fields: options.elementAttrs,
128 statusCodeExpected: options.expectedStatus
129 })
130}
131
132function removeVideoFromPlaylist (options: {
133 url: string,
134 token: string,
135 playlistId: number | string,
136 videoId: number | string,
137 expectedStatus: number
138}) {
139 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos/' + options.videoId
140
141 return makeDeleteRequest({
142 url: options.url,
143 path,
144 token: options.token,
145 statusCodeExpected: options.expectedStatus
146 })
147}
148
149function reorderVideosPlaylist (options: {
150 url: string,
151 token: string,
152 playlistId: number | string,
153 elementAttrs: {
154 startPosition: number,
155 insertAfter: number,
156 reorderLength?: number
157 },
158 expectedStatus: number
159}) {
160 const path = '/api/v1/video-playlists/' + options.playlistId + '/videos'
161
162 return makePutBodyRequest({
163 url: options.url,
164 path,
165 token: options.token,
166 fields: options.elementAttrs,
167 statusCodeExpected: options.expectedStatus
168 })
42} 169}
43 170
44// --------------------------------------------------------------------------- 171// ---------------------------------------------------------------------------
45 172
46export { 173export {
47 getPlaylist, 174 getVideoPlaylistsList,
48 getSegment, 175 getVideoPlaylist,
49 getSegmentSha256, 176
50 checkSegmentHash 177 createVideoPlaylist,
178 updateVideoPlaylist,
179 deleteVideoPlaylist,
180
181 addVideoInPlaylist,
182 removeVideoFromPlaylist,
183
184 reorderVideosPlaylist
51} 185}
diff --git a/shared/utils/videos/video-streaming-playlists.ts b/shared/utils/videos/video-streaming-playlists.ts
new file mode 100644
index 000000000..eb25011cb
--- /dev/null
+++ b/shared/utils/videos/video-streaming-playlists.ts
@@ -0,0 +1,51 @@
1import { makeRawRequest } from '../requests/requests'
2import { sha256 } from '../../../server/helpers/core-utils'
3import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model'
4import { expect } from 'chai'
5
6function getPlaylist (url: string, statusCodeExpected = 200) {
7 return makeRawRequest(url, statusCodeExpected)
8}
9
10function getSegment (url: string, statusCodeExpected = 200, range?: string) {
11 return makeRawRequest(url, statusCodeExpected, range)
12}
13
14function getSegmentSha256 (url: string, statusCodeExpected = 200) {
15 return makeRawRequest(url, statusCodeExpected)
16}
17
18async function checkSegmentHash (
19 baseUrlPlaylist: string,
20 baseUrlSegment: string,
21 videoUUID: string,
22 resolution: number,
23 hlsPlaylist: VideoStreamingPlaylist
24) {
25 const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`)
26 const playlist = res.text
27
28 const videoName = `${videoUUID}-${resolution}-fragmented.mp4`
29
30 const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
31
32 const length = parseInt(matches[1], 10)
33 const offset = parseInt(matches[2], 10)
34 const range = `${offset}-${offset + length - 1}`
35
36 const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, 206, `bytes=${range}`)
37
38 const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url)
39
40 const sha256Server = resSha.body[ videoName ][range]
41 expect(sha256(res2.body)).to.equal(sha256Server)
42}
43
44// ---------------------------------------------------------------------------
45
46export {
47 getPlaylist,
48 getSegment,
49 getSegmentSha256,
50 checkSegmentHash
51}
diff --git a/shared/utils/videos/videos.ts b/shared/utils/videos/videos.ts
index b3d24bc53..2c09f0086 100644
--- a/shared/utils/videos/videos.ts
+++ b/shared/utils/videos/videos.ts
@@ -223,6 +223,28 @@ function getVideoChannelVideos (
223 }) 223 })
224} 224}
225 225
226function getPlaylistVideos (
227 url: string,
228 accessToken: string,
229 playlistId: number | string,
230 start: number,
231 count: number,
232 query: { nsfw?: boolean } = {}
233) {
234 const path = '/api/v1/video-playlists/' + playlistId + '/videos'
235
236 return makeGetRequest({
237 url,
238 path,
239 query: immutableAssign(query, {
240 start,
241 count
242 }),
243 token: accessToken,
244 statusCodeExpected: 200
245 })
246}
247
226function getVideosListPagination (url: string, start: number, count: number, sort?: string) { 248function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
227 const path = '/api/v1/videos' 249 const path = '/api/v1/videos'
228 250
@@ -601,5 +623,6 @@ export {
601 parseTorrentVideo, 623 parseTorrentVideo,
602 getLocalVideos, 624 getLocalVideos,
603 completeVideoCheck, 625 completeVideoCheck,
604 checkVideoFilesWereRemoved 626 checkVideoFilesWereRemoved,
627 getPlaylistVideos
605} 628}