1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { FfmpegCommand } from 'fluent-ffmpeg'
10 createMultipleServers,
13 setAccessTokensToServers,
14 setDefaultVideoChannel,
16 testFfmpegStreamError,
19 } from '@shared/extra-utils'
20 import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
22 const expect = chai.expect
24 describe('Save replay setting', function () {
25 let servers: PeerTubeServer[] = []
26 let liveVideoUUID: string
27 let ffmpegCommand: FfmpegCommand
29 async function createLiveWrapper (saveReplay: boolean) {
32 await servers[0].videos.remove({ id: liveVideoUUID })
33 await waitJobs(servers)
37 const attributes: LiveVideoCreate = {
38 channelId: servers[0].store.channel.id,
39 privacy: VideoPrivacy.PUBLIC,
40 name: 'my super live',
44 const { uuid } = await servers[0].live.create({ fields: attributes })
48 async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
49 for (const server of servers) {
50 const length = existsInList ? 1 : 0
52 const { data, total } = await server.videos.list()
53 expect(data).to.have.lengthOf(length)
54 expect(total).to.equal(length)
57 await server.videos.get({ id: videoId, expectedStatus })
62 async function checkVideoState (videoId: string, state: VideoState) {
63 for (const server of servers) {
64 const video = await server.videos.get({ id: videoId })
65 expect(video.state.id).to.equal(state)
69 async function waitUntilLivePublishedOnAllServers (videoId: string) {
70 for (const server of servers) {
71 await server.live.waitUntilPublished({ videoId })
75 async function waitUntilLiveSavedOnAllServers (videoId: string) {
76 for (const server of servers) {
77 await server.live.waitUntilSaved({ videoId })
81 before(async function () {
84 servers = await createMultipleServers(2)
86 // Get the access tokens
87 await setAccessTokensToServers(servers)
88 await setDefaultVideoChannel(servers)
90 // Server 1 and server 2 follow each other
91 await doubleFollow(servers[0], servers[1])
93 await servers[0].config.updateCustomSubConfig({
101 resolutions: ConfigCommand.getCustomConfigResolutions(true)
108 describe('With save replay disabled', function () {
110 before(async function () {
114 it('Should correctly create and federate the "waiting for stream" live', async function () {
117 liveVideoUUID = await createLiveWrapper(false)
119 await waitJobs(servers)
121 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
122 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
125 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
128 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
130 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
132 await waitJobs(servers)
134 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
135 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
138 it('Should correctly delete the video files after the stream ended', async function () {
141 await stopFfmpeg(ffmpegCommand)
143 for (const server of servers) {
144 await server.live.waitUntilEnded({ videoId: liveVideoUUID })
146 await waitJobs(servers)
148 // Live still exist, but cannot be played anymore
149 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
150 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
152 // No resolutions saved since we did not save replay
153 await checkLiveCleanup(servers[0], liveVideoUUID, [])
156 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
159 liveVideoUUID = await createLiveWrapper(false)
161 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
163 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
165 await waitJobs(servers)
166 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
169 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
170 testFfmpegStreamError(ffmpegCommand, true)
173 await waitJobs(servers)
175 await checkVideosExist(liveVideoUUID, false)
177 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
178 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
181 await waitJobs(servers)
182 await checkLiveCleanup(servers[0], liveVideoUUID, [])
185 it('Should correctly terminate the stream on delete and delete the video', async function () {
188 liveVideoUUID = await createLiveWrapper(false)
190 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
192 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
194 await waitJobs(servers)
195 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
198 testFfmpegStreamError(ffmpegCommand, true),
199 servers[0].videos.remove({ id: liveVideoUUID })
203 await waitJobs(servers)
205 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
206 await checkLiveCleanup(servers[0], liveVideoUUID, [])
210 describe('With save replay enabled', function () {
212 it('Should correctly create and federate the "waiting for stream" live', async function () {
215 liveVideoUUID = await createLiveWrapper(true)
217 await waitJobs(servers)
219 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
220 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
223 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
226 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
227 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
229 await waitJobs(servers)
231 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
232 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
235 it('Should correctly have saved the live and federated it after the streaming', async function () {
238 await stopFfmpeg(ffmpegCommand)
240 await waitUntilLiveSavedOnAllServers(liveVideoUUID)
241 await waitJobs(servers)
243 // Live has been transcoded
244 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
245 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
248 it('Should update the saved live and correctly federate the updated attributes', async function () {
251 await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
252 await waitJobs(servers)
254 for (const server of servers) {
255 const video = await server.videos.get({ id: liveVideoUUID })
256 expect(video.name).to.equal('video updated')
257 expect(video.isLive).to.be.false
261 it('Should have cleaned up the live files', async function () {
262 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
265 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
268 liveVideoUUID = await createLiveWrapper(true)
270 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
271 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
273 await waitJobs(servers)
274 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
277 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
278 testFfmpegStreamError(ffmpegCommand, true)
281 await waitJobs(servers)
283 await checkVideosExist(liveVideoUUID, false)
285 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
286 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
289 await waitJobs(servers)
290 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
293 it('Should correctly terminate the stream on delete and delete the video', async function () {
296 liveVideoUUID = await createLiveWrapper(true)
298 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
299 await waitUntilLivePublishedOnAllServers(liveVideoUUID)
301 await waitJobs(servers)
302 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
305 servers[0].videos.remove({ id: liveVideoUUID }),
306 testFfmpegStreamError(ffmpegCommand, true)
310 await waitJobs(servers)
312 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
313 await checkLiveCleanup(servers[0], liveVideoUUID, [])
317 after(async function () {
318 await cleanupTests(servers)