mirror of https://github.com/Chocobozzz/PeerTube
Introduce live command
parent
2c27e70471
commit
4f2199144e
|
@ -2,27 +2,24 @@
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import { omit } from 'lodash'
|
import { omit } from 'lodash'
|
||||||
import { LiveVideo, VideoCreateResult, VideoPrivacy } from '@shared/models'
|
import { VideoCreateResult, VideoPrivacy } from '@shared/models'
|
||||||
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
import {
|
import {
|
||||||
buildAbsoluteFixturePath,
|
buildAbsoluteFixturePath,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createUser,
|
createUser,
|
||||||
flushAndRunServer,
|
flushAndRunServer,
|
||||||
getLive,
|
|
||||||
getMyUserInformation,
|
getMyUserInformation,
|
||||||
immutableAssign,
|
immutableAssign,
|
||||||
|
LiveCommand,
|
||||||
makePostBodyRequest,
|
makePostBodyRequest,
|
||||||
makeUploadRequest,
|
makeUploadRequest,
|
||||||
runAndTestFfmpegStreamError,
|
|
||||||
sendRTMPStream,
|
sendRTMPStream,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
stopFfmpeg,
|
stopFfmpeg,
|
||||||
updateLive,
|
|
||||||
uploadVideoAndGetId,
|
uploadVideoAndGetId,
|
||||||
userLogin,
|
userLogin
|
||||||
waitUntilLivePublished
|
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
describe('Test video lives API validator', function () {
|
describe('Test video lives API validator', function () {
|
||||||
|
@ -32,6 +29,7 @@ describe('Test video lives API validator', function () {
|
||||||
let channelId: number
|
let channelId: number
|
||||||
let video: VideoCreateResult
|
let video: VideoCreateResult
|
||||||
let videoIdNotLive: number
|
let videoIdNotLive: number
|
||||||
|
let command: LiveCommand
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -66,6 +64,8 @@ describe('Test video lives API validator', function () {
|
||||||
{
|
{
|
||||||
videoIdNotLive = (await uploadVideoAndGetId({ server, videoName: 'not live' })).id
|
videoIdNotLive = (await uploadVideoAndGetId({ server, videoName: 'not live' })).id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command = server.liveCommand
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When creating a live', function () {
|
describe('When creating a live', function () {
|
||||||
|
@ -337,70 +337,72 @@ describe('Test video lives API validator', function () {
|
||||||
describe('When getting live information', function () {
|
describe('When getting live information', function () {
|
||||||
|
|
||||||
it('Should fail without access token', async function () {
|
it('Should fail without access token', async function () {
|
||||||
await getLive(server.url, '', video.id, HttpStatusCode.UNAUTHORIZED_401)
|
await command.getLive({ token: '', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a bad access token', async function () {
|
it('Should fail with a bad access token', async function () {
|
||||||
await getLive(server.url, 'toto', video.id, HttpStatusCode.UNAUTHORIZED_401)
|
await command.getLive({ token: 'toto', videoId: video.id, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with access token of another user', async function () {
|
it('Should fail with access token of another user', async function () {
|
||||||
await getLive(server.url, userAccessToken, video.id, HttpStatusCode.FORBIDDEN_403)
|
await command.getLive({ token: userAccessToken, videoId: video.id, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a bad video id', async function () {
|
it('Should fail with a bad video id', async function () {
|
||||||
await getLive(server.url, server.accessToken, 'toto', HttpStatusCode.BAD_REQUEST_400)
|
await command.getLive({ videoId: 'toto', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an unknown video id', async function () {
|
it('Should fail with an unknown video id', async function () {
|
||||||
await getLive(server.url, server.accessToken, 454555, HttpStatusCode.NOT_FOUND_404)
|
await command.getLive({ videoId: 454555, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a non live video', async function () {
|
it('Should fail with a non live video', async function () {
|
||||||
await getLive(server.url, server.accessToken, videoIdNotLive, HttpStatusCode.NOT_FOUND_404)
|
await command.getLive({ videoId: videoIdNotLive, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
it('Should succeed with the correct params', async function () {
|
||||||
await getLive(server.url, server.accessToken, video.id)
|
await command.getLive({ videoId: video.id })
|
||||||
await getLive(server.url, server.accessToken, video.shortUUID)
|
await command.getLive({ videoId: video.uuid })
|
||||||
|
await command.getLive({ videoId: video.shortUUID })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When updating live information', async function () {
|
describe('When updating live information', async function () {
|
||||||
|
|
||||||
it('Should fail without access token', async function () {
|
it('Should fail without access token', async function () {
|
||||||
await updateLive(server.url, '', video.id, {}, HttpStatusCode.UNAUTHORIZED_401)
|
await command.updateLive({ token: '', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a bad access token', async function () {
|
it('Should fail with a bad access token', async function () {
|
||||||
await updateLive(server.url, 'toto', video.id, {}, HttpStatusCode.UNAUTHORIZED_401)
|
await command.updateLive({ token: 'toto', videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with access token of another user', async function () {
|
it('Should fail with access token of another user', async function () {
|
||||||
await updateLive(server.url, userAccessToken, video.id, {}, HttpStatusCode.FORBIDDEN_403)
|
await command.updateLive({ token: userAccessToken, videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a bad video id', async function () {
|
it('Should fail with a bad video id', async function () {
|
||||||
await updateLive(server.url, server.accessToken, 'toto', {}, HttpStatusCode.BAD_REQUEST_400)
|
await command.updateLive({ videoId: 'toto', fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an unknown video id', async function () {
|
it('Should fail with an unknown video id', async function () {
|
||||||
await updateLive(server.url, server.accessToken, 454555, {}, HttpStatusCode.NOT_FOUND_404)
|
await command.updateLive({ videoId: 454555, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a non live video', async function () {
|
it('Should fail with a non live video', async function () {
|
||||||
await updateLive(server.url, server.accessToken, videoIdNotLive, {}, HttpStatusCode.NOT_FOUND_404)
|
await command.updateLive({ videoId: videoIdNotLive, fields: {}, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with save replay and permanent live set to true', async function () {
|
it('Should fail with save replay and permanent live set to true', async function () {
|
||||||
const fields = { saveReplay: true, permanentLive: true }
|
const fields = { saveReplay: true, permanentLive: true }
|
||||||
|
|
||||||
await updateLive(server.url, server.accessToken, video.id, fields, HttpStatusCode.BAD_REQUEST_400)
|
await command.updateLive({ videoId: video.id, fields, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with the correct params', async function () {
|
it('Should succeed with the correct params', async function () {
|
||||||
await updateLive(server.url, server.accessToken, video.id, { saveReplay: false })
|
await command.updateLive({ videoId: video.id, fields: { saveReplay: false } })
|
||||||
await updateLive(server.url, server.accessToken, video.shortUUID, { saveReplay: false })
|
await command.updateLive({ videoId: video.uuid, fields: { saveReplay: false } })
|
||||||
|
await command.updateLive({ videoId: video.shortUUID, fields: { saveReplay: false } })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to update replay status if replay is not allowed on the instance', async function () {
|
it('Should fail to update replay status if replay is not allowed on the instance', async function () {
|
||||||
|
@ -413,36 +415,34 @@ describe('Test video lives API validator', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await updateLive(server.url, server.accessToken, video.id, { saveReplay: true }, HttpStatusCode.FORBIDDEN_403)
|
await command.updateLive({ videoId: video.id, fields: { saveReplay: true }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to update a live if it has already started', async function () {
|
it('Should fail to update a live if it has already started', async function () {
|
||||||
this.timeout(40000)
|
this.timeout(40000)
|
||||||
|
|
||||||
const resLive = await getLive(server.url, server.accessToken, video.id)
|
const live = await command.getLive({ videoId: video.id })
|
||||||
const live: LiveVideo = resLive.body
|
|
||||||
|
|
||||||
const command = sendRTMPStream(live.rtmpUrl, live.streamKey)
|
const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
|
||||||
|
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, video.id)
|
await command.waitUntilLivePublished({ videoId: video.id })
|
||||||
await updateLive(server.url, server.accessToken, video.id, {}, HttpStatusCode.BAD_REQUEST_400)
|
await command.updateLive({ videoId: video.id, fields: {}, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to stream twice in the save live', async function () {
|
it('Should fail to stream twice in the save live', async function () {
|
||||||
this.timeout(40000)
|
this.timeout(40000)
|
||||||
|
|
||||||
const resLive = await getLive(server.url, server.accessToken, video.id)
|
const live = await command.getLive({ videoId: video.id })
|
||||||
const live: LiveVideo = resLive.body
|
|
||||||
|
|
||||||
const command = sendRTMPStream(live.rtmpUrl, live.streamKey)
|
const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
|
||||||
|
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, video.id)
|
await command.waitUntilLivePublished({ videoId: video.id })
|
||||||
|
|
||||||
await runAndTestFfmpegStreamError(server.url, server.accessToken, video.id, true)
|
await command.runAndTestFfmpegStreamError({ videoId: video.id, shouldHaveError: true })
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -7,19 +7,16 @@ import {
|
||||||
checkLiveCleanup,
|
checkLiveCleanup,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
ConfigCommand,
|
ConfigCommand,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
generateUser,
|
generateUser,
|
||||||
getVideo,
|
getVideo,
|
||||||
runAndTestFfmpegStreamError,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
updateUser,
|
updateUser,
|
||||||
wait,
|
wait,
|
||||||
waitJobs,
|
waitJobs
|
||||||
waitUntilLivePublished
|
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@ -38,8 +35,8 @@ describe('Test live constraints', function () {
|
||||||
saveReplay
|
saveReplay
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, userAccessToken, liveAttributes)
|
const { uuid } = await servers[0].liveCommand.createLive({ token: userAccessToken, fields: liveAttributes })
|
||||||
return res.body.video.uuid as string
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
|
async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
|
||||||
|
@ -56,7 +53,7 @@ describe('Test live constraints', function () {
|
||||||
|
|
||||||
async function waitUntilLivePublishedOnAllServers (videoId: string) {
|
async function waitUntilLivePublishedOnAllServers (videoId: string) {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, videoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +105,7 @@ describe('Test live constraints', function () {
|
||||||
this.timeout(60000)
|
this.timeout(60000)
|
||||||
|
|
||||||
const userVideoLiveoId = await createLiveWrapper(false)
|
const userVideoLiveoId = await createLiveWrapper(false)
|
||||||
await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false)
|
await servers[0].liveCommand.runAndTestFfmpegStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have size limit depending on user global quota if save replay is enabled', async function () {
|
it('Should have size limit depending on user global quota if save replay is enabled', async function () {
|
||||||
|
@ -118,7 +115,7 @@ describe('Test live constraints', function () {
|
||||||
await wait(5000)
|
await wait(5000)
|
||||||
|
|
||||||
const userVideoLiveoId = await createLiveWrapper(true)
|
const userVideoLiveoId = await createLiveWrapper(true)
|
||||||
await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
|
await servers[0].liveCommand.runAndTestFfmpegStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -135,7 +132,7 @@ describe('Test live constraints', function () {
|
||||||
await updateQuota({ total: -1, daily: 1 })
|
await updateQuota({ total: -1, daily: 1 })
|
||||||
|
|
||||||
const userVideoLiveoId = await createLiveWrapper(true)
|
const userVideoLiveoId = await createLiveWrapper(true)
|
||||||
await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
|
await servers[0].liveCommand.runAndTestFfmpegStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -152,7 +149,7 @@ describe('Test live constraints', function () {
|
||||||
await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
|
await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
|
||||||
|
|
||||||
const userVideoLiveoId = await createLiveWrapper(true)
|
const userVideoLiveoId = await createLiveWrapper(true)
|
||||||
await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, false)
|
await servers[0].liveCommand.runAndTestFfmpegStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: false })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have max duration limit', async function () {
|
it('Should have max duration limit', async function () {
|
||||||
|
@ -173,7 +170,7 @@ describe('Test live constraints', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
const userVideoLiveoId = await createLiveWrapper(true)
|
const userVideoLiveoId = await createLiveWrapper(true)
|
||||||
await runAndTestFfmpegStreamError(servers[0].url, userAccessToken, userVideoLiveoId, true)
|
await servers[0].liveCommand.runAndTestFfmpegStreamError({ token: userAccessToken, videoId: userVideoLiveoId, shouldHaveError: true })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
await waitUntilLivePublishedOnAllServers(userVideoLiveoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
|
@ -6,22 +6,15 @@ import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
ConfigCommand,
|
ConfigCommand,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getLive,
|
|
||||||
getPlaylistsCount,
|
|
||||||
getVideo,
|
getVideo,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
stopFfmpeg,
|
stopFfmpeg,
|
||||||
updateLive,
|
|
||||||
wait,
|
wait,
|
||||||
waitJobs,
|
waitJobs
|
||||||
waitUntilLivePublished,
|
|
||||||
waitUntilLiveWaiting
|
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@ -39,8 +32,8 @@ describe('Permanent live', function () {
|
||||||
permanentLive
|
permanentLive
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
|
const { uuid } = await servers[0].liveCommand.createLive({ fields: attributes })
|
||||||
return res.body.video.uuid
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkVideoState (videoId: string, state: VideoState) {
|
async function checkVideoState (videoId: string, state: VideoState) {
|
||||||
|
@ -83,15 +76,15 @@ describe('Permanent live', function () {
|
||||||
const videoUUID = await createLiveWrapper(false)
|
const videoUUID = await createLiveWrapper(false)
|
||||||
|
|
||||||
{
|
{
|
||||||
const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
|
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
|
||||||
expect(res.body.permanentLive).to.be.false
|
expect(live.permanentLive).to.be.false
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateLive(servers[0].url, servers[0].accessToken, videoUUID, { permanentLive: true })
|
await servers[0].liveCommand.updateLive({ videoId: videoUUID, fields: { permanentLive: true } })
|
||||||
|
|
||||||
{
|
{
|
||||||
const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
|
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
|
||||||
expect(res.body.permanentLive).to.be.true
|
expect(live.permanentLive).to.be.true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -100,8 +93,8 @@ describe('Permanent live', function () {
|
||||||
|
|
||||||
videoUUID = await createLiveWrapper(true)
|
videoUUID = await createLiveWrapper(true)
|
||||||
|
|
||||||
const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
|
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
|
||||||
expect(res.body.permanentLive).to.be.true
|
expect(live.permanentLive).to.be.true
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
@ -109,16 +102,16 @@ describe('Permanent live', function () {
|
||||||
it('Should stream into this permanent live', async function () {
|
it('Should stream into this permanent live', async function () {
|
||||||
this.timeout(120000)
|
this.timeout(120000)
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID)
|
const ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: videoUUID })
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
|
await server.liveCommand.waitUntilLivePublished({ videoId: videoUUID })
|
||||||
}
|
}
|
||||||
|
|
||||||
await checkVideoState(videoUUID, VideoState.PUBLISHED)
|
await checkVideoState(videoUUID, VideoState.PUBLISHED)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
await waitUntilLiveWaiting(servers[0].url, servers[0].accessToken, videoUUID)
|
await servers[0].liveCommand.waitUntilLiveWaiting({ videoId: videoUUID })
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
@ -160,19 +153,19 @@ describe('Permanent live', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, videoUUID)
|
const ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: videoUUID })
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
|
await server.liveCommand.waitUntilLivePublished({ videoId: videoUUID })
|
||||||
}
|
}
|
||||||
|
|
||||||
await checkVideoState(videoUUID, VideoState.PUBLISHED)
|
await checkVideoState(videoUUID, VideoState.PUBLISHED)
|
||||||
|
|
||||||
const count = await getPlaylistsCount(servers[0], videoUUID)
|
const count = await servers[0].liveCommand.getPlaylistsCount({ videoUUID })
|
||||||
// master playlist and 720p playlist
|
// master playlist and 720p playlist
|
||||||
expect(count).to.equal(2)
|
expect(count).to.equal(2)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -10,13 +10,11 @@ import {
|
||||||
checkLiveCleanup,
|
checkLiveCleanup,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
ConfigCommand,
|
ConfigCommand,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getVideo,
|
getVideo,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
removeVideo,
|
removeVideo,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
|
@ -24,10 +22,7 @@ import {
|
||||||
testFfmpegStreamError,
|
testFfmpegStreamError,
|
||||||
updateVideo,
|
updateVideo,
|
||||||
wait,
|
wait,
|
||||||
waitJobs,
|
waitJobs
|
||||||
waitUntilLiveEnded,
|
|
||||||
waitUntilLivePublished,
|
|
||||||
waitUntilLiveSaved
|
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
@ -52,8 +47,8 @@ describe('Save replay setting', function () {
|
||||||
saveReplay
|
saveReplay
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
|
const { uuid } = await servers[0].liveCommand.createLive({ fields: attributes })
|
||||||
return res.body.video.uuid
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) {
|
async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) {
|
||||||
|
@ -79,13 +74,13 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
async function waitUntilLivePublishedOnAllServers (videoId: string) {
|
async function waitUntilLivePublishedOnAllServers (videoId: string) {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, videoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitUntilLiveSavedOnAllServers (videoId: string) {
|
async function waitUntilLiveSavedOnAllServers (videoId: string) {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLiveSaved(server.url, server.accessToken, videoId)
|
await server.liveCommand.waitUntilLiveSaved({ videoId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +131,7 @@ describe('Save replay setting', function () {
|
||||||
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
|
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
|
||||||
this.timeout(30000)
|
this.timeout(30000)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
|
@ -152,7 +147,7 @@ describe('Save replay setting', function () {
|
||||||
await stopFfmpeg(ffmpegCommand)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
|
await server.liveCommand.waitUntilLiveEnded({ videoId: liveVideoUUID })
|
||||||
}
|
}
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
@ -169,7 +164,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
liveVideoUUID = await createLiveWrapper(false)
|
liveVideoUUID = await createLiveWrapper(false)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
|
@ -198,7 +193,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
liveVideoUUID = await createLiveWrapper(false)
|
liveVideoUUID = await createLiveWrapper(false)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
|
@ -234,7 +229,7 @@ describe('Save replay setting', function () {
|
||||||
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
|
it('Should correctly have updated the live and federated it when streaming in the live', async function () {
|
||||||
this.timeout(20000)
|
this.timeout(20000)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -278,7 +273,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
liveVideoUUID = await createLiveWrapper(true)
|
liveVideoUUID = await createLiveWrapper(true)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -306,7 +301,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
liveVideoUUID = await createLiveWrapper(true)
|
liveVideoUUID = await createLiveWrapper(true)
|
||||||
|
|
||||||
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
|
@ -5,11 +5,9 @@ import * as chai from 'chai'
|
||||||
import { VideoPrivacy, VideoState } from '@shared/models'
|
import { VideoPrivacy, VideoState } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getVideoIdFromUUID,
|
getVideoIdFromUUID,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
|
@ -17,7 +15,6 @@ import {
|
||||||
viewVideo,
|
viewVideo,
|
||||||
wait,
|
wait,
|
||||||
waitJobs,
|
waitJobs,
|
||||||
waitUntilLiveEnded,
|
|
||||||
waitUntilLivePublishedOnAllServers
|
waitUntilLivePublishedOnAllServers
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
|
@ -60,8 +57,8 @@ describe('Test live', function () {
|
||||||
privacy: VideoPrivacy.PUBLIC
|
privacy: VideoPrivacy.PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
|
const { uuid } = await servers[0].liveCommand.createLive({ fields: liveAttributes })
|
||||||
return res.body.video.uuid
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Should correctly send a message when the live starts and ends', async function () {
|
it('Should correctly send a message when the live starts and ends', async function () {
|
||||||
|
@ -89,7 +86,7 @@ describe('Test live', function () {
|
||||||
remoteSocket.emit('subscribe', { videoId })
|
remoteSocket.emit('subscribe', { videoId })
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
const ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -99,10 +96,10 @@ describe('Test live', function () {
|
||||||
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
|
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
|
||||||
}
|
}
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
|
await server.liveCommand.waitUntilLiveEnded({ videoId: liveVideoUUID })
|
||||||
}
|
}
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
@ -137,7 +134,7 @@ describe('Test live', function () {
|
||||||
remoteSocket.emit('subscribe', { videoId })
|
remoteSocket.emit('subscribe', { videoId })
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
const ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
@ -155,7 +152,7 @@ describe('Test live', function () {
|
||||||
expect(localLastVideoViews).to.equal(2)
|
expect(localLastVideoViews).to.equal(2)
|
||||||
expect(remoteLastVideoViews).to.equal(2)
|
expect(remoteLastVideoViews).to.equal(2)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not receive a notification after unsubscribe', async function () {
|
it('Should not receive a notification after unsubscribe', async function () {
|
||||||
|
@ -172,7 +169,7 @@ describe('Test live', function () {
|
||||||
socket.on('state-change', data => stateChanges.push(data.state))
|
socket.on('state-change', data => stateChanges.push(data.state))
|
||||||
socket.emit('subscribe', { videoId })
|
socket.emit('subscribe', { videoId })
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
const command = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
|
||||||
|
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoUUID)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
|
@ -6,11 +6,9 @@ import { FfmpegCommand } from 'fluent-ffmpeg'
|
||||||
import { VideoDetails, VideoPrivacy } from '@shared/models'
|
import { VideoDetails, VideoPrivacy } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getVideo,
|
getVideo,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
|
@ -73,10 +71,10 @@ describe('Test live', function () {
|
||||||
privacy: VideoPrivacy.PUBLIC
|
privacy: VideoPrivacy.PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
|
const live = await servers[0].liveCommand.createLive({ fields: liveAttributes })
|
||||||
liveVideoId = res.body.video.uuid
|
liveVideoId = live.uuid
|
||||||
|
|
||||||
command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
|
command = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId })
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
|
|
@ -13,41 +13,36 @@ import {
|
||||||
checkLiveSegmentHash,
|
checkLiveSegmentHash,
|
||||||
checkResolutionsInMasterPlaylist,
|
checkResolutionsInMasterPlaylist,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getLive,
|
|
||||||
getMyVideosWithFilter,
|
getMyVideosWithFilter,
|
||||||
getPlaylist,
|
getPlaylist,
|
||||||
getVideo,
|
getVideo,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
getVideosWithFilters,
|
getVideosWithFilters,
|
||||||
killallServers,
|
killallServers,
|
||||||
|
LiveCommand,
|
||||||
makeRawRequest,
|
makeRawRequest,
|
||||||
removeVideo,
|
removeVideo,
|
||||||
reRunServer,
|
reRunServer,
|
||||||
sendRTMPStream,
|
sendRTMPStream,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
stopFfmpeg,
|
stopFfmpeg,
|
||||||
testFfmpegStreamError,
|
testFfmpegStreamError,
|
||||||
testImage,
|
testImage,
|
||||||
updateLive,
|
|
||||||
uploadVideoAndGetId,
|
uploadVideoAndGetId,
|
||||||
wait,
|
wait,
|
||||||
waitJobs,
|
waitJobs,
|
||||||
waitUntilLiveEnded,
|
waitUntilLivePublishedOnAllServers
|
||||||
waitUntilLivePublished,
|
|
||||||
waitUntilLivePublishedOnAllServers,
|
|
||||||
waitUntilLiveSegmentGeneration
|
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
describe('Test live', function () {
|
describe('Test live', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
|
let commands: LiveCommand[]
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(120000)
|
this.timeout(120000)
|
||||||
|
@ -72,6 +67,8 @@ describe('Test live', function () {
|
||||||
|
|
||||||
// Server 1 and server 2 follow each other
|
// Server 1 and server 2 follow each other
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
|
||||||
|
commands = servers.map(s => s.liveCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Live creation, update and delete', function () {
|
describe('Live creation, update and delete', function () {
|
||||||
|
@ -99,8 +96,8 @@ describe('Test live', function () {
|
||||||
thumbnailfile: 'video_short1.webm.jpg'
|
thumbnailfile: 'video_short1.webm.jpg'
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
|
const live = await commands[0].createLive({ fields: attributes })
|
||||||
liveVideoUUID = res.body.video.uuid
|
liveVideoUUID = live.uuid
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
@ -130,8 +127,7 @@ describe('Test live', function () {
|
||||||
await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
|
await testImage(server.url, 'video_short1-preview.webm', video.previewPath)
|
||||||
await testImage(server.url, 'video_short1.webm', video.thumbnailPath)
|
await testImage(server.url, 'video_short1.webm', video.thumbnailPath)
|
||||||
|
|
||||||
const resLive = await getLive(server.url, server.accessToken, liveVideoUUID)
|
const live = await server.liveCommand.getLive({ videoId: liveVideoUUID })
|
||||||
const live: LiveVideo = resLive.body
|
|
||||||
|
|
||||||
if (server.url === servers[0].url) {
|
if (server.url === servers[0].url) {
|
||||||
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
|
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
|
||||||
|
@ -155,8 +151,8 @@ describe('Test live', function () {
|
||||||
nsfw: true
|
nsfw: true
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
|
const live = await commands[0].createLive({ fields: attributes })
|
||||||
const videoId = res.body.video.uuid
|
const videoId = live.uuid
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
@ -182,20 +178,19 @@ describe('Test live', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to update a live of another server', async function () {
|
it('Should not be able to update a live of another server', async function () {
|
||||||
await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
|
await commands[1].updateLive({ videoId: liveVideoUUID, fields: { saveReplay: false }, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should update the live', async function () {
|
it('Should update the live', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
await updateLive(servers[0].url, servers[0].accessToken, liveVideoUUID, { saveReplay: false })
|
await commands[0].updateLive({ videoId: liveVideoUUID, fields: { saveReplay: false } })
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Have the live updated', async function () {
|
it('Have the live updated', async function () {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
const res = await getLive(server.url, server.accessToken, liveVideoUUID)
|
const live = await server.liveCommand.getLive({ videoId: liveVideoUUID })
|
||||||
const live: LiveVideo = res.body
|
|
||||||
|
|
||||||
if (server.url === servers[0].url) {
|
if (server.url === servers[0].url) {
|
||||||
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
|
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
|
||||||
|
@ -219,13 +214,13 @@ describe('Test live', function () {
|
||||||
it('Should have the live deleted', async function () {
|
it('Should have the live deleted', async function () {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
await server.liveCommand.getLive({ videoId: liveVideoUUID, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Live filters', function () {
|
describe('Live filters', function () {
|
||||||
let command: any
|
let ffmpegCommand: any
|
||||||
let liveVideoId: string
|
let liveVideoId: string
|
||||||
let vodVideoId: string
|
let vodVideoId: string
|
||||||
|
|
||||||
|
@ -235,10 +230,10 @@ describe('Test live', function () {
|
||||||
vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid
|
vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid
|
||||||
|
|
||||||
const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id }
|
const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id }
|
||||||
const resLive = await createLive(servers[0].url, servers[0].accessToken, liveOptions)
|
const live = await commands[0].createLive({ fields: liveOptions })
|
||||||
liveVideoId = resLive.body.video.uuid
|
liveVideoId = live.uuid
|
||||||
|
|
||||||
command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
|
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId })
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
@ -262,7 +257,7 @@ describe('Test live', function () {
|
||||||
it('Should display my lives', async function () {
|
it('Should display my lives', async function () {
|
||||||
this.timeout(60000)
|
this.timeout(60000)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true })
|
const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true })
|
||||||
|
@ -302,13 +297,12 @@ describe('Test live', function () {
|
||||||
saveReplay: false
|
saveReplay: false
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
|
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
|
||||||
const uuid = res.body.video.uuid
|
|
||||||
|
|
||||||
const resLive = await getLive(servers[0].url, servers[0].accessToken, uuid)
|
const live = await commands[0].getLive({ videoId: uuid })
|
||||||
const resVideo = await getVideo(servers[0].url, uuid)
|
const resVideo = await getVideo(servers[0].url, uuid)
|
||||||
|
|
||||||
return Object.assign(resVideo.body, resLive.body) as LiveVideo & VideoDetails
|
return Object.assign(resVideo.body as VideoDetails, live)
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Should not allow a stream without the appropriate path', async function () {
|
it('Should not allow a stream without the appropriate path', async function () {
|
||||||
|
@ -382,8 +376,8 @@ describe('Test live', function () {
|
||||||
saveReplay
|
saveReplay
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
|
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
|
||||||
return res.body.video.uuid
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testVideoResolutions (liveVideoId: string, resolutions: number[]) {
|
async function testVideoResolutions (liveVideoId: string, resolutions: number[]) {
|
||||||
|
@ -409,7 +403,7 @@ describe('Test live', function () {
|
||||||
for (let i = 0; i < resolutions.length; i++) {
|
for (let i = 0; i < resolutions.length; i++) {
|
||||||
const segmentNum = 3
|
const segmentNum = 3
|
||||||
const segmentName = `${i}-00000${segmentNum}.ts`
|
const segmentName = `${i}-00000${segmentNum}.ts`
|
||||||
await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum)
|
await commands[0].waitUntilLiveSegmentGeneration({ videoUUID: video.uuid, resolution: i, segment: segmentNum })
|
||||||
|
|
||||||
const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`)
|
const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`)
|
||||||
const subPlaylist = res.text
|
const subPlaylist = res.text
|
||||||
|
@ -454,13 +448,13 @@ describe('Test live', function () {
|
||||||
|
|
||||||
liveVideoId = await createLiveWrapper(false)
|
liveVideoId = await createLiveWrapper(false)
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
|
const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await testVideoResolutions(liveVideoId, [ 720 ])
|
await testVideoResolutions(liveVideoId, [ 720 ])
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should enable transcoding with some resolutions', async function () {
|
it('Should enable transcoding with some resolutions', async function () {
|
||||||
|
@ -470,13 +464,13 @@ describe('Test live', function () {
|
||||||
await updateConf(resolutions)
|
await updateConf(resolutions)
|
||||||
liveVideoId = await createLiveWrapper(false)
|
liveVideoId = await createLiveWrapper(false)
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
|
const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId })
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await testVideoResolutions(liveVideoId, resolutions)
|
await testVideoResolutions(liveVideoId, resolutions)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should enable transcoding with some resolutions and correctly save them', async function () {
|
it('Should enable transcoding with some resolutions and correctly save them', async function () {
|
||||||
|
@ -487,14 +481,14 @@ describe('Test live', function () {
|
||||||
await updateConf(resolutions)
|
await updateConf(resolutions)
|
||||||
liveVideoId = await createLiveWrapper(true)
|
liveVideoId = await createLiveWrapper(true)
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm')
|
const ffmpegCommand = await commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
await waitUntilLivePublishedOnAllServers(servers, liveVideoId)
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await testVideoResolutions(liveVideoId, resolutions)
|
await testVideoResolutions(liveVideoId, resolutions)
|
||||||
|
|
||||||
await stopFfmpeg(command)
|
await stopFfmpeg(ffmpegCommand)
|
||||||
await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
|
await commands[0].waitUntilLiveEnded({ videoId: liveVideoId })
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
@ -565,8 +559,8 @@ describe('Test live', function () {
|
||||||
saveReplay
|
saveReplay
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
|
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
|
||||||
return res.body.video.uuid
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -576,17 +570,17 @@ describe('Test live', function () {
|
||||||
liveVideoReplayId = await createLiveWrapper(true)
|
liveVideoReplayId = await createLiveWrapper(true)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId),
|
commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }),
|
||||||
sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoReplayId)
|
commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId })
|
||||||
])
|
])
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId),
|
commands[0].waitUntilLivePublished({ videoId: liveVideoId }),
|
||||||
waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
|
commands[0].waitUntilLivePublished({ videoId: liveVideoReplayId })
|
||||||
])
|
])
|
||||||
|
|
||||||
await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2)
|
await commands[0].waitUntilLiveSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 })
|
||||||
await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2)
|
await commands[0].waitUntilLiveSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 })
|
||||||
|
|
||||||
await killallServers([ servers[0] ])
|
await killallServers([ servers[0] ])
|
||||||
await reRunServer(servers[0])
|
await reRunServer(servers[0])
|
||||||
|
@ -597,13 +591,13 @@ describe('Test live', function () {
|
||||||
it('Should cleanup lives', async function () {
|
it('Should cleanup lives', async function () {
|
||||||
this.timeout(60000)
|
this.timeout(60000)
|
||||||
|
|
||||||
await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
|
await commands[0].waitUntilLiveEnded({ videoId: liveVideoId })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should save a live replay', async function () {
|
it('Should save a live replay', async function () {
|
||||||
this.timeout(120000)
|
this.timeout(120000)
|
||||||
|
|
||||||
await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
|
await commands[0].waitUntilLivePublished({ videoId: liveVideoReplayId })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,20 @@
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import * as chai from 'chai'
|
import * as chai from 'chai'
|
||||||
import { VideoPrivacy } from '@shared/models'
|
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
createVideoCaption,
|
||||||
flushAndRunServer,
|
flushAndRunServer,
|
||||||
immutableAssign,
|
immutableAssign,
|
||||||
SearchCommand,
|
SearchCommand,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
stopFfmpeg,
|
stopFfmpeg,
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
wait,
|
wait
|
||||||
waitUntilLivePublished
|
} from '@shared/extra-utils'
|
||||||
} from '../../../../shared/extra-utils'
|
import { VideoPrivacy } from '@shared/models'
|
||||||
import { createVideoCaption } from '../../../../shared/extra-utils/videos/video-captions'
|
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -502,12 +499,13 @@ describe('Test videos search', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.videoChannel.id }
|
const liveCommand = server.liveCommand
|
||||||
const resLive = await createLive(server.url, server.accessToken, liveOptions)
|
|
||||||
const liveVideoId = resLive.body.video.uuid
|
|
||||||
|
|
||||||
const ffmpegCommand = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId)
|
const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.videoChannel.id }
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
|
const live = await liveCommand.createLive({ fields: liveAttributes })
|
||||||
|
|
||||||
|
const ffmpegCommand = await liveCommand.sendRTMPStreamInVideo({ videoId: live.id })
|
||||||
|
await liveCommand.waitUntilLivePublished({ videoId: live.id })
|
||||||
|
|
||||||
const body = await command.advancedVideoSearch({ search: { isLive: true } })
|
const body = await command.advancedVideoSearch({ search: { isLive: true } })
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
acceptChangeOwnership,
|
acceptChangeOwnership,
|
||||||
changeVideoOwnership,
|
changeVideoOwnership,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
createUser,
|
createUser,
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
|
@ -112,9 +111,9 @@ describe('Test video change ownership - nominal', function () {
|
||||||
|
|
||||||
{
|
{
|
||||||
const attributes = { name: 'live', channelId: firstUserChannelId, privacy: VideoPrivacy.PUBLIC }
|
const attributes = { name: 'live', channelId: firstUserChannelId, privacy: VideoPrivacy.PUBLIC }
|
||||||
const res = await createLive(servers[0].url, firstUserAccessToken, attributes)
|
const video = await servers[0].liveCommand.createLive({ token: firstUserAccessToken, fields: attributes })
|
||||||
|
|
||||||
liveId = res.body.video.id
|
liveId = video.id
|
||||||
}
|
}
|
||||||
|
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
addVideoCommentThread,
|
addVideoCommentThread,
|
||||||
addVideoInPlaylist,
|
addVideoInPlaylist,
|
||||||
blockUser,
|
blockUser,
|
||||||
createLive,
|
|
||||||
createUser,
|
createUser,
|
||||||
createVideoPlaylist,
|
createVideoPlaylist,
|
||||||
deleteVideoComment,
|
deleteVideoComment,
|
||||||
|
@ -96,7 +95,7 @@ describe('Test plugin action hooks', function () {
|
||||||
channelId: servers[0].videoChannel.id
|
channelId: servers[0].videoChannel.id
|
||||||
}
|
}
|
||||||
|
|
||||||
await createLive(servers[0].url, servers[0].accessToken, attributes)
|
await servers[0].liveCommand.createLive({ fields: attributes })
|
||||||
|
|
||||||
await checkHook('action:api.live-video.created')
|
await checkHook('action:api.live-video.created')
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
addVideoCommentReply,
|
addVideoCommentReply,
|
||||||
addVideoCommentThread,
|
addVideoCommentThread,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
createVideoPlaylist,
|
createVideoPlaylist,
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
|
@ -156,7 +155,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
channelId: servers[0].videoChannel.id
|
channelId: servers[0].videoChannel.id
|
||||||
}
|
}
|
||||||
|
|
||||||
await createLive(servers[0].url, servers[0].accessToken, attributes, HttpStatusCode.FORBIDDEN_403)
|
await servers[0].liveCommand.createLive({ fields: attributes, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
|
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
|
||||||
|
|
|
@ -7,18 +7,15 @@ import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server
|
||||||
import {
|
import {
|
||||||
buildServerDirectory,
|
buildServerDirectory,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createLive,
|
|
||||||
flushAndRunServer,
|
flushAndRunServer,
|
||||||
getVideo,
|
getVideo,
|
||||||
PluginsCommand,
|
PluginsCommand,
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
setDefaultVideoChannel,
|
setDefaultVideoChannel,
|
||||||
testFfmpegStreamError,
|
testFfmpegStreamError,
|
||||||
uploadVideoAndGetId,
|
uploadVideoAndGetId,
|
||||||
waitJobs,
|
waitJobs
|
||||||
waitUntilLivePublished
|
|
||||||
} from '@shared/extra-utils'
|
} from '@shared/extra-utils'
|
||||||
import { VideoDetails, VideoPrivacy } from '@shared/models'
|
import { VideoDetails, VideoPrivacy } from '@shared/models'
|
||||||
|
|
||||||
|
@ -29,8 +26,9 @@ async function createLiveWrapper (server: ServerInfo) {
|
||||||
privacy: VideoPrivacy.PUBLIC
|
privacy: VideoPrivacy.PUBLIC
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createLive(server.url, server.accessToken, liveAttributes)
|
const { uuid } = await server.liveCommand.createLive({ fields: liveAttributes })
|
||||||
return res.body.video.uuid
|
|
||||||
|
return uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
|
function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
|
||||||
|
@ -171,8 +169,8 @@ describe('Test transcoding plugins', function () {
|
||||||
|
|
||||||
const liveVideoId = await createLiveWrapper(server)
|
const liveVideoId = await createLiveWrapper(server)
|
||||||
|
|
||||||
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
|
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
|
||||||
await waitJobs([ server ])
|
await waitJobs([ server ])
|
||||||
|
|
||||||
await checkLiveFPS(liveVideoId, 'above', 20)
|
await checkLiveFPS(liveVideoId, 'above', 20)
|
||||||
|
@ -185,8 +183,8 @@ describe('Test transcoding plugins', function () {
|
||||||
|
|
||||||
const liveVideoId = await createLiveWrapper(server)
|
const liveVideoId = await createLiveWrapper(server)
|
||||||
|
|
||||||
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
|
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
|
||||||
await waitJobs([ server ])
|
await waitJobs([ server ])
|
||||||
|
|
||||||
await checkLiveFPS(liveVideoId, 'below', 12)
|
await checkLiveFPS(liveVideoId, 'below', 12)
|
||||||
|
@ -199,8 +197,8 @@ describe('Test transcoding plugins', function () {
|
||||||
|
|
||||||
const liveVideoId = await createLiveWrapper(server)
|
const liveVideoId = await createLiveWrapper(server)
|
||||||
|
|
||||||
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
|
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
|
||||||
await waitJobs([ server ])
|
await waitJobs([ server ])
|
||||||
|
|
||||||
await checkLiveFPS(liveVideoId, 'below', 6)
|
await checkLiveFPS(liveVideoId, 'below', 6)
|
||||||
|
@ -213,7 +211,7 @@ describe('Test transcoding plugins', function () {
|
||||||
|
|
||||||
const liveVideoId = await createLiveWrapper(server)
|
const liveVideoId = await createLiveWrapper(server)
|
||||||
|
|
||||||
const command = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
|
const command = await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await testFfmpegStreamError(command, true)
|
await testFfmpegStreamError(command, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -262,8 +260,8 @@ describe('Test transcoding plugins', function () {
|
||||||
|
|
||||||
const liveVideoId = await createLiveWrapper(server)
|
const liveVideoId = await createLiveWrapper(server)
|
||||||
|
|
||||||
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
|
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
|
||||||
await waitJobs([ server ])
|
await waitJobs([ server ])
|
||||||
|
|
||||||
const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
|
const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
|
||||||
|
|
|
@ -7,21 +7,9 @@ export * from './miscs'
|
||||||
export * from './mock-servers'
|
export * from './mock-servers'
|
||||||
export * from './moderation'
|
export * from './moderation'
|
||||||
export * from './overviews'
|
export * from './overviews'
|
||||||
|
export * from './requests'
|
||||||
export * from './search'
|
export * from './search'
|
||||||
export * from './server'
|
export * from './server'
|
||||||
export * from './socket'
|
export * from './socket'
|
||||||
export * from './users'
|
export * from './users'
|
||||||
|
export * from './videos'
|
||||||
export * from './requests/check-api-params'
|
|
||||||
export * from './requests/requests'
|
|
||||||
|
|
||||||
export * from './videos/live'
|
|
||||||
export * from './videos/services'
|
|
||||||
export * from './videos/video-blacklist'
|
|
||||||
export * from './videos/video-captions'
|
|
||||||
export * from './videos/video-change-ownership'
|
|
||||||
export * from './videos/video-channels'
|
|
||||||
export * from './videos/video-comments'
|
|
||||||
export * from './videos/video-playlists'
|
|
||||||
export * from './videos/video-streaming-playlists'
|
|
||||||
export * from './videos/videos'
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Don't include activitypub that import stuff from server
|
||||||
|
export * from './check-api-params'
|
||||||
|
export * from './requests'
|
|
@ -18,6 +18,7 @@ import { makeGetRequest } from '../requests/requests'
|
||||||
import { SearchCommand } from '../search'
|
import { SearchCommand } from '../search'
|
||||||
import { SocketIOCommand } from '../socket'
|
import { SocketIOCommand } from '../socket'
|
||||||
import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users'
|
import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users'
|
||||||
|
import { LiveCommand } from '../videos'
|
||||||
import { ConfigCommand } from './config-command'
|
import { ConfigCommand } from './config-command'
|
||||||
import { ContactFormCommand } from './contact-form-command'
|
import { ContactFormCommand } from './contact-form-command'
|
||||||
import { DebugCommand } from './debug-command'
|
import { DebugCommand } from './debug-command'
|
||||||
|
@ -99,6 +100,7 @@ interface ServerInfo {
|
||||||
accountsCommand?: AccountsCommand
|
accountsCommand?: AccountsCommand
|
||||||
blocklistCommand?: BlocklistCommand
|
blocklistCommand?: BlocklistCommand
|
||||||
subscriptionsCommand?: SubscriptionsCommand
|
subscriptionsCommand?: SubscriptionsCommand
|
||||||
|
liveCommand?: LiveCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
function parallelTests () {
|
function parallelTests () {
|
||||||
|
@ -324,6 +326,7 @@ async function runServer (server: ServerInfo, configOverrideArg?: any, args = []
|
||||||
server.accountsCommand = new AccountsCommand(server)
|
server.accountsCommand = new AccountsCommand(server)
|
||||||
server.blocklistCommand = new BlocklistCommand(server)
|
server.blocklistCommand = new BlocklistCommand(server)
|
||||||
server.subscriptionsCommand = new SubscriptionsCommand(server)
|
server.subscriptionsCommand = new SubscriptionsCommand(server)
|
||||||
|
server.liveCommand = new LiveCommand(server)
|
||||||
|
|
||||||
res(server)
|
res(server)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { HttpStatusCode } from '@shared/core-utils'
|
import { HttpStatusCode } from '@shared/core-utils'
|
||||||
import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, unwrapBody, unwrapText } from '../requests/requests'
|
import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequest, makeUploadRequest, unwrapBody, unwrapText } from '../requests/requests'
|
||||||
import { ServerInfo } from '../server/servers'
|
import { ServerInfo } from '../server/servers'
|
||||||
|
|
||||||
export interface OverrideCommandOptions {
|
export interface OverrideCommandOptions {
|
||||||
|
@ -86,6 +86,36 @@ abstract class AbstractCommand {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected postUploadRequest (options: CommonCommandOptions & {
|
||||||
|
fields?: { [ fieldName: string ]: any }
|
||||||
|
attaches?: any
|
||||||
|
}) {
|
||||||
|
const { fields, attaches } = options
|
||||||
|
|
||||||
|
return makeUploadRequest({
|
||||||
|
...this.buildCommonRequestOptions(options),
|
||||||
|
|
||||||
|
method: 'POST',
|
||||||
|
fields,
|
||||||
|
attaches
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
protected putUploadRequest (options: CommonCommandOptions & {
|
||||||
|
fields?: { [ fieldName: string ]: any }
|
||||||
|
attaches?: any
|
||||||
|
}) {
|
||||||
|
const { fields, attaches } = options
|
||||||
|
|
||||||
|
return makeUploadRequest({
|
||||||
|
...this.buildCommonRequestOptions(options),
|
||||||
|
|
||||||
|
method: 'PUT',
|
||||||
|
fields,
|
||||||
|
attaches
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private buildCommonRequestOptions (options: CommonCommandOptions) {
|
private buildCommonRequestOptions (options: CommonCommandOptions) {
|
||||||
const { token, expectedStatus, defaultExpectedStatus, path } = options
|
const { token, expectedStatus, defaultExpectedStatus, path } = options
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
export * from './accounts-command'
|
export * from './accounts-command'
|
||||||
export * from './accounts'
|
export * from './accounts'
|
||||||
export * from './blocklist-command'
|
export * from './blocklist-command'
|
||||||
|
|
||||||
export * from './login'
|
export * from './login'
|
||||||
export * from './user-notifications'
|
export * from './user-notifications'
|
||||||
export * from './subscriptions-command'
|
export * from './subscriptions-command'
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
export * from './live-command'
|
||||||
|
export * from './live'
|
||||||
|
export * from './services'
|
||||||
|
export * from './video-blacklist'
|
||||||
|
export * from './video-captions'
|
||||||
|
export * from './video-change-ownership'
|
||||||
|
export * from './video-channels'
|
||||||
|
export * from './video-comments'
|
||||||
|
export * from './video-history'
|
||||||
|
export * from './video-imports'
|
||||||
|
export * from './video-playlists'
|
||||||
|
export * from './video-streaming-playlists'
|
||||||
|
export * from './videos'
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||||
|
|
||||||
|
import { readdir } from 'fs-extra'
|
||||||
|
import { omit } from 'lodash'
|
||||||
|
import { join } from 'path'
|
||||||
|
import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
|
||||||
|
import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
|
||||||
|
import { buildServerDirectory, wait } from '../miscs/miscs'
|
||||||
|
import { unwrapBody } from '../requests'
|
||||||
|
import { waitUntilLog } from '../server/servers'
|
||||||
|
import { AbstractCommand, OverrideCommandOptions } from '../shared'
|
||||||
|
import { sendRTMPStream, testFfmpegStreamError } from './live'
|
||||||
|
import { getVideoWithToken } from './videos'
|
||||||
|
|
||||||
|
export class LiveCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
getLive (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
}) {
|
||||||
|
const path = '/api/v1/videos/live'
|
||||||
|
|
||||||
|
return this.getRequestBody<LiveVideo>({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path: path + '/' + options.videoId,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.OK_200
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLive (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
fields: LiveVideoUpdate
|
||||||
|
}) {
|
||||||
|
const { videoId, fields } = options
|
||||||
|
const path = '/api/v1/videos/live'
|
||||||
|
|
||||||
|
return this.putBodyRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path: path + '/' + videoId,
|
||||||
|
fields,
|
||||||
|
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async createLive (options: OverrideCommandOptions & {
|
||||||
|
fields: LiveVideoCreate
|
||||||
|
}) {
|
||||||
|
const { fields } = options
|
||||||
|
const path = '/api/v1/videos/live'
|
||||||
|
|
||||||
|
const attaches: any = {}
|
||||||
|
if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
|
||||||
|
if (fields.previewfile) attaches.previewfile = fields.previewfile
|
||||||
|
|
||||||
|
const body = await unwrapBody<{ video: VideoCreateResult }>(this.postUploadRequest({
|
||||||
|
...options,
|
||||||
|
|
||||||
|
path,
|
||||||
|
attaches,
|
||||||
|
fields: omit(fields, 'thumbnailfile', 'previewfile'),
|
||||||
|
defaultExpectedStatus: HttpStatusCode.OK_200
|
||||||
|
}))
|
||||||
|
|
||||||
|
return body.video
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
fixtureName?: string
|
||||||
|
}) {
|
||||||
|
const { videoId, fixtureName } = options
|
||||||
|
const videoLive = await this.getLive({ videoId })
|
||||||
|
|
||||||
|
return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, fixtureName)
|
||||||
|
}
|
||||||
|
|
||||||
|
async runAndTestFfmpegStreamError (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
shouldHaveError: boolean
|
||||||
|
}) {
|
||||||
|
const command = await this.sendRTMPStreamInVideo(options)
|
||||||
|
|
||||||
|
return testFfmpegStreamError(command, options.shouldHaveError)
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilLivePublished (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
}) {
|
||||||
|
const { videoId } = options
|
||||||
|
return this.waitUntilLiveState({ videoId, state: VideoState.PUBLISHED })
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilLiveWaiting (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
}) {
|
||||||
|
const { videoId } = options
|
||||||
|
return this.waitUntilLiveState({ videoId, state: VideoState.WAITING_FOR_LIVE })
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilLiveEnded (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
}) {
|
||||||
|
const { videoId } = options
|
||||||
|
return this.waitUntilLiveState({ videoId, state: VideoState.LIVE_ENDED })
|
||||||
|
}
|
||||||
|
|
||||||
|
waitUntilLiveSegmentGeneration (options: OverrideCommandOptions & {
|
||||||
|
videoUUID: string
|
||||||
|
resolution: number
|
||||||
|
segment: number
|
||||||
|
}) {
|
||||||
|
const { resolution, segment, videoUUID } = options
|
||||||
|
const segmentName = `${resolution}-00000${segment}.ts`
|
||||||
|
|
||||||
|
return waitUntilLog(this.server, `${videoUUID}/${segmentName}`, 2, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitUntilLiveSaved (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
}) {
|
||||||
|
let video: VideoDetails
|
||||||
|
|
||||||
|
do {
|
||||||
|
const res = await getVideoWithToken(this.server.url, options.token ?? this.server.accessToken, options.videoId)
|
||||||
|
video = res.body
|
||||||
|
|
||||||
|
await wait(500)
|
||||||
|
} while (video.isLive === true && video.state.id !== VideoState.PUBLISHED)
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPlaylistsCount (options: OverrideCommandOptions & {
|
||||||
|
videoUUID: string
|
||||||
|
}) {
|
||||||
|
const basePath = buildServerDirectory(this.server, 'streaming-playlists')
|
||||||
|
const hlsPath = join(basePath, 'hls', options.videoUUID)
|
||||||
|
|
||||||
|
const files = await readdir(hlsPath)
|
||||||
|
|
||||||
|
return files.filter(f => f.endsWith('.m3u8')).length
|
||||||
|
}
|
||||||
|
|
||||||
|
private async waitUntilLiveState (options: OverrideCommandOptions & {
|
||||||
|
videoId: number | string
|
||||||
|
state: VideoState
|
||||||
|
}) {
|
||||||
|
let video: VideoDetails
|
||||||
|
|
||||||
|
do {
|
||||||
|
const res = await getVideoWithToken(this.server.url, options.token ?? this.server.accessToken, options.videoId)
|
||||||
|
video = res.body
|
||||||
|
|
||||||
|
await wait(500)
|
||||||
|
} while (video.state.id !== options.state)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,69 +3,9 @@
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import * as ffmpeg from 'fluent-ffmpeg'
|
import * as ffmpeg from 'fluent-ffmpeg'
|
||||||
import { pathExists, readdir } from 'fs-extra'
|
import { pathExists, readdir } from 'fs-extra'
|
||||||
import { omit } from 'lodash'
|
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoDetails, VideoState } from '@shared/models'
|
|
||||||
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
|
||||||
import { buildAbsoluteFixturePath, buildServerDirectory, wait } from '../miscs/miscs'
|
import { buildAbsoluteFixturePath, buildServerDirectory, wait } from '../miscs/miscs'
|
||||||
import { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
|
import { ServerInfo } from '../server/servers'
|
||||||
import { ServerInfo, waitUntilLog } from '../server/servers'
|
|
||||||
import { getVideoWithToken } from './videos'
|
|
||||||
|
|
||||||
function getLive (url: string, token: string, videoId: number | string, statusCodeExpected = HttpStatusCode.OK_200) {
|
|
||||||
const path = '/api/v1/videos/live'
|
|
||||||
|
|
||||||
return makeGetRequest({
|
|
||||||
url,
|
|
||||||
token,
|
|
||||||
path: path + '/' + videoId,
|
|
||||||
statusCodeExpected
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateLive (
|
|
||||||
url: string,
|
|
||||||
token: string,
|
|
||||||
videoId: number | string,
|
|
||||||
fields: LiveVideoUpdate,
|
|
||||||
statusCodeExpected = HttpStatusCode.NO_CONTENT_204
|
|
||||||
) {
|
|
||||||
const path = '/api/v1/videos/live'
|
|
||||||
|
|
||||||
return makePutBodyRequest({
|
|
||||||
url,
|
|
||||||
token,
|
|
||||||
path: path + '/' + videoId,
|
|
||||||
fields,
|
|
||||||
statusCodeExpected
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLive (url: string, token: string, fields: LiveVideoCreate, statusCodeExpected = HttpStatusCode.OK_200) {
|
|
||||||
const path = '/api/v1/videos/live'
|
|
||||||
|
|
||||||
const attaches: any = {}
|
|
||||||
if (fields.thumbnailfile) attaches.thumbnailfile = fields.thumbnailfile
|
|
||||||
if (fields.previewfile) attaches.previewfile = fields.previewfile
|
|
||||||
|
|
||||||
const updatedFields = omit(fields, 'thumbnailfile', 'previewfile')
|
|
||||||
|
|
||||||
return makeUploadRequest({
|
|
||||||
url,
|
|
||||||
path,
|
|
||||||
token,
|
|
||||||
attaches,
|
|
||||||
fields: updatedFields,
|
|
||||||
statusCodeExpected
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function sendRTMPStreamInVideo (url: string, token: string, videoId: number | string, fixtureName?: string) {
|
|
||||||
const res = await getLive(url, token, videoId)
|
|
||||||
const videoLive = res.body as LiveVideo
|
|
||||||
|
|
||||||
return sendRTMPStream(videoLive.rtmpUrl, videoLive.streamKey, fixtureName)
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
|
function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
|
||||||
const fixture = buildAbsoluteFixturePath(fixtureName)
|
const fixture = buildAbsoluteFixturePath(fixtureName)
|
||||||
|
@ -109,12 +49,6 @@ function waitFfmpegUntilError (command: ffmpeg.FfmpegCommand, successAfterMS = 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runAndTestFfmpegStreamError (url: string, token: string, videoId: number | string, shouldHaveError: boolean) {
|
|
||||||
const command = await sendRTMPStreamInVideo(url, token, videoId)
|
|
||||||
|
|
||||||
return testFfmpegStreamError(command, shouldHaveError)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) {
|
async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) {
|
||||||
let error: Error
|
let error: Error
|
||||||
|
|
||||||
|
@ -136,48 +70,9 @@ async function stopFfmpeg (command: ffmpeg.FfmpegCommand) {
|
||||||
await wait(500)
|
await wait(500)
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitUntilLivePublished (url: string, token: string, videoId: number | string) {
|
|
||||||
return waitUntilLiveState(url, token, videoId, VideoState.PUBLISHED)
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitUntilLiveWaiting (url: string, token: string, videoId: number | string) {
|
|
||||||
return waitUntilLiveState(url, token, videoId, VideoState.WAITING_FOR_LIVE)
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitUntilLiveEnded (url: string, token: string, videoId: number | string) {
|
|
||||||
return waitUntilLiveState(url, token, videoId, VideoState.LIVE_ENDED)
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitUntilLiveSegmentGeneration (server: ServerInfo, videoUUID: string, resolutionNum: number, segmentNum: number) {
|
|
||||||
const segmentName = `${resolutionNum}-00000${segmentNum}.ts`
|
|
||||||
return waitUntilLog(server, `${videoUUID}/${segmentName}`, 2, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitUntilLiveState (url: string, token: string, videoId: number | string, state: VideoState) {
|
|
||||||
let video: VideoDetails
|
|
||||||
|
|
||||||
do {
|
|
||||||
const res = await getVideoWithToken(url, token, videoId)
|
|
||||||
video = res.body
|
|
||||||
|
|
||||||
await wait(500)
|
|
||||||
} while (video.state.id !== state)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitUntilLiveSaved (url: string, token: string, videoId: number | string) {
|
|
||||||
let video: VideoDetails
|
|
||||||
|
|
||||||
do {
|
|
||||||
const res = await getVideoWithToken(url, token, videoId)
|
|
||||||
video = res.body
|
|
||||||
|
|
||||||
await wait(500)
|
|
||||||
} while (video.isLive === true && video.state.id !== VideoState.PUBLISHED)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function waitUntilLivePublishedOnAllServers (servers: ServerInfo[], videoId: string) {
|
async function waitUntilLivePublishedOnAllServers (servers: ServerInfo[], videoId: string) {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await waitUntilLivePublished(server.url, server.accessToken, videoId)
|
await server.liveCommand.waitUntilLivePublished({ videoId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,33 +101,11 @@ async function checkLiveCleanup (server: ServerInfo, videoUUID: string, resoluti
|
||||||
expect(files).to.contain('segments-sha256.json')
|
expect(files).to.contain('segments-sha256.json')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPlaylistsCount (server: ServerInfo, videoUUID: string) {
|
|
||||||
const basePath = buildServerDirectory(server, 'streaming-playlists')
|
|
||||||
const hlsPath = join(basePath, 'hls', videoUUID)
|
|
||||||
|
|
||||||
const files = await readdir(hlsPath)
|
|
||||||
|
|
||||||
return files.filter(f => f.endsWith('.m3u8')).length
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getLive,
|
|
||||||
getPlaylistsCount,
|
|
||||||
waitUntilLiveSaved,
|
|
||||||
waitUntilLivePublished,
|
|
||||||
updateLive,
|
|
||||||
createLive,
|
|
||||||
runAndTestFfmpegStreamError,
|
|
||||||
checkLiveCleanup,
|
|
||||||
waitUntilLiveSegmentGeneration,
|
|
||||||
stopFfmpeg,
|
|
||||||
waitUntilLiveWaiting,
|
|
||||||
sendRTMPStreamInVideo,
|
|
||||||
waitUntilLiveEnded,
|
|
||||||
waitFfmpegUntilError,
|
|
||||||
waitUntilLivePublishedOnAllServers,
|
|
||||||
sendRTMPStream,
|
sendRTMPStream,
|
||||||
testFfmpegStreamError
|
waitFfmpegUntilError,
|
||||||
|
testFfmpegStreamError,
|
||||||
|
stopFfmpeg,
|
||||||
|
waitUntilLivePublishedOnAllServers,
|
||||||
|
checkLiveCleanup
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue