Introduce live command

pull/4271/head
Chocobozzz 2021-07-08 10:18:40 +02:00
parent 2c27e70471
commit 4f2199144e
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
20 changed files with 370 additions and 338 deletions

View File

@ -2,27 +2,24 @@
import 'mocha'
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 {
buildAbsoluteFixturePath,
cleanupTests,
createUser,
flushAndRunServer,
getLive,
getMyUserInformation,
immutableAssign,
LiveCommand,
makePostBodyRequest,
makeUploadRequest,
runAndTestFfmpegStreamError,
sendRTMPStream,
ServerInfo,
setAccessTokensToServers,
stopFfmpeg,
updateLive,
uploadVideoAndGetId,
userLogin,
waitUntilLivePublished
userLogin
} from '../../../../shared/extra-utils'
describe('Test video lives API validator', function () {
@ -32,6 +29,7 @@ describe('Test video lives API validator', function () {
let channelId: number
let video: VideoCreateResult
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
}
command = server.liveCommand
})
describe('When creating a live', function () {
@ -337,70 +337,72 @@ describe('Test video lives API validator', function () {
describe('When getting live information', 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 () {
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 () {
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 () {
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 () {
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 () {
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 () {
await getLive(server.url, server.accessToken, video.id)
await getLive(server.url, server.accessToken, video.shortUUID)
await command.getLive({ videoId: video.id })
await command.getLive({ videoId: video.uuid })
await command.getLive({ videoId: video.shortUUID })
})
})
describe('When updating live information', 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 () {
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 () {
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 () {
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 () {
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 () {
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 () {
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 () {
await updateLive(server.url, server.accessToken, video.id, { saveReplay: false })
await updateLive(server.url, server.accessToken, video.shortUUID, { saveReplay: false })
await command.updateLive({ videoId: video.id, fields: { 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 () {
@ -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 () {
this.timeout(40000)
const resLive = await getLive(server.url, server.accessToken, video.id)
const live: LiveVideo = resLive.body
const live = await command.getLive({ videoId: video.id })
const command = sendRTMPStream(live.rtmpUrl, live.streamKey)
const ffmpegCommand = sendRTMPStream(live.rtmpUrl, live.streamKey)
await waitUntilLivePublished(server.url, server.accessToken, video.id)
await updateLive(server.url, server.accessToken, video.id, {}, HttpStatusCode.BAD_REQUEST_400)
await command.waitUntilLivePublished({ videoId: video.id })
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 () {
this.timeout(40000)
const resLive = await getLive(server.url, server.accessToken, video.id)
const live: LiveVideo = resLive.body
const live = await command.getLive({ videoId: video.id })
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)
})
})

View File

@ -7,19 +7,16 @@ import {
checkLiveCleanup,
cleanupTests,
ConfigCommand,
createLive,
doubleFollow,
flushAndRunMultipleServers,
generateUser,
getVideo,
runAndTestFfmpegStreamError,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
updateUser,
wait,
waitJobs,
waitUntilLivePublished
waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
@ -38,8 +35,8 @@ describe('Test live constraints', function () {
saveReplay
}
const res = await createLive(servers[0].url, userAccessToken, liveAttributes)
return res.body.video.uuid as string
const { uuid } = await servers[0].liveCommand.createLive({ token: userAccessToken, fields: liveAttributes })
return uuid
}
async function checkSaveReplay (videoId: string, resolutions = [ 720 ]) {
@ -56,7 +53,7 @@ describe('Test live constraints', function () {
async function waitUntilLivePublishedOnAllServers (videoId: string) {
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)
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 () {
@ -118,7 +115,7 @@ describe('Test live constraints', function () {
await wait(5000)
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 waitJobs(servers)
@ -135,7 +132,7 @@ describe('Test live constraints', function () {
await updateQuota({ total: -1, daily: 1 })
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 waitJobs(servers)
@ -152,7 +149,7 @@ describe('Test live constraints', function () {
await updateQuota({ total: 10 * 1000 * 1000, daily: -1 })
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 () {
@ -173,7 +170,7 @@ describe('Test live constraints', function () {
})
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 waitJobs(servers)

View File

@ -6,22 +6,15 @@ import { LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState } from '@shared
import {
cleanupTests,
ConfigCommand,
createLive,
doubleFollow,
flushAndRunMultipleServers,
getLive,
getPlaylistsCount,
getVideo,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
updateLive,
wait,
waitJobs,
waitUntilLivePublished,
waitUntilLiveWaiting
waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
@ -39,8 +32,8 @@ describe('Permanent live', function () {
permanentLive
}
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
return res.body.video.uuid
const { uuid } = await servers[0].liveCommand.createLive({ fields: attributes })
return uuid
}
async function checkVideoState (videoId: string, state: VideoState) {
@ -83,15 +76,15 @@ describe('Permanent live', function () {
const videoUUID = await createLiveWrapper(false)
{
const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
expect(res.body.permanentLive).to.be.false
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
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)
expect(res.body.permanentLive).to.be.true
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
expect(live.permanentLive).to.be.true
}
})
@ -100,8 +93,8 @@ describe('Permanent live', function () {
videoUUID = await createLiveWrapper(true)
const res = await getLive(servers[0].url, servers[0].accessToken, videoUUID)
expect(res.body.permanentLive).to.be.true
const live = await servers[0].liveCommand.getLive({ videoId: videoUUID })
expect(live.permanentLive).to.be.true
await waitJobs(servers)
})
@ -109,16 +102,16 @@ describe('Permanent live', function () {
it('Should stream into this permanent live', async function () {
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) {
await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
await server.liveCommand.waitUntilLivePublished({ videoId: videoUUID })
}
await checkVideoState(videoUUID, VideoState.PUBLISHED)
await stopFfmpeg(command)
await waitUntilLiveWaiting(servers[0].url, servers[0].accessToken, videoUUID)
await stopFfmpeg(ffmpegCommand)
await servers[0].liveCommand.waitUntilLiveWaiting({ videoId: videoUUID })
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) {
await waitUntilLivePublished(server.url, server.accessToken, videoUUID)
await server.liveCommand.waitUntilLivePublished({ videoId: videoUUID })
}
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
expect(count).to.equal(2)
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
})
after(async function () {

View File

@ -10,13 +10,11 @@ import {
checkLiveCleanup,
cleanupTests,
ConfigCommand,
createLive,
doubleFollow,
flushAndRunMultipleServers,
getVideo,
getVideosList,
removeVideo,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
@ -24,10 +22,7 @@ import {
testFfmpegStreamError,
updateVideo,
wait,
waitJobs,
waitUntilLiveEnded,
waitUntilLivePublished,
waitUntilLiveSaved
waitJobs
} from '../../../../shared/extra-utils'
const expect = chai.expect
@ -52,8 +47,8 @@ describe('Save replay setting', function () {
saveReplay
}
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
return res.body.video.uuid
const { uuid } = await servers[0].liveCommand.createLive({ fields: attributes })
return uuid
}
async function checkVideosExist (videoId: string, existsInList: boolean, getStatus?: number) {
@ -79,13 +74,13 @@ describe('Save replay setting', function () {
async function waitUntilLivePublishedOnAllServers (videoId: string) {
for (const server of servers) {
await waitUntilLivePublished(server.url, server.accessToken, videoId)
await server.liveCommand.waitUntilLivePublished({ videoId })
}
}
async function waitUntilLiveSavedOnAllServers (videoId: string) {
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 () {
this.timeout(30000)
ffmpegCommand = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
ffmpegCommand = await servers[0].liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoUUID })
await waitUntilLivePublishedOnAllServers(liveVideoUUID)
@ -152,7 +147,7 @@ describe('Save replay setting', function () {
await stopFfmpeg(ffmpegCommand)
for (const server of servers) {
await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
await server.liveCommand.waitUntilLiveEnded({ videoId: liveVideoUUID })
}
await waitJobs(servers)
@ -169,7 +164,7 @@ describe('Save replay setting', function () {
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)
@ -198,7 +193,7 @@ describe('Save replay setting', function () {
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)
@ -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 () {
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 waitJobs(servers)
@ -278,7 +273,7 @@ describe('Save replay setting', function () {
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 waitJobs(servers)
@ -306,7 +301,7 @@ describe('Save replay setting', function () {
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 waitJobs(servers)

View File

@ -5,11 +5,9 @@ import * as chai from 'chai'
import { VideoPrivacy, VideoState } from '@shared/models'
import {
cleanupTests,
createLive,
doubleFollow,
flushAndRunMultipleServers,
getVideoIdFromUUID,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
@ -17,7 +15,6 @@ import {
viewVideo,
wait,
waitJobs,
waitUntilLiveEnded,
waitUntilLivePublishedOnAllServers
} from '../../../../shared/extra-utils'
@ -60,8 +57,8 @@ describe('Test live', function () {
privacy: VideoPrivacy.PUBLIC
}
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
return res.body.video.uuid
const { uuid } = await servers[0].liveCommand.createLive({ fields: liveAttributes })
return uuid
}
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 })
}
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 waitJobs(servers)
@ -99,10 +96,10 @@ describe('Test live', function () {
expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
}
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
for (const server of servers) {
await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
await server.liveCommand.waitUntilLiveEnded({ videoId: liveVideoUUID })
}
await waitJobs(servers)
@ -137,7 +134,7 @@ describe('Test live', function () {
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 waitJobs(servers)
@ -155,7 +152,7 @@ describe('Test live', function () {
expect(localLastVideoViews).to.equal(2)
expect(remoteLastVideoViews).to.equal(2)
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
})
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.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 waitJobs(servers)

View File

@ -6,11 +6,9 @@ import { FfmpegCommand } from 'fluent-ffmpeg'
import { VideoDetails, VideoPrivacy } from '@shared/models'
import {
cleanupTests,
createLive,
doubleFollow,
flushAndRunMultipleServers,
getVideo,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
@ -73,10 +71,10 @@ describe('Test live', function () {
privacy: VideoPrivacy.PUBLIC
}
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
liveVideoId = res.body.video.uuid
const live = await servers[0].liveCommand.createLive({ fields: liveAttributes })
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 waitJobs(servers)
})

View File

@ -13,41 +13,36 @@ import {
checkLiveSegmentHash,
checkResolutionsInMasterPlaylist,
cleanupTests,
createLive,
doubleFollow,
flushAndRunMultipleServers,
getLive,
getMyVideosWithFilter,
getPlaylist,
getVideo,
getVideosList,
getVideosWithFilters,
killallServers,
LiveCommand,
makeRawRequest,
removeVideo,
reRunServer,
sendRTMPStream,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
testFfmpegStreamError,
testImage,
updateLive,
uploadVideoAndGetId,
wait,
waitJobs,
waitUntilLiveEnded,
waitUntilLivePublished,
waitUntilLivePublishedOnAllServers,
waitUntilLiveSegmentGeneration
waitUntilLivePublishedOnAllServers
} from '../../../../shared/extra-utils'
const expect = chai.expect
describe('Test live', function () {
let servers: ServerInfo[] = []
let commands: LiveCommand[]
before(async function () {
this.timeout(120000)
@ -72,6 +67,8 @@ describe('Test live', function () {
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
commands = servers.map(s => s.liveCommand)
})
describe('Live creation, update and delete', function () {
@ -99,8 +96,8 @@ describe('Test live', function () {
thumbnailfile: 'video_short1.webm.jpg'
}
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
liveVideoUUID = res.body.video.uuid
const live = await commands[0].createLive({ fields: attributes })
liveVideoUUID = live.uuid
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.webm', video.thumbnailPath)
const resLive = await getLive(server.url, server.accessToken, liveVideoUUID)
const live: LiveVideo = resLive.body
const live = await server.liveCommand.getLive({ videoId: liveVideoUUID })
if (server.url === servers[0].url) {
expect(live.rtmpUrl).to.equal('rtmp://' + server.hostname + ':' + servers[0].rtmpPort + '/live')
@ -155,8 +151,8 @@ describe('Test live', function () {
nsfw: true
}
const res = await createLive(servers[0].url, servers[0].accessToken, attributes)
const videoId = res.body.video.uuid
const live = await commands[0].createLive({ fields: attributes })
const videoId = live.uuid
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 () {
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 () {
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)
})
it('Have the live updated', async function () {
for (const server of servers) {
const res = await getLive(server.url, server.accessToken, liveVideoUUID)
const live: LiveVideo = res.body
const live = await server.liveCommand.getLive({ videoId: liveVideoUUID })
if (server.url === servers[0].url) {
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 () {
for (const server of servers) {
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 () {
let command: any
let ffmpegCommand: any
let liveVideoId: string
let vodVideoId: string
@ -235,10 +230,10 @@ describe('Test live', function () {
vodVideoId = (await uploadVideoAndGetId({ server: servers[0], videoName: 'vod video' })).uuid
const liveOptions = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: servers[0].videoChannel.id }
const resLive = await createLive(servers[0].url, servers[0].accessToken, liveOptions)
liveVideoId = resLive.body.video.uuid
const live = await commands[0].createLive({ fields: liveOptions })
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 waitJobs(servers)
})
@ -262,7 +257,7 @@ describe('Test live', function () {
it('Should display my lives', async function () {
this.timeout(60000)
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
await waitJobs(servers)
const res = await getMyVideosWithFilter(servers[0].url, servers[0].accessToken, { isLive: true })
@ -302,13 +297,12 @@ describe('Test live', function () {
saveReplay: false
}
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
const uuid = res.body.video.uuid
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
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)
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 () {
@ -382,8 +376,8 @@ describe('Test live', function () {
saveReplay
}
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
return res.body.video.uuid
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
return uuid
}
async function testVideoResolutions (liveVideoId: string, resolutions: number[]) {
@ -409,7 +403,7 @@ describe('Test live', function () {
for (let i = 0; i < resolutions.length; i++) {
const segmentNum = 3
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 subPlaylist = res.text
@ -454,13 +448,13 @@ describe('Test live', function () {
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 waitJobs(servers)
await testVideoResolutions(liveVideoId, [ 720 ])
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
})
it('Should enable transcoding with some resolutions', async function () {
@ -470,13 +464,13 @@ describe('Test live', function () {
await updateConf(resolutions)
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 waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
await stopFfmpeg(command)
await stopFfmpeg(ffmpegCommand)
})
it('Should enable transcoding with some resolutions and correctly save them', async function () {
@ -487,14 +481,14 @@ describe('Test live', function () {
await updateConf(resolutions)
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 waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
await stopFfmpeg(command)
await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
await stopFfmpeg(ffmpegCommand)
await commands[0].waitUntilLiveEnded({ videoId: liveVideoId })
await waitJobs(servers)
@ -565,8 +559,8 @@ describe('Test live', function () {
saveReplay
}
const res = await createLive(servers[0].url, servers[0].accessToken, liveAttributes)
return res.body.video.uuid
const { uuid } = await commands[0].createLive({ fields: liveAttributes })
return uuid
}
before(async function () {
@ -576,17 +570,17 @@ describe('Test live', function () {
liveVideoReplayId = await createLiveWrapper(true)
await Promise.all([
sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId),
sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoReplayId)
commands[0].sendRTMPStreamInVideo({ videoId: liveVideoId }),
commands[0].sendRTMPStreamInVideo({ videoId: liveVideoReplayId })
])
await Promise.all([
waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId),
waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
commands[0].waitUntilLivePublished({ videoId: liveVideoId }),
commands[0].waitUntilLivePublished({ videoId: liveVideoReplayId })
])
await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2)
await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2)
await commands[0].waitUntilLiveSegmentGeneration({ videoUUID: liveVideoId, resolution: 0, segment: 2 })
await commands[0].waitUntilLiveSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 })
await killallServers([ servers[0] ])
await reRunServer(servers[0])
@ -597,13 +591,13 @@ describe('Test live', function () {
it('Should cleanup lives', async function () {
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 () {
this.timeout(120000)
await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
await commands[0].waitUntilLivePublished({ videoId: liveVideoReplayId })
})
})

View File

@ -2,23 +2,20 @@
import 'mocha'
import * as chai from 'chai'
import { VideoPrivacy } from '@shared/models'
import {
cleanupTests,
createLive,
createVideoCaption,
flushAndRunServer,
immutableAssign,
SearchCommand,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
uploadVideo,
wait,
waitUntilLivePublished
} from '../../../../shared/extra-utils'
import { createVideoCaption } from '../../../../shared/extra-utils/videos/video-captions'
wait
} from '@shared/extra-utils'
import { VideoPrivacy } from '@shared/models'
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 resLive = await createLive(server.url, server.accessToken, liveOptions)
const liveVideoId = resLive.body.video.uuid
const liveCommand = server.liveCommand
const ffmpegCommand = await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId)
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
const liveAttributes = { name: 'live', privacy: VideoPrivacy.PUBLIC, channelId: server.videoChannel.id }
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 } })

View File

@ -7,7 +7,6 @@ import {
acceptChangeOwnership,
changeVideoOwnership,
cleanupTests,
createLive,
createUser,
doubleFollow,
flushAndRunMultipleServers,
@ -112,9 +111,9 @@ describe('Test video change ownership - nominal', function () {
{
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])

View File

@ -7,7 +7,6 @@ import {
addVideoCommentThread,
addVideoInPlaylist,
blockUser,
createLive,
createUser,
createVideoPlaylist,
deleteVideoComment,
@ -96,7 +95,7 @@ describe('Test plugin action hooks', function () {
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')
})

View File

@ -7,7 +7,6 @@ import {
addVideoCommentReply,
addVideoCommentThread,
cleanupTests,
createLive,
createVideoPlaylist,
doubleFollow,
flushAndRunMultipleServers,
@ -156,7 +155,7 @@ describe('Test plugin filter hooks', function () {
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 () {

View File

@ -7,18 +7,15 @@ import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server
import {
buildServerDirectory,
cleanupTests,
createLive,
flushAndRunServer,
getVideo,
PluginsCommand,
sendRTMPStreamInVideo,
ServerInfo,
setAccessTokensToServers,
setDefaultVideoChannel,
testFfmpegStreamError,
uploadVideoAndGetId,
waitJobs,
waitUntilLivePublished
waitJobs
} from '@shared/extra-utils'
import { VideoDetails, VideoPrivacy } from '@shared/models'
@ -29,8 +26,9 @@ async function createLiveWrapper (server: ServerInfo) {
privacy: VideoPrivacy.PUBLIC
}
const res = await createLive(server.url, server.accessToken, liveAttributes)
return res.body.video.uuid
const { uuid } = await server.liveCommand.createLive({ fields: liveAttributes })
return uuid
}
function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
@ -171,8 +169,8 @@ describe('Test transcoding plugins', function () {
const liveVideoId = await createLiveWrapper(server)
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
await waitJobs([ server ])
await checkLiveFPS(liveVideoId, 'above', 20)
@ -185,8 +183,8 @@ describe('Test transcoding plugins', function () {
const liveVideoId = await createLiveWrapper(server)
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
await waitJobs([ server ])
await checkLiveFPS(liveVideoId, 'below', 12)
@ -199,8 +197,8 @@ describe('Test transcoding plugins', function () {
const liveVideoId = await createLiveWrapper(server)
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
await waitJobs([ server ])
await checkLiveFPS(liveVideoId, 'below', 6)
@ -213,7 +211,7 @@ describe('Test transcoding plugins', function () {
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)
})
@ -262,8 +260,8 @@ describe('Test transcoding plugins', function () {
const liveVideoId = await createLiveWrapper(server)
await sendRTMPStreamInVideo(server.url, server.accessToken, liveVideoId, 'video_short2.webm')
await waitUntilLivePublished(server.url, server.accessToken, liveVideoId)
await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
await server.liveCommand.waitUntilLivePublished({ videoId: liveVideoId })
await waitJobs([ server ])
const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`

View File

@ -7,21 +7,9 @@ export * from './miscs'
export * from './mock-servers'
export * from './moderation'
export * from './overviews'
export * from './requests'
export * from './search'
export * from './server'
export * from './socket'
export * from './users'
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'
export * from './videos'

View File

@ -0,0 +1,3 @@
// Don't include activitypub that import stuff from server
export * from './check-api-params'
export * from './requests'

View File

@ -18,6 +18,7 @@ import { makeGetRequest } from '../requests/requests'
import { SearchCommand } from '../search'
import { SocketIOCommand } from '../socket'
import { AccountsCommand, BlocklistCommand, SubscriptionsCommand } from '../users'
import { LiveCommand } from '../videos'
import { ConfigCommand } from './config-command'
import { ContactFormCommand } from './contact-form-command'
import { DebugCommand } from './debug-command'
@ -99,6 +100,7 @@ interface ServerInfo {
accountsCommand?: AccountsCommand
blocklistCommand?: BlocklistCommand
subscriptionsCommand?: SubscriptionsCommand
liveCommand?: LiveCommand
}
function parallelTests () {
@ -324,6 +326,7 @@ async function runServer (server: ServerInfo, configOverrideArg?: any, args = []
server.accountsCommand = new AccountsCommand(server)
server.blocklistCommand = new BlocklistCommand(server)
server.subscriptionsCommand = new SubscriptionsCommand(server)
server.liveCommand = new LiveCommand(server)
res(server)
})

View File

@ -1,5 +1,5 @@
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'
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) {
const { token, expectedStatus, defaultExpectedStatus, path } = options

View File

@ -1,7 +1,6 @@
export * from './accounts-command'
export * from './accounts'
export * from './blocklist-command'
export * from './login'
export * from './user-notifications'
export * from './subscriptions-command'

View File

@ -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'

View File

@ -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)
}
}

View File

@ -3,69 +3,9 @@
import { expect } from 'chai'
import * as ffmpeg from 'fluent-ffmpeg'
import { pathExists, readdir } from 'fs-extra'
import { omit } from 'lodash'
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 { makeGetRequest, makePutBodyRequest, makeUploadRequest } from '../requests/requests'
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)
}
import { ServerInfo } from '../server/servers'
function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
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) {
let error: Error
@ -136,48 +70,9 @@ async function stopFfmpeg (command: ffmpeg.FfmpegCommand) {
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) {
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')
}
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 {
getLive,
getPlaylistsCount,
waitUntilLiveSaved,
waitUntilLivePublished,
updateLive,
createLive,
runAndTestFfmpegStreamError,
checkLiveCleanup,
waitUntilLiveSegmentGeneration,
stopFfmpeg,
waitUntilLiveWaiting,
sendRTMPStreamInVideo,
waitUntilLiveEnded,
waitFfmpegUntilError,
waitUntilLivePublishedOnAllServers,
sendRTMPStream,
testFfmpegStreamError
waitFfmpegUntilError,
testFfmpegStreamError,
stopFfmpeg,
waitUntilLivePublishedOnAllServers,
checkLiveCleanup
}