]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/live/live-save-replay.ts
Introduce config command
[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 ConfigCommand,
13 createLive,
14 doubleFollow,
15 flushAndRunMultipleServers,
16 getVideo,
17 getVideosList,
18 removeVideo,
19 sendRTMPStreamInVideo,
20 ServerInfo,
21 setAccessTokensToServers,
22 setDefaultVideoChannel,
23 stopFfmpeg,
24 testFfmpegStreamError,
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 servers[0].configCommand.updateCustomSubConfig({
105 newConfig: {
106 live: {
107 enabled: true,
108 allowReplay: true,
109 maxDuration: -1,
110 transcoding: {
111 enabled: false,
112 resolutions: ConfigCommand.getCustomConfigResolutions(true)
113 }
114 }
115 }
116 })
117 })
118
119 describe('With save replay disabled', function () {
120
121 before(async function () {
122 this.timeout(10000)
123 })
124
125 it('Should correctly create and federate the "waiting for stream" live', async function () {
126 this.timeout(20000)
127
128 liveVideoUUID = await createLiveWrapper(false)
129
130 await waitJobs(servers)
131
132 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
133 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
134 })
135
136 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
137 this.timeout(30000)
138
139 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
140
141 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
142
143 await waitJobs(servers)
144
145 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
146 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
147 })
148
149 it('Should correctly delete the video files after the stream ended', async function () {
150 this.timeout(40000)
151
152 await stopFfmpeg(ffmpegCommand)
153
154 for (const server of servers) {
155 await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
156 }
157 await waitJobs(servers)
158
159 // Live still exist, but cannot be played anymore
160 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
161 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
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 wait(5000)
192 await waitJobs(servers)
193 await checkLiveCleanup(servers[0], liveVideoUUID, [])
194 })
195
196 it('Should correctly terminate the stream on delete and delete the video', async function () {
197 this.timeout(40000)
198
199 liveVideoUUID = await createLiveWrapper(false)
200
201 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
202
203 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
204
205 await waitJobs(servers)
206 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
207
208 await Promise.all([
209 testFfmpegStreamError(ffmpegCommand, true),
210 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
211 ])
212
213 await wait(5000)
214 await waitJobs(servers)
215
216 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
217 await checkLiveCleanup(servers[0], liveVideoUUID, [])
218 })
219 })
220
221 describe('With save replay enabled', function () {
222
223 it('Should correctly create and federate the "waiting for stream" live', async function () {
224 this.timeout(20000)
225
226 liveVideoUUID = await createLiveWrapper(true)
227
228 await waitJobs(servers)
229
230 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
231 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
232 })
233
234 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
235 this.timeout(20000)
236
237 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
238 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
239
240 await waitJobs(servers)
241
242 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
243 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
244 })
245
246 it('Should correctly have saved the live and federated it after the streaming', async function () {
247 this.timeout(30000)
248
249 await stopFfmpeg(ffmpegCommand)
250
251 await waitUntilLiveSavedOnAllServers(liveVideoUUID)
252 await waitJobs(servers)
253
254 // Live has been transcoded
255 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
256 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
257 })
258
259 it('Should update the saved live and correctly federate the updated attributes', async function () {
260 this.timeout(30000)
261
262 await updateVideo(servers[0].url, servers[0].accessToken, liveVideoUUID, { name: 'video updated' })
263 await waitJobs(servers)
264
265 for (const server of servers) {
266 const res = await getVideo(server.url, liveVideoUUID)
267 expect(res.body.name).to.equal('video updated')
268 expect(res.body.isLive).to.be.false
269 }
270 })
271
272 it('Should have cleaned up the live files', async function () {
273 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
274 })
275
276 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
277 this.timeout(40000)
278
279 liveVideoUUID = await createLiveWrapper(true)
280
281 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
282 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
283
284 await waitJobs(servers)
285 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
286
287 await Promise.all([
288 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
289 testFfmpegStreamError(ffmpegCommand, true)
290 ])
291
292 await waitJobs(servers)
293
294 await checkVideosExist(liveVideoUUID, false)
295
296 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
297 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
298
299 await wait(5000)
300 await waitJobs(servers)
301 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
302 })
303
304 it('Should correctly terminate the stream on delete and delete the video', async function () {
305 this.timeout(40000)
306
307 liveVideoUUID = await createLiveWrapper(true)
308
309 ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
310 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
311
312 await waitJobs(servers)
313 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
314
315 await Promise.all([
316 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
317 testFfmpegStreamError(ffmpegCommand, true)
318 ])
319
320 await wait(5000)
321 await waitJobs(servers)
322
323 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
324 await checkLiveCleanup(servers[0], liveVideoUUID, [])
325 })
326 })
327
328 after(async function () {
329 await cleanupTests(servers)
330 })
331 })