1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import * as chai from 'chai'
5 import { FfmpegCommand } from 'fluent-ffmpeg'
7 checkLiveCleanupAfterSave,
10 createMultipleServers,
13 setAccessTokensToServers,
14 setDefaultVideoChannel,
16 testFfmpegStreamError,
19 waitUntilLivePublishedOnAllServers,
20 waitUntilLiveSavedOnAllServers
21 } from '@shared/extra-utils'
22 import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
24 const expect = chai.expect
26 describe('Save replay setting', function () {
27 let servers: PeerTubeServer[] = []
28 let liveVideoUUID: string
29 let ffmpegCommand: FfmpegCommand
31 async function createLiveWrapper (saveReplay: boolean) {
34 await servers[0].videos.remove({ id: liveVideoUUID })
35 await waitJobs(servers)
39 const attributes: LiveVideoCreate = {
40 channelId: servers[0].store.channel.id,
41 privacy: VideoPrivacy.PUBLIC,
42 name: 'my super live',
46 const { uuid } = await servers[0].live.create({ fields: attributes })
50 async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
51 for (const server of servers) {
52 const length = existsInList ? 1 : 0
54 const { data, total } = await server.videos.list()
55 expect(data).to.have.lengthOf(length)
56 expect(total).to.equal(length)
59 await server.videos.get({ id: videoId, expectedStatus })
64 async function checkVideoState (videoId: string, state: VideoState) {
65 for (const server of servers) {
66 const video = await server.videos.get({ id: videoId })
67 expect(video.state.id).to.equal(state)
71 before(async function () {
74 servers = await createMultipleServers(2)
76 // Get the access tokens
77 await setAccessTokensToServers(servers)
78 await setDefaultVideoChannel(servers)
80 // Server 1 and server 2 follow each other
81 await doubleFollow(servers[0], servers[1])
83 await servers[0].config.updateCustomSubConfig({
91 resolutions: ConfigCommand.getCustomConfigResolutions(true)
98 describe('With save replay disabled', function () {
100 before(async function () {
104 it('Should correctly create and federate the "waiting for stream" live', async function () {
107 liveVideoUUID = await createLiveWrapper(false)
109 await waitJobs(servers)
111 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
112 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
115 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
118 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
120 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
122 await waitJobs(servers)
124 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
125 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
128 it('Should correctly delete the video files after the stream ended', async function () {
131 await stopFfmpeg(ffmpegCommand)
133 for (const server of servers) {
134 await server.live.waitUntilEnded({ videoId: liveVideoUUID })
136 await waitJobs(servers)
138 // Live still exist, but cannot be played anymore
139 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
140 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
142 // No resolutions saved since we did not save replay
143 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
146 it('Should correctly terminate the stream on blacklist and delete the live', async function () {
149 liveVideoUUID = await createLiveWrapper(false)
151 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
153 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
155 await waitJobs(servers)
156 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
159 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
160 testFfmpegStreamError(ffmpegCommand, true)
163 await waitJobs(servers)
165 await checkVideosExist(liveVideoUUID, false)
167 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
168 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
171 await waitJobs(servers)
172 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
175 it('Should correctly terminate the stream on delete and delete the video', async function () {
178 liveVideoUUID = await createLiveWrapper(false)
180 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
182 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
184 await waitJobs(servers)
185 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
188 testFfmpegStreamError(ffmpegCommand, true),
189 servers[0].videos.remove({ id: liveVideoUUID })
193 await waitJobs(servers)
195 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
196 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
200 describe('With save replay enabled', function () {
202 it('Should correctly create and federate the "waiting for stream" live', async function () {
205 liveVideoUUID = await createLiveWrapper(true)
207 await waitJobs(servers)
209 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
210 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
213 it('Should correctly have updated the live and federated it when streaming in the live', async function () {
216 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
217 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
219 await waitJobs(servers)
221 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
222 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
225 it('Should correctly have saved the live and federated it after the streaming', async function () {
228 await stopFfmpeg(ffmpegCommand)
230 await waitUntilLiveSavedOnAllServers(servers, liveVideoUUID)
231 await waitJobs(servers)
233 // Live has been transcoded
234 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
235 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
238 it('Should update the saved live and correctly federate the updated attributes', async function () {
241 await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
242 await waitJobs(servers)
244 for (const server of servers) {
245 const video = await server.videos.get({ id: liveVideoUUID })
246 expect(video.name).to.equal('video updated')
247 expect(video.isLive).to.be.false
251 it('Should have cleaned up the live files', async function () {
252 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
255 it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
258 liveVideoUUID = await createLiveWrapper(true)
260 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
261 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
263 await waitJobs(servers)
264 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
267 servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
268 testFfmpegStreamError(ffmpegCommand, true)
271 await waitJobs(servers)
273 await checkVideosExist(liveVideoUUID, false)
275 await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
276 await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
279 await waitJobs(servers)
280 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
283 it('Should correctly terminate the stream on delete and delete the video', async function () {
286 liveVideoUUID = await createLiveWrapper(true)
288 ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
289 await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
291 await waitJobs(servers)
292 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
295 servers[0].videos.remove({ id: liveVideoUUID }),
296 testFfmpegStreamError(ffmpegCommand, true)
300 await waitJobs(servers)
302 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
303 await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
307 after(async function () {
308 await cleanupTests(servers)