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