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