2021-06-16 08:14:41 -05:00
|
|
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
|
|
|
|
|
|
|
import 'mocha'
|
|
|
|
import * as chai from 'chai'
|
2021-12-17 04:58:15 -06:00
|
|
|
import { wait } from '@shared/core-utils'
|
2021-06-16 08:14:41 -05:00
|
|
|
import { VideoPrivacy, VideoState } from '@shared/models'
|
|
|
|
import {
|
|
|
|
cleanupTests,
|
2021-07-16 02:47:51 -05:00
|
|
|
createMultipleServers,
|
2021-07-16 07:27:30 -05:00
|
|
|
doubleFollow,
|
2021-07-16 02:47:51 -05:00
|
|
|
PeerTubeServer,
|
2021-06-16 08:14:41 -05:00
|
|
|
setAccessTokensToServers,
|
|
|
|
setDefaultVideoChannel,
|
|
|
|
stopFfmpeg,
|
|
|
|
waitJobs,
|
|
|
|
waitUntilLivePublishedOnAllServers
|
2021-12-17 04:58:15 -06:00
|
|
|
} from '@shared/server-commands'
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
const expect = chai.expect
|
|
|
|
|
|
|
|
describe('Test live', function () {
|
2021-07-16 02:47:51 -05:00
|
|
|
let servers: PeerTubeServer[] = []
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
before(async function () {
|
|
|
|
this.timeout(120000)
|
|
|
|
|
2021-07-16 02:47:51 -05:00
|
|
|
servers = await createMultipleServers(2)
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
// Get the access tokens
|
|
|
|
await setAccessTokensToServers(servers)
|
|
|
|
await setDefaultVideoChannel(servers)
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
await servers[0].config.updateCustomSubConfig({
|
2021-07-07 04:51:09 -05:00
|
|
|
newConfig: {
|
|
|
|
live: {
|
|
|
|
enabled: true,
|
|
|
|
allowReplay: true,
|
|
|
|
transcoding: {
|
|
|
|
enabled: false
|
|
|
|
}
|
2021-06-16 08:14:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Server 1 and server 2 follow each other
|
|
|
|
await doubleFollow(servers[0], servers[1])
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('Live socket messages', function () {
|
|
|
|
|
|
|
|
async function createLiveWrapper () {
|
|
|
|
const liveAttributes = {
|
|
|
|
name: 'live video',
|
2021-07-16 02:04:35 -05:00
|
|
|
channelId: servers[0].store.channel.id,
|
2021-06-16 08:14:41 -05:00
|
|
|
privacy: VideoPrivacy.PUBLIC
|
|
|
|
}
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const { uuid } = await servers[0].live.create({ fields: liveAttributes })
|
2021-07-08 03:18:40 -05:00
|
|
|
return uuid
|
2021-06-16 08:14:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
it('Should correctly send a message when the live starts and ends', async function () {
|
|
|
|
this.timeout(60000)
|
|
|
|
|
|
|
|
const localStateChanges: VideoState[] = []
|
|
|
|
const remoteStateChanges: VideoState[] = []
|
|
|
|
|
|
|
|
const liveVideoUUID = await createLiveWrapper()
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
{
|
2021-07-16 02:04:35 -05:00
|
|
|
const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const localSocket = servers[0].socketIO.getLiveNotificationSocket()
|
2021-06-16 08:14:41 -05:00
|
|
|
localSocket.on('state-change', data => localStateChanges.push(data.state))
|
|
|
|
localSocket.emit('subscribe', { videoId })
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2021-07-16 02:04:35 -05:00
|
|
|
const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
|
2021-06-16 08:14:41 -05:00
|
|
|
remoteSocket.on('state-change', data => remoteStateChanges.push(data.state))
|
|
|
|
remoteSocket.emit('subscribe', { videoId })
|
|
|
|
}
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
|
|
|
|
expect(stateChanges).to.have.length.at.least(1)
|
|
|
|
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
|
|
|
|
}
|
|
|
|
|
2021-07-08 03:18:40 -05:00
|
|
|
await stopFfmpeg(ffmpegCommand)
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
for (const server of servers) {
|
2021-07-16 02:04:35 -05:00
|
|
|
await server.live.waitUntilEnded({ videoId: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
}
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
|
|
|
|
expect(stateChanges).to.have.length.at.least(2)
|
|
|
|
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.LIVE_ENDED)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
it('Should correctly send views change notification', async function () {
|
|
|
|
this.timeout(60000)
|
|
|
|
|
|
|
|
let localLastVideoViews = 0
|
|
|
|
let remoteLastVideoViews = 0
|
|
|
|
|
|
|
|
const liveVideoUUID = await createLiveWrapper()
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
{
|
2021-07-16 02:04:35 -05:00
|
|
|
const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const localSocket = servers[0].socketIO.getLiveNotificationSocket()
|
2021-06-16 08:14:41 -05:00
|
|
|
localSocket.on('views-change', data => { localLastVideoViews = data.views })
|
|
|
|
localSocket.emit('subscribe', { videoId })
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2021-07-16 02:04:35 -05:00
|
|
|
const videoId = await servers[1].videos.getId({ uuid: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const remoteSocket = servers[1].socketIO.getLiveNotificationSocket()
|
2021-06-16 08:14:41 -05:00
|
|
|
remoteSocket.on('views-change', data => { remoteLastVideoViews = data.views })
|
|
|
|
remoteSocket.emit('subscribe', { videoId })
|
|
|
|
}
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
expect(localLastVideoViews).to.equal(0)
|
|
|
|
expect(remoteLastVideoViews).to.equal(0)
|
|
|
|
|
2022-03-24 07:36:47 -05:00
|
|
|
await servers[0].views.simulateView({ id: liveVideoUUID })
|
|
|
|
await servers[1].views.simulateView({ id: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
expect(localLastVideoViews).to.equal(2)
|
|
|
|
expect(remoteLastVideoViews).to.equal(2)
|
|
|
|
|
2021-07-08 03:18:40 -05:00
|
|
|
await stopFfmpeg(ffmpegCommand)
|
2021-06-16 08:14:41 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
it('Should not receive a notification after unsubscribe', async function () {
|
|
|
|
this.timeout(120000)
|
|
|
|
|
|
|
|
const stateChanges: VideoState[] = []
|
|
|
|
|
|
|
|
const liveVideoUUID = await createLiveWrapper()
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const videoId = await servers[0].videos.getId({ uuid: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const socket = servers[0].socketIO.getLiveNotificationSocket()
|
2021-06-16 08:14:41 -05:00
|
|
|
socket.on('state-change', data => stateChanges.push(data.state))
|
|
|
|
socket.emit('subscribe', { videoId })
|
|
|
|
|
2021-07-16 02:04:35 -05:00
|
|
|
const command = await servers[0].live.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
2021-06-16 08:14:41 -05:00
|
|
|
|
|
|
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
// Notifier waits before sending a notification
|
|
|
|
await wait(10000)
|
|
|
|
|
|
|
|
expect(stateChanges).to.have.lengthOf(1)
|
|
|
|
socket.emit('unsubscribe', { videoId })
|
|
|
|
|
|
|
|
await stopFfmpeg(command)
|
|
|
|
await waitJobs(servers)
|
|
|
|
|
|
|
|
expect(stateChanges).to.have.lengthOf(1)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
after(async function () {
|
|
|
|
await cleanupTests(servers)
|
|
|
|
})
|
|
|
|
})
|