diff options
Diffstat (limited to 'server/tests/api/live/live.ts')
-rw-r--r-- | server/tests/api/live/live.ts | 289 |
1 files changed, 143 insertions, 146 deletions
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts index 50397924e..d555cff19 100644 --- a/server/tests/api/live/live.ts +++ b/server/tests/api/live/live.ts | |||
@@ -2,75 +2,70 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { join } from 'path' | 5 | import { basename, join } from 'path' |
6 | import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' | 6 | import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils' |
7 | import { LiveVideo, LiveVideoCreate, Video, VideoDetails, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models' | ||
8 | import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' | ||
9 | import { | 7 | import { |
10 | addVideoToBlacklist, | 8 | checkLiveCleanupAfterSave, |
11 | buildServerDirectory, | ||
12 | checkLiveCleanup, | ||
13 | checkLiveSegmentHash, | 9 | checkLiveSegmentHash, |
14 | checkResolutionsInMasterPlaylist, | 10 | checkResolutionsInMasterPlaylist, |
15 | cleanupTests, | 11 | cleanupTests, |
16 | createLive, | 12 | createMultipleServers, |
17 | doubleFollow, | 13 | doubleFollow, |
18 | flushAndRunMultipleServers, | ||
19 | getLive, | ||
20 | getMyVideosWithFilter, | ||
21 | getPlaylist, | ||
22 | getVideo, | ||
23 | getVideosList, | ||
24 | getVideosWithFilters, | ||
25 | killallServers, | 14 | killallServers, |
15 | LiveCommand, | ||
26 | makeRawRequest, | 16 | makeRawRequest, |
27 | removeVideo, | 17 | PeerTubeServer, |
28 | reRunServer, | ||
29 | sendRTMPStream, | 18 | sendRTMPStream, |
30 | sendRTMPStreamInVideo, | ||
31 | ServerInfo, | ||
32 | setAccessTokensToServers, | 19 | setAccessTokensToServers, |
33 | setDefaultVideoChannel, | 20 | setDefaultVideoChannel, |
34 | stopFfmpeg, | 21 | stopFfmpeg, |
35 | testFfmpegStreamError, | 22 | testFfmpegStreamError, |
36 | testImage, | 23 | testImage, |
37 | updateCustomSubConfig, | ||
38 | updateLive, | ||
39 | uploadVideoAndGetId, | ||
40 | wait, | 24 | wait, |
41 | waitJobs, | 25 | waitJobs, |
42 | waitUntilLiveEnded, | 26 | waitUntilLivePublishedOnAllServers |
43 | waitUntilLivePublished, | 27 | } from '@shared/extra-utils' |
44 | waitUntilLivePublishedOnAllServers, | 28 | import { |
45 | waitUntilLiveSegmentGeneration | 29 | HttpStatusCode, |
46 | } from '../../../../shared/extra-utils' | 30 | LiveVideo, |
31 | LiveVideoCreate, | ||
32 | VideoDetails, | ||
33 | VideoPrivacy, | ||
34 | VideoState, | ||
35 | VideoStreamingPlaylistType | ||
36 | } from '@shared/models' | ||
47 | 37 | ||
48 | const expect = chai.expect | 38 | const expect = chai.expect |
49 | 39 | ||
50 | describe('Test live', function () { | 40 | describe('Test live', function () { |
51 | let servers: ServerInfo[] = [] | 41 | let servers: PeerTubeServer[] = [] |
42 | let commands: LiveCommand[] | ||
52 | 43 | ||
53 | before(async function () { | 44 | before(async function () { |
54 | this.timeout(120000) | 45 | this.timeout(120000) |
55 | 46 | ||
56 | servers = await flushAndRunMultipleServers(2) | 47 | servers = await createMultipleServers(2) |
57 | 48 | ||
58 | // Get the access tokens | 49 | // Get the access tokens |
59 | await setAccessTokensToServers(servers) | 50 | await setAccessTokensToServers(servers) |
60 | await setDefaultVideoChannel(servers) | 51 | await setDefaultVideoChannel(servers) |
61 | 52 | ||
62 | await updateCustomSubConfig(servers[0].url, servers[0].accessToken, { | 53 | await servers[0].config.updateCustomSubConfig({ |
63 | live: { | 54 | newConfig: { |
64 | enabled: true, | 55 | live: { |
65 | allowReplay: true, | 56 | enabled: true, |
66 | transcoding: { | 57 | allowReplay: true, |
67 | enabled: false | 58 | transcoding: { |
59 | enabled: false | ||
60 | } | ||
68 | } | 61 | } |
69 | } | 62 | } |
70 | }) | 63 | }) |
71 | 64 | ||
72 | // Server 1 and server 2 follow each other | 65 | // Server 1 and server 2 follow each other |
73 | await doubleFollow(servers[0], servers[1]) | 66 | await doubleFollow(servers[0], servers[1]) |
67 | |||
68 | commands = servers.map(s => s.live) | ||
74 | }) | 69 | }) |
75 | 70 | ||
76 | describe('Live creation, update and delete', function () { | 71 | describe('Live creation, update and delete', function () { |
@@ -85,7 +80,7 @@ describe('Test live', function () { | |||
85 | language: 'fr', | 80 | language: 'fr', |
86 | description: 'super live description', | 81 | description: 'super live description', |
87 | support: 'support field', | 82 | support: 'support field', |
88 | channelId: servers[0].videoChannel.id, | 83 | channelId: servers[0].store.channel.id, |
89 | nsfw: false, | 84 | nsfw: false, |
90 | waitTranscoding: false, | 85 | waitTranscoding: false, |
91 | name: 'my super live', | 86 | name: 'my super live', |
@@ -98,14 +93,13 @@ describe('Test live', function () { | |||
98 | thumbnailfile: 'video_short1.webm.jpg' | 93 | thumbnailfile: 'video_short1.webm.jpg' |
99 | } | 94 | } |
100 | 95 | ||
101 | const res = await createLive(servers[0].url, servers[0].accessToken, attributes) | 96 | const live = await commands[0].create({ fields: attributes }) |
102 | liveVideoUUID = res.body.video.uuid | 97 | liveVideoUUID = live.uuid |
103 | 98 | ||
104 | await waitJobs(servers) | 99 | await waitJobs(servers) |
105 | 100 | ||
106 | for (const server of servers) { | 101 | for (const server of servers) { |
107 | const resVideo = await getVideo(server.url, liveVideoUUID) | 102 | const video = await server.videos.get({ id: liveVideoUUID }) |
108 | const video: VideoDetails = resVideo.body | ||
109 | 103 | ||
110 | expect(video.category.id).to.equal(1) | 104 | expect(video.category.id).to.equal(1) |
111 | expect(video.licence.id).to.equal(2) | 105 | expect(video.licence.id).to.equal(2) |
@@ -113,8 +107,8 @@ describe('Test live', function () { | |||
113 | expect(video.description).to.equal('super live description') | 107 | expect(video.description).to.equal('super live description') |
114 | expect(video.support).to.equal('support field') | 108 | expect(video.support).to.equal('support field') |
115 | 109 | ||
116 | expect(video.channel.name).to.equal(servers[0].videoChannel.name) | 110 | expect(video.channel.name).to.equal(servers[0].store.channel.name) |
117 | expect(video.channel.host).to.equal(servers[0].videoChannel.host) | 111 | expect(video.channel.host).to.equal(servers[0].store.channel.host) |
118 | 112 | ||
119 | expect(video.isLive).to.be.true | 113 | expect(video.isLive).to.be.true |
120 | 114 | ||
@@ -129,8 +123,7 @@ describe('Test live', function () { | |||
129 | await testImage(server.url, 'video_short1-preview.webm', video.previewPath) | 123 | await testImage(server.url, 'video_short1-preview.webm', video.previewPath) |
130 | await testImage(server.url, 'video_short1.webm', video.thumbnailPath) | 124 | await testImage(server.url, 'video_short1.webm', video.thumbnailPath) |
131 | 125 | ||
132 | const resLive = await getLive(server.url, server.accessToken, liveVideoUUID) | 126 | const live = await server.live.get({ videoId: liveVideoUUID }) |
133 | const live: LiveVideo = resLive.body | ||
134 | 127 | ||
135 | if (server.url === servers[0].url) { | 128 | if (server.url === servers[0].url) { |
136 | expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') | 129 | expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') |
@@ -149,20 +142,18 @@ describe('Test live', function () { | |||
149 | 142 | ||
150 | const attributes: LiveVideoCreate = { | 143 | const attributes: LiveVideoCreate = { |
151 | name: 'default live thumbnail', | 144 | name: 'default live thumbnail', |
152 | channelId: servers[0].videoChannel.id, | 145 | channelId: servers[0].store.channel.id, |
153 | privacy: VideoPrivacy.UNLISTED, | 146 | privacy: VideoPrivacy.UNLISTED, |
154 | nsfw: true | 147 | nsfw: true |
155 | } | 148 | } |
156 | 149 | ||
157 | const res = await createLive(servers[0].url, servers[0].accessToken, attributes) | 150 | const live = await commands[0].create({ fields: attributes }) |
158 | const videoId = res.body.video.uuid | 151 | const videoId = live.uuid |
159 | 152 | ||
160 | await waitJobs(servers) | 153 | await waitJobs(servers) |
161 | 154 | ||
162 | for (const server of servers) { | 155 | for (const server of servers) { |
163 | const resVideo = await getVideo(server.url, videoId) | 156 | const video = await server.videos.get({ id: videoId }) |
164 | const video: VideoDetails = resVideo.body | ||
165 | |||
166 | expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) | 157 | expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) |
167 | expect(video.nsfw).to.be.true | 158 | expect(video.nsfw).to.be.true |
168 | 159 | ||
@@ -173,28 +164,27 @@ describe('Test live', function () { | |||
173 | 164 | ||
174 | it('Should not have the live listed since nobody streams into', async function () { | 165 | it('Should not have the live listed since nobody streams into', async function () { |
175 | for (const server of servers) { | 166 | for (const server of servers) { |
176 | const res = await getVideosList(server.url) | 167 | const { total, data } = await server.videos.list() |
177 | 168 | ||
178 | expect(res.body.total).to.equal(0) | 169 | expect(total).to.equal(0) |
179 | expect(res.body.data).to.have.lengthOf(0) | 170 | expect(data).to.have.lengthOf(0) |
180 | } | 171 | } |
181 | }) | 172 | }) |
182 | 173 | ||
183 | it('Should not be able to update a live of another server', async function () { | 174 | it('Should not be able to update a live of another server', async function () { |
184 | await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403) | 175 | await commands[1].update({ videoId: liveVideoUUID, fields: { saveReplay: false }, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) |
185 | }) | 176 | }) |
186 | 177 | ||
187 | it('Should update the live', async function () { | 178 | it('Should update the live', async function () { |
188 | this.timeout(10000) | 179 | this.timeout(10000) |
189 | 180 | ||
190 | await updateLive(servers[0].url, servers[0].accessToken, liveVideoUUID, { saveReplay: false }) | 181 | await commands[0].update({ videoId: liveVideoUUID, fields: { saveReplay: false } }) |
191 | await waitJobs(servers) | 182 | await waitJobs(servers) |
192 | }) | 183 | }) |
193 | 184 | ||
194 | it('Have the live updated', async function () { | 185 | it('Have the live updated', async function () { |
195 | for (const server of servers) { | 186 | for (const server of servers) { |
196 | const res = await getLive(server.url, server.accessToken, liveVideoUUID) | 187 | const live = await server.live.get({ videoId: liveVideoUUID }) |
197 | const live: LiveVideo = res.body | ||
198 | 188 | ||
199 | if (server.url === servers[0].url) { | 189 | if (server.url === servers[0].url) { |
200 | expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') | 190 | expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live') |
@@ -211,77 +201,75 @@ describe('Test live', function () { | |||
211 | it('Delete the live', async function () { | 201 | it('Delete the live', async function () { |
212 | this.timeout(10000) | 202 | this.timeout(10000) |
213 | 203 | ||
214 | await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID) | 204 | await servers[0].videos.remove({ id: liveVideoUUID }) |
215 | await waitJobs(servers) | 205 | await waitJobs(servers) |
216 | }) | 206 | }) |
217 | 207 | ||
218 | it('Should have the live deleted', async function () { | 208 | it('Should have the live deleted', async function () { |
219 | for (const server of servers) { | 209 | for (const server of servers) { |
220 | await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) | 210 | await server.videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
221 | await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404) | 211 | await server.live.get({ videoId: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) |
222 | } | 212 | } |
223 | }) | 213 | }) |
224 | }) | 214 | }) |
225 | 215 | ||
226 | describe('Live filters', function () { | 216 | describe('Live filters', function () { |
227 | let command: any | 217 | let ffmpegCommand: any |
228 | let liveVideoId: string | 218 | let liveVideoId: string |
229 | let vodVideoId: string | 219 | let vodVideoId: string |
230 | 220 | ||
231 | before(async function () { | 221 | before(async function () { |
232 | this.timeout(120000) | 222 | this.timeout(120000) |
233 | 223 | ||
234 | vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid | 224 | vodVideoId = (await servers[0].videos.quickUpload({ name: 'vod video' })).uuid |
235 | 225 | ||
236 | const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id } | 226 | const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].store.channel.id } |
237 | const resLive = await createLive(servers[0].url, servers[0].accessToken, liveOptions) | 227 | const live = await commands[0].create({ fields: liveOptions }) |
238 | liveVideoId = resLive.body.video.uuid | 228 | liveVideoId = live.uuid |
239 | 229 | ||
240 | command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) | 230 | ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoId }) |
241 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) | 231 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) |
242 | await waitJobs(servers) | 232 | await waitJobs(servers) |
243 | }) | 233 | }) |
244 | 234 | ||
245 | it('Should only display lives', async function () { | 235 | it('Should only display lives', async function () { |
246 | const res = await getVideosWithFilters(servers[0].url, { isLive: true }) | 236 | const { data, total } = await servers[0].videos.list({ isLive: true }) |
247 | 237 | ||
248 | expect(res.body.total).to.equal(1) | 238 | expect(total).to.equal(1) |
249 | expect(res.body.data).to.have.lengthOf(1) | 239 | expect(data).to.have.lengthOf(1) |
250 | expect(res.body.data[0].name).to.equal('live') | 240 | expect(data[0].name).to.equal('live') |
251 | }) | 241 | }) |
252 | 242 | ||
253 | it('Should not display lives', async function () { | 243 | it('Should not display lives', async function () { |
254 | const res = await getVideosWithFilters(servers[0].url, { isLive: false }) | 244 | const { data, total } = await servers[0].videos.list({ isLive: false }) |
255 | 245 | ||
256 | expect(res.body.total).to.equal(1) | 246 | expect(total).to.equal(1) |
257 | expect(res.body.data).to.have.lengthOf(1) | 247 | expect(data).to.have.lengthOf(1) |
258 | expect(res.body.data[0].name).to.equal('vod video') | 248 | expect(data[0].name).to.equal('vod video') |
259 | }) | 249 | }) |
260 | 250 | ||
261 | it('Should display my lives', async function () { | 251 | it('Should display my lives', async function () { |
262 | this.timeout(60000) | 252 | this.timeout(60000) |
263 | 253 | ||
264 | await stopFfmpeg(command) | 254 | await stopFfmpeg(ffmpegCommand) |
265 | await waitJobs(servers) | 255 | await waitJobs(servers) |
266 | 256 | ||
267 | const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true }) | 257 | const { data } = await servers[0].videos.listMyVideos({ isLive: true }) |
268 | const videos = res.body.data as Video[] | ||
269 | 258 | ||
270 | const result = videos.every(v => v.isLive) | 259 | const result = data.every(v => v.isLive) |
271 | expect(result).to.be.true | 260 | expect(result).to.be.true |
272 | }) | 261 | }) |
273 | 262 | ||
274 | it('Should not display my lives', async function () { | 263 | it('Should not display my lives', async function () { |
275 | const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: false }) | 264 | const { data } = await servers[0].videos.listMyVideos({ isLive: false }) |
276 | const videos = res.body.data as Video[] | ||
277 | 265 | ||
278 | const result = videos.every(v => !v.isLive) | 266 | const result = data.every(v => !v.isLive) |
279 | expect(result).to.be.true | 267 | expect(result).to.be.true |
280 | }) | 268 | }) |
281 | 269 | ||
282 | after(async function () { | 270 | after(async function () { |
283 | await removeVideo(servers[0].url, servers[0].accessToken, vodVideoId) | 271 | await servers[0].videos.remove({ id: vodVideoId }) |
284 | await removeVideo(servers[0].url, servers[0].accessToken, liveVideoId) | 272 | await servers[0].videos.remove({ id: liveVideoId }) |
285 | }) | 273 | }) |
286 | }) | 274 | }) |
287 | 275 | ||
@@ -296,18 +284,17 @@ describe('Test live', function () { | |||
296 | async function createLiveWrapper () { | 284 | async function createLiveWrapper () { |
297 | const liveAttributes = { | 285 | const liveAttributes = { |
298 | name: 'user live', | 286 | name: 'user live', |
299 | channelId: servers[0].videoChannel.id, | 287 | channelId: servers[0].store.channel.id, |
300 | privacy: VideoPrivacy.PUBLIC, | 288 | privacy: VideoPrivacy.PUBLIC, |
301 | saveReplay: false | 289 | saveReplay: false |
302 | } | 290 | } |
303 | 291 | ||
304 | const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) | 292 | const { uuid } = await commands[0].create({ fields: liveAttributes }) |
305 | const uuid = res.body.video.uuid | ||
306 | 293 | ||
307 | const resLive = await getLive(servers[0].url, servers[0].accessToken, uuid) | 294 | const live = await commands[0].get({ videoId: uuid }) |
308 | const resVideo = await getVideo(servers[0].url, uuid) | 295 | const video = await servers[0].videos.get({ id: uuid }) |
309 | 296 | ||
310 | return Object.assign(resVideo.body, resLive.body) as LiveVideo & VideoDetails | 297 | return Object.assign(video, live) |
311 | } | 298 | } |
312 | 299 | ||
313 | it('Should not allow a stream without the appropriate path', async function () { | 300 | it('Should not allow a stream without the appropriate path', async function () { |
@@ -335,13 +322,12 @@ describe('Test live', function () { | |||
335 | 322 | ||
336 | it('Should list this live now someone stream into it', async function () { | 323 | it('Should list this live now someone stream into it', async function () { |
337 | for (const server of servers) { | 324 | for (const server of servers) { |
338 | const res = await getVideosList(server.url) | 325 | const { total, data } = await server.videos.list() |
339 | 326 | ||
340 | expect(res.body.total).to.equal(1) | 327 | expect(total).to.equal(1) |
341 | expect(res.body.data).to.have.lengthOf(1) | 328 | expect(data).to.have.lengthOf(1) |
342 | |||
343 | const video: Video = res.body.data[0] | ||
344 | 329 | ||
330 | const video = data[0] | ||
345 | expect(video.name).to.equal('user live') | 331 | expect(video.name).to.equal('user live') |
346 | expect(video.isLive).to.be.true | 332 | expect(video.isLive).to.be.true |
347 | } | 333 | } |
@@ -352,7 +338,7 @@ describe('Test live', function () { | |||
352 | 338 | ||
353 | liveVideo = await createLiveWrapper() | 339 | liveVideo = await createLiveWrapper() |
354 | 340 | ||
355 | await addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideo.uuid) | 341 | await servers[0].blacklist.add({ videoId: liveVideo.uuid }) |
356 | 342 | ||
357 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) | 343 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) |
358 | await testFfmpegStreamError(command, true) | 344 | await testFfmpegStreamError(command, true) |
@@ -363,7 +349,7 @@ describe('Test live', function () { | |||
363 | 349 | ||
364 | liveVideo = await createLiveWrapper() | 350 | liveVideo = await createLiveWrapper() |
365 | 351 | ||
366 | await removeVideo(servers[0].url, servers[0].accessToken, liveVideo.uuid) | 352 | await servers[0].videos.remove({ id: liveVideo.uuid }) |
367 | 353 | ||
368 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) | 354 | const command = sendRTMPStream(rtmpUrl + '/live', liveVideo.streamKey) |
369 | await testFfmpegStreamError(command, true) | 355 | await testFfmpegStreamError(command, true) |
@@ -376,24 +362,21 @@ describe('Test live', function () { | |||
376 | async function createLiveWrapper (saveReplay: boolean) { | 362 | async function createLiveWrapper (saveReplay: boolean) { |
377 | const liveAttributes = { | 363 | const liveAttributes = { |
378 | name: 'live video', | 364 | name: 'live video', |
379 | channelId: servers[0].videoChannel.id, | 365 | channelId: servers[0].store.channel.id, |
380 | privacy: VideoPrivacy.PUBLIC, | 366 | privacy: VideoPrivacy.PUBLIC, |
381 | saveReplay | 367 | saveReplay |
382 | } | 368 | } |
383 | 369 | ||
384 | const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) | 370 | const { uuid } = await commands[0].create({ fields: liveAttributes }) |
385 | return res.body.video.uuid | 371 | return uuid |
386 | } | 372 | } |
387 | 373 | ||
388 | async function testVideoResolutions (liveVideoId: string, resolutions: number[]) { | 374 | async function testVideoResolutions (liveVideoId: string, resolutions: number[]) { |
389 | for (const server of servers) { | 375 | for (const server of servers) { |
390 | const resList = await getVideosList(server.url) | 376 | const { data } = await server.videos.list() |
391 | const videos: Video[] = resList.body.data | 377 | expect(data.find(v => v.uuid === liveVideoId)).to.exist |
392 | |||
393 | expect(videos.find(v => v.uuid === liveVideoId)).to.exist | ||
394 | 378 | ||
395 | const resVideo = await getVideo(server.url, liveVideoId) | 379 | const video = await server.videos.get({ id: liveVideoId }) |
396 | const video: VideoDetails = resVideo.body | ||
397 | 380 | ||
398 | expect(video.streamingPlaylists).to.have.lengthOf(1) | 381 | expect(video.streamingPlaylists).to.have.lengthOf(1) |
399 | 382 | ||
@@ -403,39 +386,48 @@ describe('Test live', function () { | |||
403 | // Only finite files are displayed | 386 | // Only finite files are displayed |
404 | expect(hlsPlaylist.files).to.have.lengthOf(0) | 387 | expect(hlsPlaylist.files).to.have.lengthOf(0) |
405 | 388 | ||
406 | await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions) | 389 | await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions }) |
407 | 390 | ||
408 | for (let i = 0; i < resolutions.length; i++) { | 391 | for (let i = 0; i < resolutions.length; i++) { |
409 | const segmentNum = 3 | 392 | const segmentNum = 3 |
410 | const segmentName = `${i}-00000${segmentNum}.ts` | 393 | const segmentName = `${i}-00000${segmentNum}.ts` |
411 | await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum) | 394 | await commands[0].waitUntilSegmentGeneration({ videoUUID: video.uuid, resolution: i, segment: segmentNum }) |
412 | 395 | ||
413 | const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`) | 396 | const subPlaylist = await servers[0].streamingPlaylists.get({ |
414 | const subPlaylist = res.text | 397 | url: `${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8` |
398 | }) | ||
415 | 399 | ||
416 | expect(subPlaylist).to.contain(segmentName) | 400 | expect(subPlaylist).to.contain(segmentName) |
417 | 401 | ||
418 | const baseUrlAndPath = servers[0].url + '/static/streaming-playlists/hls' | 402 | const baseUrlAndPath = servers[0].url + '/static/streaming-playlists/hls' |
419 | await checkLiveSegmentHash(baseUrlAndPath, video.uuid, segmentName, hlsPlaylist) | 403 | await checkLiveSegmentHash({ |
404 | server, | ||
405 | baseUrlSegment: baseUrlAndPath, | ||
406 | videoUUID: video.uuid, | ||
407 | segmentName, | ||
408 | hlsPlaylist | ||
409 | }) | ||
420 | } | 410 | } |
421 | } | 411 | } |
422 | } | 412 | } |
423 | 413 | ||
424 | function updateConf (resolutions: number[]) { | 414 | function updateConf (resolutions: number[]) { |
425 | return updateCustomSubConfig(servers[0].url, servers[0].accessToken, { | 415 | return servers[0].config.updateCustomSubConfig({ |
426 | live: { | 416 | newConfig: { |
427 | enabled: true, | 417 | live: { |
428 | allowReplay: true, | ||
429 | maxDuration: -1, | ||
430 | transcoding: { | ||
431 | enabled: true, | 418 | enabled: true, |
432 | resolutions: { | 419 | allowReplay: true, |
433 | '240p': resolutions.includes(240), | 420 | maxDuration: -1, |
434 | '360p': resolutions.includes(360), | 421 | transcoding: { |
435 | '480p': resolutions.includes(480), | 422 | enabled: true, |
436 | '720p': resolutions.includes(720), | 423 | resolutions: { |
437 | '1080p': resolutions.includes(1080), | 424 | '240p': resolutions.includes(240), |
438 | '2160p': resolutions.includes(2160) | 425 | '360p': resolutions.includes(360), |
426 | '480p': resolutions.includes(480), | ||
427 | '720p': resolutions.includes(720), | ||
428 | '1080p': resolutions.includes(1080), | ||
429 | '2160p': resolutions.includes(2160) | ||
430 | } | ||
439 | } | 431 | } |
440 | } | 432 | } |
441 | } | 433 | } |
@@ -451,13 +443,13 @@ describe('Test live', function () { | |||
451 | 443 | ||
452 | liveVideoId = await createLiveWrapper(false) | 444 | liveVideoId = await createLiveWrapper(false) |
453 | 445 | ||
454 | const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) | 446 | const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }) |
455 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) | 447 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) |
456 | await waitJobs(servers) | 448 | await waitJobs(servers) |
457 | 449 | ||
458 | await testVideoResolutions(liveVideoId, [ 720 ]) | 450 | await testVideoResolutions(liveVideoId, [ 720 ]) |
459 | 451 | ||
460 | await stopFfmpeg(command) | 452 | await stopFfmpeg(ffmpegCommand) |
461 | }) | 453 | }) |
462 | 454 | ||
463 | it('Should enable transcoding with some resolutions', async function () { | 455 | it('Should enable transcoding with some resolutions', async function () { |
@@ -467,13 +459,13 @@ describe('Test live', function () { | |||
467 | await updateConf(resolutions) | 459 | await updateConf(resolutions) |
468 | liveVideoId = await createLiveWrapper(false) | 460 | liveVideoId = await createLiveWrapper(false) |
469 | 461 | ||
470 | const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId) | 462 | const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }) |
471 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) | 463 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) |
472 | await waitJobs(servers) | 464 | await waitJobs(servers) |
473 | 465 | ||
474 | await testVideoResolutions(liveVideoId, resolutions) | 466 | await testVideoResolutions(liveVideoId, resolutions) |
475 | 467 | ||
476 | await stopFfmpeg(command) | 468 | await stopFfmpeg(ffmpegCommand) |
477 | }) | 469 | }) |
478 | 470 | ||
479 | it('Should enable transcoding with some resolutions and correctly save them', async function () { | 471 | it('Should enable transcoding with some resolutions and correctly save them', async function () { |
@@ -484,14 +476,14 @@ describe('Test live', function () { | |||
484 | await updateConf(resolutions) | 476 | await updateConf(resolutions) |
485 | liveVideoId = await createLiveWrapper(true) | 477 | liveVideoId = await createLiveWrapper(true) |
486 | 478 | ||
487 | const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm') | 479 | const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' }) |
488 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) | 480 | await waitUntilLivePublishedOnAllServers(servers, liveVideoId) |
489 | await waitJobs(servers) | 481 | await waitJobs(servers) |
490 | 482 | ||
491 | await testVideoResolutions(liveVideoId, resolutions) | 483 | await testVideoResolutions(liveVideoId, resolutions) |
492 | 484 | ||
493 | await stopFfmpeg(command) | 485 | await stopFfmpeg(ffmpegCommand) |
494 | await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId) | 486 | await commands[0].waitUntilEnded({ videoId: liveVideoId }) |
495 | 487 | ||
496 | await waitJobs(servers) | 488 | await waitJobs(servers) |
497 | 489 | ||
@@ -504,8 +496,7 @@ describe('Test live', function () { | |||
504 | } | 496 | } |
505 | 497 | ||
506 | for (const server of servers) { | 498 | for (const server of servers) { |
507 | const resVideo = await getVideo(server.url, liveVideoId) | 499 | const video = await server.videos.get({ id: liveVideoId }) |
508 | const video: VideoDetails = resVideo.body | ||
509 | 500 | ||
510 | expect(video.state.id).to.equal(VideoState.PUBLISHED) | 501 | expect(video.state.id).to.equal(VideoState.PUBLISHED) |
511 | expect(video.duration).to.be.greaterThan(1) | 502 | expect(video.duration).to.be.greaterThan(1) |
@@ -515,6 +506,10 @@ describe('Test live', function () { | |||
515 | await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200) | 506 | await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200) |
516 | await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200) | 507 | await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200) |
517 | 508 | ||
509 | // We should have generated random filenames | ||
510 | expect(basename(hlsPlaylist.playlistUrl)).to.not.equal('master.m3u8') | ||
511 | expect(basename(hlsPlaylist.segmentsSha256Url)).to.not.equal('segments-sha256.json') | ||
512 | |||
518 | expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length) | 513 | expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length) |
519 | 514 | ||
520 | for (const resolution of resolutions) { | 515 | for (const resolution of resolutions) { |
@@ -529,8 +524,10 @@ describe('Test live', function () { | |||
529 | expect(file.fps).to.be.approximately(30, 2) | 524 | expect(file.fps).to.be.approximately(30, 2) |
530 | } | 525 | } |
531 | 526 | ||
532 | const filename = `${video.uuid}-${resolution}-fragmented.mp4` | 527 | const filename = basename(file.fileUrl) |
533 | const segmentPath = buildServerDirectory(servers[0], join('streaming-playlists', 'hls', video.uuid, filename)) | 528 | expect(filename).to.not.contain(video.uuid) |
529 | |||
530 | const segmentPath = servers[0].servers.buildDirectory(join('streaming-playlists', 'hls', video.uuid, filename)) | ||
534 | 531 | ||
535 | const probe = await ffprobePromise(segmentPath) | 532 | const probe = await ffprobePromise(segmentPath) |
536 | const videoStream = await getVideoStreamFromFile(segmentPath, probe) | 533 | const videoStream = await getVideoStreamFromFile(segmentPath, probe) |
@@ -546,7 +543,7 @@ describe('Test live', function () { | |||
546 | it('Should correctly have cleaned up the live files', async function () { | 543 | it('Should correctly have cleaned up the live files', async function () { |
547 | this.timeout(30000) | 544 | this.timeout(30000) |
548 | 545 | ||
549 | await checkLiveCleanup(servers[0], liveVideoId, [ 240, 360, 720 ]) | 546 | await checkLiveCleanupAfterSave(servers[0], liveVideoId, [ 240, 360, 720 ]) |
550 | }) | 547 | }) |
551 | }) | 548 | }) |
552 | 549 | ||
@@ -557,13 +554,13 @@ describe('Test live', function () { | |||
557 | async function createLiveWrapper (saveReplay: boolean) { | 554 | async function createLiveWrapper (saveReplay: boolean) { |
558 | const liveAttributes = { | 555 | const liveAttributes = { |
559 | name: 'live video', | 556 | name: 'live video', |
560 | channelId: servers[0].videoChannel.id, | 557 | channelId: servers[0].store.channel.id, |
561 | privacy: VideoPrivacy.PUBLIC, | 558 | privacy: VideoPrivacy.PUBLIC, |
562 | saveReplay | 559 | saveReplay |
563 | } | 560 | } |
564 | 561 | ||
565 | const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes) | 562 | const { uuid } = await commands[0].create({ fields: liveAttributes }) |
566 | return res.body.video.uuid | 563 | return uuid |
567 | } | 564 | } |
568 | 565 | ||
569 | before(async function () { | 566 | before(async function () { |
@@ -573,20 +570,20 @@ describe('Test live', function () { | |||
573 | liveVideoReplayId = await createLiveWrapper(true) | 570 | liveVideoReplayId = await createLiveWrapper(true) |
574 | 571 | ||
575 | await Promise.all([ | 572 | await Promise.all([ |
576 | sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId), | 573 | commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }), |
577 | sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoReplayId) | 574 | commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId }) |
578 | ]) | 575 | ]) |
579 | 576 | ||
580 | await Promise.all([ | 577 | await Promise.all([ |
581 | waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId), | 578 | commands[0].waitUntilPublished({ videoId: liveVideoId }), |
582 | waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) | 579 | commands[0].waitUntilPublished({ videoId: liveVideoReplayId }) |
583 | ]) | 580 | ]) |
584 | 581 | ||
585 | await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2) | 582 | await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 }) |
586 | await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2) | 583 | await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 }) |
587 | 584 | ||
588 | await killallServers([ servers[0] ]) | 585 | await killallServers([ servers[0] ]) |
589 | await reRunServer(servers[0]) | 586 | await servers[0].run() |
590 | 587 | ||
591 | await wait(5000) | 588 | await wait(5000) |
592 | }) | 589 | }) |
@@ -594,13 +591,13 @@ describe('Test live', function () { | |||
594 | it('Should cleanup lives', async function () { | 591 | it('Should cleanup lives', async function () { |
595 | this.timeout(60000) | 592 | this.timeout(60000) |
596 | 593 | ||
597 | await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId) | 594 | await commands[0].waitUntilEnded({ videoId: liveVideoId }) |
598 | }) | 595 | }) |
599 | 596 | ||
600 | it('Should save a live replay', async function () { | 597 | it('Should save a live replay', async function () { |
601 | this.timeout(120000) | 598 | this.timeout(120000) |
602 | 599 | ||
603 | await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId) | 600 | await commands[0].waitUntilPublished({ videoId: liveVideoReplayId }) |
604 | }) | 601 | }) |
605 | }) | 602 | }) |
606 | 603 | ||