1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { FfmpegCommand } from 'fluent-ffmpeg'
6 import { HttpStatusCode } from '@shared/core-utils'
12 flushAndRunMultipleServers,
14 setAccessTokensToServers,
15 setDefaultVideoChannel,
17 testFfmpegStreamError,
20 } from '@shared/extra-utils'
21 import { LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
23 const expect = chai.expect
25 describe('Save replay setting', function () {
26 let servers: ServerInfo[] = []
27 let liveVideoUUID: string
28 let ffmpegCommand: FfmpegCommand
30 async function createLiveWrapper (saveReplay: boolean) {
33 await servers[0].videosCommand.remove({ id: liveVideoUUID })
34 await waitJobs(servers)
38 const attributes: LiveVideoCreate = {
39 channelId: servers[0].videoChannel.id,
40 privacy: VideoPrivacy.PUBLIC,
41 name: 'my super live',
45 const { uuid } = await servers[0].liveCommand.create({ fields: attributes })
49 async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
50 for (const server of servers) {
51 const length = existsInList ? 1 : 0
53 const { data, total } = await server.videosCommand.list()
54 expect(data).to.have.lengthOf(length)
55 expect(total).to.equal(length)
58 await server.videosCommand.get({ id: videoId, expectedStatus })
63 async function checkVideoState (videoId: string, state: VideoState) {
64 for (const server of servers) {
65 const video = await server.videosCommand.get({ id: videoId })
66 expect(video.state.id).to.equal(state)
70 async function waitUntilLivePublishedOnAllServers (videoId: string) {
71 for (const server of servers) {
72 await server.liveCommand.waitUntilPublished({ videoId })
76 async function waitUntilLiveSavedOnAllServers (videoId: string) {
77 for (const server of servers) {
78 await server.liveCommand.waitUntilSaved({ videoId })
82 before(async function () {
85 servers = await flushAndRunMultipleServers(2)
87 // Get the access tokens
88 await setAccessTokensToServers(servers)
89 await setDefaultVideoChannel(servers)
91 // Server 1 and server 2 follow each other
92 await doubleFollow(servers[0], servers[1])
94 await servers[0].configCommand.updateCustomSubConfig({
102 resolutions: ConfigCommand.getCustomConfigResolutions(true)
109 describe('With save replay disabled', function () {
111 before(async function () {
115 it('Should correctly create and federate the "waiting for stream" live', async function () {
118 liveVideoUUID = await createLiveWrapper(false)
120 await waitJobs(servers)
122 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
123 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
126 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
129 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
131 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
133 await waitJobs(servers)
135 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
136 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
139 it('Should correctly delete the video files after the stream ended', async function () {
142 await stopFfmpeg(ffmpegCommand)
144 for (const server of servers) {
145 await server.liveCommand.waitUntilEnded({ videoId: liveVideoUUID })
147 await waitJobs(servers)
149 // Live still exist, but cannot be played anymore
150 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
151 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
153 // No resolutions saved since we did not save replay
154 await checkLiveCleanup(servers[0], liveVideoUUID, [])
157 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
160 liveVideoUUID = await createLiveWrapper(false)
162 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
164 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
166 await waitJobs(servers)
167 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
170 servers[0].blacklistCommand.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
171 testFfmpegStreamError(ffmpegCommand, true)
174 await waitJobs(servers)
176 await checkVideosExist(liveVideoUUID, false)
178 await servers[0].videosCommand.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
179 await servers[1].videosCommand.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
182 await waitJobs(servers)
183 await checkLiveCleanup(servers[0], liveVideoUUID, [])
186 it('Should correctly terminate the stream on delete and delete the video', async function () {
189 liveVideoUUID = await createLiveWrapper(false)
191 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
193 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
195 await waitJobs(servers)
196 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
199 testFfmpegStreamError(ffmpegCommand, true),
200 servers[0].videosCommand.remove({ id: liveVideoUUID })
204 await waitJobs(servers)
206 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
207 await checkLiveCleanup(servers[0], liveVideoUUID, [])
211 describe('With save replay enabled', function () {
213 it('Should correctly create and federate the "waiting for stream" live', async function () {
216 liveVideoUUID = await createLiveWrapper(true)
218 await waitJobs(servers)
220 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
221 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
224 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
227 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
228 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
230 await waitJobs(servers)
232 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
233 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
236 it('Should correctly have saved the live and federated it after the streaming', async function () {
239 await stopFfmpeg(ffmpegCommand)
241 await waitUntilLiveSavedOnAllServers(liveVideoUUID)
242 await waitJobs(servers)
244 // Live has been transcoded
245 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
246 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
249 it('Should update the saved live and correctly federate the updated attributes', async function () {
252 await servers[0].videosCommand.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
253 await waitJobs(servers)
255 for (const server of servers) {
256 const video = await server.videosCommand.get({ id: liveVideoUUID })
257 expect(video.name).to.equal('video updated')
258 expect(video.isLive).to.be.false
262 it('Should have cleaned up the live files', async function () {
263 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
266 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
269 liveVideoUUID = await createLiveWrapper(true)
271 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
272 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
274 await waitJobs(servers)
275 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
278 servers[0].blacklistCommand.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
279 testFfmpegStreamError(ffmpegCommand, true)
282 await waitJobs(servers)
284 await checkVideosExist(liveVideoUUID, false)
286 await servers[0].videosCommand.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
287 await servers[1].videosCommand.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
290 await waitJobs(servers)
291 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
294 it('Should correctly terminate the stream on delete and delete the video', async function () {
297 liveVideoUUID = await createLiveWrapper(true)
299 ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
300 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
302 await waitJobs(servers)
303 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
306 servers[0].videosCommand.remove({ id: liveVideoUUID }),
307 testFfmpegStreamError(ffmpegCommand, true)
311 await waitJobs(servers)
313 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
314 await checkLiveCleanup(servers[0], liveVideoUUID, [])
318 after(async function () {
319 await cleanupTests(servers)