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