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