PeerTube/server/tests/api/live/live-save-replay.ts

321 lines
10 KiB
TypeScript
Raw Normal View History

2020-11-04 14:16:57 +01:00
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import 'mocha'
import * as chai from 'chai'
import { FfmpegCommand } from 'fluent-ffmpeg'
import {
2021-07-23 11:20:00 +02:00
checkLiveCleanupAfterSave,
2020-11-04 14:16:57 +01:00
cleanupTests,
2021-07-07 11:51:09 +02:00
ConfigCommand,
2021-07-16 09:47:51 +02:00
createMultipleServers,
2021-07-16 14:27:30 +02:00
doubleFollow,
2021-07-16 09:47:51 +02:00
PeerTubeServer,
2020-11-04 14:16:57 +01:00
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
testFfmpegStreamError,
2021-02-19 14:30:00 +01:00
wait,
2021-07-08 10:18:40 +02:00
waitJobs
2021-07-15 10:02:54 +02:00
} from '@shared/extra-utils'
2021-07-16 14:27:30 +02:00
import { HttpStatusCode, LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
2020-11-04 14:16:57 +01:00
const expect = chai.expect
describe('Save replay setting', function () {
2021-07-16 09:47:51 +02:00
let servers: PeerTubeServer[] = []
2020-11-04 14:16:57 +01:00
let liveVideoUUID: string
let ffmpegCommand: FfmpegCommand
async function createLiveWrapper (saveReplay: boolean) {
if (liveVideoUUID) {
try {
2021-07-16 09:04:35 +02:00
await servers[0].videos.remove({ id: liveVideoUUID })
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
} catch {}
}
const attributes: LiveVideoCreate = {
2021-07-16 09:04:35 +02:00
channelId: servers[0].store.channel.id,
2020-11-04 14:16:57 +01:00
privacy: VideoPrivacy.PUBLIC,
name: 'my super live',
saveReplay
}
2021-07-16 09:04:35 +02:00
const { uuid } = await servers[0].live.create({ fields: attributes })
2021-07-08 10:18:40 +02:00
return uuid
2020-11-04 14:16:57 +01:00
}
2021-07-15 10:02:54 +02:00
async function checkVideosExist (videoId: string, existsInList: boolean, expectedStatus?: number) {
2020-11-04 14:16:57 +01:00
for (const server of servers) {
const length = existsInList ? 1 : 0
2021-07-16 09:04:35 +02:00
const { data, total } = await server.videos.list()
2021-07-15 10:02:54 +02:00
expect(data).to.have.lengthOf(length)
expect(total).to.equal(length)
2020-11-04 14:16:57 +01:00
2021-07-15 10:02:54 +02:00
if (expectedStatus) {
2021-07-16 09:04:35 +02:00
await server.videos.get({ id: videoId, expectedStatus })
2020-11-04 14:16:57 +01:00
}
}
}
async function checkVideoState (videoId: string, state: VideoState) {
for (const server of servers) {
2021-07-16 09:04:35 +02:00
const video = await server.videos.get({ id: videoId })
2021-07-15 10:02:54 +02:00
expect(video.state.id).to.equal(state)
2020-11-04 14:16:57 +01:00
}
}
2021-02-18 14:44:12 +01:00
async function waitUntilLivePublishedOnAllServers (videoId: string) {
for (const server of servers) {
2021-07-16 09:04:35 +02:00
await server.live.waitUntilPublished({ videoId })
2021-02-18 14:44:12 +01:00
}
}
2021-02-19 14:30:00 +01:00
async function waitUntilLiveSavedOnAllServers (videoId: string) {
for (const server of servers) {
2021-07-16 09:04:35 +02:00
await server.live.waitUntilSaved({ videoId })
2021-02-19 14:30:00 +01:00
}
}
2020-11-04 14:16:57 +01:00
before(async function () {
this.timeout(120000)
2021-07-16 09:47:51 +02:00
servers = await createMultipleServers(2)
2020-11-04 14:16:57 +01:00
// Get the access tokens
await setAccessTokensToServers(servers)
await setDefaultVideoChannel(servers)
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
2021-07-16 09:04:35 +02:00
await servers[0].config.updateCustomSubConfig({
2021-07-07 11:51:09 +02:00
newConfig: {
live: {
enabled: true,
allowReplay: true,
maxDuration: -1,
transcoding: {
enabled: false,
resolutions: ConfigCommand.getCustomConfigResolutions(true)
}
2020-11-04 14:16:57 +01:00
}
}
})
})
describe('With save replay disabled', function () {
before(async function () {
this.timeout(10000)
})
it('Should correctly create and federate the "waiting for stream" live', async function () {
this.timeout(20000)
liveVideoUUID = await createLiveWrapper(false)
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
})
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
2021-02-18 14:44:12 +01:00
this.timeout(30000)
2020-11-04 14:16:57 +01:00
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
})
it('Should correctly delete the video files after the stream ended', async function () {
2020-12-11 10:36:05 +01:00
this.timeout(40000)
2020-11-04 14:16:57 +01:00
await stopFfmpeg(ffmpegCommand)
2021-02-18 14:44:12 +01:00
for (const server of servers) {
2021-07-16 09:04:35 +02:00
await server.live.waitUntilEnded({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
}
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
// Live still exist, but cannot be played anymore
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
// No resolutions saved since we did not save replay
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
2020-11-04 14:16:57 +01:00
})
it('Should correctly terminate the stream on blacklist and delete the live', async function () {
this.timeout(40000)
liveVideoUUID = await createLiveWrapper(false)
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await Promise.all([
2021-07-16 09:04:35 +02:00
servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
2020-11-04 14:16:57 +01:00
testFfmpegStreamError(ffmpegCommand, true)
])
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false)
2021-07-16 09:04:35 +02:00
await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
2020-11-04 14:16:57 +01:00
2021-02-19 14:30:00 +01:00
await wait(5000)
await waitJobs(servers)
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
2020-11-04 14:16:57 +01:00
})
it('Should correctly terminate the stream on delete and delete the video', async function () {
this.timeout(40000)
liveVideoUUID = await createLiveWrapper(false)
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await Promise.all([
testFfmpegStreamError(ffmpegCommand, true),
2021-07-16 09:04:35 +02:00
servers[0].videos.remove({ id: liveVideoUUID })
2020-11-04 14:16:57 +01:00
])
2021-02-19 14:30:00 +01:00
await wait(5000)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
2020-11-04 14:16:57 +01:00
})
})
describe('With save replay enabled', function () {
it('Should correctly create and federate the "waiting for stream" live', async function () {
this.timeout(20000)
liveVideoUUID = await createLiveWrapper(true)
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
})
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
this.timeout(20000)
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
})
it('Should correctly have saved the live and federated it after the streaming', async function () {
this.timeout(30000)
await stopFfmpeg(ffmpegCommand)
2021-02-19 14:30:00 +01:00
await waitUntilLiveSavedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
// Live has been transcoded
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
})
it('Should update the saved live and correctly federate the updated attributes', async function () {
this.timeout(30000)
2021-07-16 09:04:35 +02:00
await servers[0].videos.update({ id: liveVideoUUID, attributes: { name: 'video updated' } })
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
for (const server of servers) {
2021-07-16 09:04:35 +02:00
const video = await server.videos.get({ id: liveVideoUUID })
2021-07-15 10:02:54 +02:00
expect(video.name).to.equal('video updated')
expect(video.isLive).to.be.false
2020-11-04 14:16:57 +01:00
}
})
it('Should have cleaned up the live files', async function () {
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
2020-11-04 14:16:57 +01:00
})
it('Should correctly terminate the stream on blacklist and blacklist the saved replay video', async function () {
this.timeout(40000)
liveVideoUUID = await createLiveWrapper(true)
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await Promise.all([
2021-07-16 09:04:35 +02:00
servers[0].blacklist.add({ videoId: liveVideoUUID, reason: 'bad live', unfederate: true }),
2020-11-04 14:16:57 +01:00
testFfmpegStreamError(ffmpegCommand, true)
])
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false)
2021-07-16 09:04:35 +02:00
await servers[0].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
await servers[1].videos.get({ id: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
2020-11-04 14:16:57 +01:00
2021-02-19 14:30:00 +01:00
await wait(5000)
await waitJobs(servers)
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [ 720 ])
2020-11-04 14:16:57 +01:00
})
it('Should correctly terminate the stream on delete and delete the video', async function () {
this.timeout(40000)
liveVideoUUID = await createLiveWrapper(true)
2021-07-16 09:04:35 +02:00
ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
2021-02-18 14:44:12 +01:00
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
2020-11-04 14:16:57 +01:00
await Promise.all([
2021-07-16 09:04:35 +02:00
servers[0].videos.remove({ id: liveVideoUUID }),
2020-11-04 14:16:57 +01:00
testFfmpegStreamError(ffmpegCommand, true)
])
2021-02-19 14:30:00 +01:00
await wait(5000)
2020-11-04 14:16:57 +01:00
await waitJobs(servers)
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
2021-07-23 11:20:00 +02:00
await checkLiveCleanupAfterSave(servers[0], liveVideoUUID, [])
2020-11-04 14:16:57 +01:00
})
})
after(async function () {
await cleanupTests(servers)
})
})