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