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