]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/live/live-save-replay.ts
Fix stats tests
[github/Chocobozzz/PeerTube.git] / server / tests / api / live / live-save-replay.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import 'mocha'
4 import * as chai from 'chai'
5 import { FfmpegCommand } from 'fluent-ffmpeg'
6 import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared/models'
7 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8 import {
9 addVideoToBlacklist,
10 checkLiveCleanup,
11 cleanupTests,
12 createLive,
13 doubleFollow,
14 flushAndRunMultipleServers,
15 getVideo,
16 getVideosList,
17 removeVideo,
18 sendRTMPStreamInVideo,
19 ServerInfo,
20 setAccessTokensToServers,
21 setDefaultVideoChannel,
22 stopFfmpeg,
23 testFfmpegStreamError,
24 updateCustomSubConfig,
25 updateVideo,
26 wait,
27 waitJobs,
28 waitUntilLiveEnded,
29 waitUntilLivePublished,
30 waitUntilLiveSaved
31 } from '../../../../shared/extra-utils'
32
33 const expect = chai.expect
34
35 describe('Save replay setting', function () {
36 let servers: ServerInfo[] = []
37 let liveVideoUUID: string
38 let ffmpegCommand: FfmpegCommand
39
40 async function createLiveWrapper (saveReplay: boolean) {
41 if (liveVideoUUID) {
42 try {
43 await removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
44 await waitJobs(servers)
45 } catch {}
46 }
47
48 const attributes: LiveVideoCreate = {
49 channelId: servers[0].videoChannel.id,
50 privacy: VideoPrivacy.PUBLIC,
51 name: 'my super live',
52 saveReplay
53 }
54
55 const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
56 return res.body.video.uuid
57 }
58
59 async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) {
60 for (const server of servers) {
61 const length = existsInList ? 1 : 0
62
63 const resVideos = await getVideosList(server.url)
64 expect(resVideos.body.data).to.have.lengthOf(length)
65 expect(resVideos.body.total).to.equal(length)
66
67 if (getStatus) {
68 await getVideo(server.url, videoId, getStatus)
69 }
70 }
71 }
72
73 async function checkVideoState (videoId: string, state: VideoState) {
74 for (const server of servers) {
75 const res = await getVideo(server.url, videoId)
76 expect((res.body as VideoDetails).state.id).to.equal(state)
77 }
78 }
79
80 async function waitUntilLivePublishedOnAllServers (videoId: string) {
81 for (const server of servers) {
82 await waitUntilLivePublished(server.url, server.accessToken, videoId)
83 }
84 }
85
86 async function waitUntilLiveSavedOnAllServers (videoId: string) {
87 for (const server of servers) {
88 await waitUntilLiveSaved(server.url, server.accessToken, videoId)
89 }
90 }
91
92 before(async function () {
93 this.timeout(120000)
94
95 servers = await flushAndRunMultipleServers(2)
96
97 // Get the access tokens
98 await setAccessTokensToServers(servers)
99 await setDefaultVideoChannel(servers)
100
101 // Server 1 and server 2 follow each other
102 await doubleFollow(servers[0], servers[1])
103
104 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, {
105 live: {
106 enabled: true,
107 allowReplay: true,
108 maxDuration: -1,
109 transcoding: {
110 enabled: false,
111 resolutions: {
112 '240p': true,
113 '360p': true,
114 '480p': true,
115 '720p': true,
116 '1080p': true,
117 '1440p': true,
118 '2160p': true
119 }
120 }
121 }
122 })
123 })
124
125 describe('With save replay disabled', function () {
126
127 before(async function () {
128 this.timeout(10000)
129 })
130
131 it('Should correctly create and federate the "waiting for stream" live', async function () {
132 this.timeout(20000)
133
134 liveVideoUUID = await createLiveWrapper(false)
135
136 await waitJobs(servers)
137
138 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
139 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
140 })
141
142 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
143 this.timeout(30000)
144
145 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
146
147 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
148
149 await waitJobs(servers)
150
151 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
152 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
153 })
154
155 it('Should correctly delete the video files after the stream ended', async function () {
156 this.timeout(40000)
157
158 await stopFfmpeg(ffmpegCommand)
159
160 for (const server of servers) {
161 await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
162 }
163 await waitJobs(servers)
164
165 // Live still exist, but cannot be played anymore
166 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
167 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
168
169 // No resolutions saved since we did not save replay
170 await checkLiveCleanup(servers[0], liveVideoUUID, [])
171 })
172
173 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
174 this.timeout(40000)
175
176 liveVideoUUID = await createLiveWrapper(false)
177
178 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
179
180 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
181
182 await waitJobs(servers)
183 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
184
185 await Promise.all([
186 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
187 testFfmpegStreamError(ffmpegCommand, true)
188 ])
189
190 await waitJobs(servers)
191
192 await checkVideosExist(liveVideoUUID, false)
193
194 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
195 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
196
197 await wait(5000)
198 await waitJobs(servers)
199 await checkLiveCleanup(servers[0], liveVideoUUID, [])
200 })
201
202 it('Should correctly terminate the stream on delete and delete the video', async function () {
203 this.timeout(40000)
204
205 liveVideoUUID = await createLiveWrapper(false)
206
207 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
208
209 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
210
211 await waitJobs(servers)
212 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
213
214 await Promise.all([
215 testFfmpegStreamError(ffmpegCommand, true),
216 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
217 ])
218
219 await wait(5000)
220 await waitJobs(servers)
221
222 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
223 await checkLiveCleanup(servers[0], liveVideoUUID, [])
224 })
225 })
226
227 describe('With save replay enabled', function () {
228
229 it('Should correctly create and federate the "waiting for stream" live', async function () {
230 this.timeout(20000)
231
232 liveVideoUUID = await createLiveWrapper(true)
233
234 await waitJobs(servers)
235
236 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
237 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
238 })
239
240 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
241 this.timeout(20000)
242
243 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
244 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
245
246 await waitJobs(servers)
247
248 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
249 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
250 })
251
252 it('Should correctly have saved the live and federated it after the streaming', async function () {
253 this.timeout(30000)
254
255 await stopFfmpeg(ffmpegCommand)
256
257 await waitUntilLiveSavedOnAllServers(liveVideoUUID)
258 await waitJobs(servers)
259
260 // Live has been transcoded
261 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
262 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
263 })
264
265 it('Should update the saved live and correctly federate the updated attributes', async function () {
266 this.timeout(30000)
267
268 await updateVideo(servers[0].url, servers[0].accessToken, liveVideoUUID, { name: 'video updated' })
269 await waitJobs(servers)
270
271 for (const server of servers) {
272 const res = await getVideo(server.url, liveVideoUUID)
273 expect(res.body.name).to.equal('video updated')
274 expect(res.body.isLive).to.be.false
275 }
276 })
277
278 it('Should have cleaned up the live files', async function () {
279 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
280 })
281
282 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
283 this.timeout(40000)
284
285 liveVideoUUID = await createLiveWrapper(true)
286
287 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
288 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
289
290 await waitJobs(servers)
291 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
292
293 await Promise.all([
294 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
295 testFfmpegStreamError(ffmpegCommand, true)
296 ])
297
298 await waitJobs(servers)
299
300 await checkVideosExist(liveVideoUUID, false)
301
302 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
303 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
304
305 await wait(5000)
306 await waitJobs(servers)
307 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
308 })
309
310 it('Should correctly terminate the stream on delete and delete the video', async function () {
311 this.timeout(40000)
312
313 liveVideoUUID = await createLiveWrapper(true)
314
315 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
316 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
317
318 await waitJobs(servers)
319 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
320
321 await Promise.all([
322 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
323 testFfmpegStreamError(ffmpegCommand, true)
324 ])
325
326 await wait(5000)
327 await waitJobs(servers)
328
329 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
330 await checkLiveCleanup(servers[0], liveVideoUUID, [])
331 })
332 })
333
334 after(async function () {
335 await cleanupTests(servers)
336 })
337 })