import 'mocha'
import * as chai from 'chai'
import { FfmpegCommand } from 'fluent-ffmpeg'
+import { join } from 'path'
+import { ffprobePromise, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
import { getLiveNotificationSocket } from '@shared/extra-utils/socket/socket-io'
import { LiveVideo, LiveVideoCreate, Video, VideoDetails, VideoPrivacy, VideoState, VideoStreamingPlaylistType } from '@shared/models'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
import {
addVideoToBlacklist,
+ buildServerDirectory,
checkLiveCleanup,
checkLiveSegmentHash,
checkResolutionsInMasterPlaylist,
- checkSegmentHash,
cleanupTests,
createLive,
doubleFollow,
viewVideo,
wait,
waitJobs,
- waitUntilLiveStarts,
+ waitUntilLiveEnded,
+ waitUntilLivePublished,
+ waitUntilLiveSegmentGeneration,
waitUntilLog
} from '../../../../shared/extra-utils'
expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
expect(video.nsfw).to.be.true
- await makeRawRequest(server.url + video.thumbnailPath, 200)
- await makeRawRequest(server.url + video.previewPath, 200)
+ await makeRawRequest(server.url + video.thumbnailPath, HttpStatusCode.OK_200)
+ await makeRawRequest(server.url + video.previewPath, HttpStatusCode.OK_200)
}
})
})
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 }, 403)
+ await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
})
it('Should update the live', async function () {
it('Should have the live deleted', async function () {
for (const server of servers) {
- await getVideo(server.url, liveVideoUUID, 404)
- await getLive(server.url, server.accessToken, liveVideoUUID, 404)
+ await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
+ await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
}
})
})
await checkResolutionsInMasterPlaylist(hlsPlaylist.playlistUrl, resolutions)
for (let i = 0; i < resolutions.length; i++) {
- const segmentName = `${i}-000001.ts`
- await waitUntilLog(servers[0], `${video.uuid}/${segmentName}`, 1, false)
+ const segmentNum = 1
+ const segmentName = `${i}-00000${segmentNum}.ts`
+ await waitUntilLiveSegmentGeneration(servers[0], video.uuid, i, segmentNum)
const res = await getPlaylist(`${servers[0].url}/static/streaming-playlists/hls/${video.uuid}/${i}.m3u8`)
const subPlaylist = res.text
liveVideoId = await createLiveWrapper(false)
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, [ 720 ])
liveVideoId = await createLiveWrapper(false)
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
})
it('Should enable transcoding with some resolutions and correctly save them', async function () {
- this.timeout(60000)
+ this.timeout(120000)
const resolutions = [ 240, 360, 720 ]
+
await updateConf(resolutions)
liveVideoId = await createLiveWrapper(true)
- const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId)
+ const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId, 'video_short2.webm')
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId)
await waitJobs(servers)
await testVideoResolutions(liveVideoId, resolutions)
await stopFfmpeg(command)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId)
await waitJobs(servers)
+ const bitrateLimits = {
+ 720: 5000 * 1000, // 60FPS
+ 360: 1100 * 1000,
+ 240: 600 * 1000
+ }
+
for (const server of servers) {
const resVideo = await getVideo(server.url, liveVideoId)
const video: VideoDetails = resVideo.body
expect(video.files).to.have.lengthOf(0)
const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
+ await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
+ await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
expect(file).to.exist
- expect(file.fps).to.equal(25)
expect(file.size).to.be.greaterThan(1)
- await makeRawRequest(file.torrentUrl, 200)
- await makeRawRequest(file.fileUrl, 200)
+ if (resolution >= 720) {
+ expect(file.fps).to.be.approximately(60, 2)
+ } else {
+ expect(file.fps).to.be.approximately(30, 2)
+ }
+
+ const filename = `${video.uuid}-${resolution}-fragmented.mp4`
+ const segmentPath = buildServerDirectory(servers[0], join('streaming-playlists', 'hls', video.uuid, filename))
+
+ const probe = await ffprobePromise(segmentPath)
+ const videoStream = await getVideoStreamFromFile(segmentPath, probe)
+
+ expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height])
+
+ await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
+ await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
}
}
})
liveVideoId = res.body.video.uuid
command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoId)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId)
await waitJobs(servers)
})
}
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
+
+ for (const server of servers) {
+ await waitUntilLivePublished(server.url, server.accessToken, liveVideoUUID)
+ }
+
await waitJobs(servers)
for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
- expect(stateChanges).to.have.lengthOf(1)
- expect(stateChanges[0]).to.equal(VideoState.PUBLISHED)
+ expect(stateChanges).to.have.length.at.least(1)
+ expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.PUBLISHED)
}
await stopFfmpeg(command)
+
+ for (const server of servers) {
+ await waitUntilLiveEnded(server.url, server.accessToken, liveVideoUUID)
+ }
+
await waitJobs(servers)
for (const stateChanges of [ localStateChanges, remoteStateChanges ]) {
- expect(stateChanges).to.have.lengthOf(2)
- expect(stateChanges[1]).to.equal(VideoState.LIVE_ENDED)
+ expect(stateChanges).to.have.length.at.least(2)
+ expect(stateChanges[stateChanges.length - 1]).to.equal(VideoState.LIVE_ENDED)
}
})
socket.emit('subscribe', { videoId })
const command = await sendRTMPStreamInVideo(servers[0].url, servers[0].accessToken, liveVideoUUID)
- await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoUUID)
await waitJobs(servers)
expect(stateChanges).to.have.lengthOf(1)
}
before(async function () {
- this.timeout(60000)
+ this.timeout(120000)
liveVideoId = await createLiveWrapper(false)
liveVideoReplayId = await createLiveWrapper(true)
])
await Promise.all([
- waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoId),
- waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoReplayId)
+ waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoId),
+ waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
])
+ await waitUntilLiveSegmentGeneration(servers[0], liveVideoId, 0, 2)
+ await waitUntilLiveSegmentGeneration(servers[0], liveVideoReplayId, 0, 2)
+
await killallServers([ servers[0] ])
await reRunServer(servers[0])
it('Should cleanup lives', async function () {
this.timeout(60000)
- const res = await getVideo(servers[0].url, liveVideoId)
- const video: VideoDetails = res.body
-
- expect(video.state.id).to.equal(VideoState.LIVE_ENDED)
+ await waitUntilLiveEnded(servers[0].url, servers[0].accessToken, liveVideoId)
})
it('Should save a live replay', async function () {
- this.timeout(60000)
-
- await waitJobs(servers)
-
- const res = await getVideo(servers[0].url, liveVideoReplayId)
- const video: VideoDetails = res.body
+ this.timeout(120000)
- expect(video.state.id).to.equal(VideoState.PUBLISHED)
+ await waitUntilLivePublished(servers[0].url, servers[0].accessToken, liveVideoReplayId)
})
})