1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
import { wait } from '@shared/core-utils'
import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models'
import {
cleanupTests,
createSingleServer,
makeRawRequest,
PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel,
stopFfmpeg,
waitJobs
} from '@shared/server-commands'
describe('Fast restream in live', function () {
let server: PeerTubeServer
async function createLiveWrapper (options: { permanent: boolean, replay: boolean }) {
const attributes: LiveVideoCreate = {
channelId: server.store.channel.id,
privacy: VideoPrivacy.PUBLIC,
name: 'my super live',
saveReplay: options.replay,
replaySettings: options.replay ? { privacy: VideoPrivacy.PUBLIC } : undefined,
permanentLive: options.permanent
}
const { uuid } = await server.live.create({ fields: attributes })
return uuid
}
async function fastRestreamWrapper ({ replay }: { replay: boolean }) {
const liveVideoUUID = await createLiveWrapper({ permanent: true, replay })
await waitJobs([ server ])
const rtmpOptions = {
videoId: liveVideoUUID,
copyCodecs: true,
fixtureName: 'video_short.mp4'
}
// Streaming session #1
let ffmpegCommand = await server.live.sendRTMPStreamInVideo(rtmpOptions)
await server.live.waitUntilPublished({ videoId: liveVideoUUID })
const video = await server.videos.get({ id: liveVideoUUID })
const session1PlaylistId = video.streamingPlaylists[0].id
await stopFfmpeg(ffmpegCommand)
await server.live.waitUntilWaiting({ videoId: liveVideoUUID })
// Streaming session #2
ffmpegCommand = await server.live.sendRTMPStreamInVideo(rtmpOptions)
let hasNewPlaylist = false
do {
const video = await server.videos.get({ id: liveVideoUUID })
hasNewPlaylist = video.streamingPlaylists.length === 1 && video.streamingPlaylists[0].id !== session1PlaylistId
await wait(100)
} while (!hasNewPlaylist)
await server.live.waitUntilSegmentGeneration({
server,
videoUUID: liveVideoUUID,
segment: 1,
playlistNumber: 0,
objectStorage: false
})
return { ffmpegCommand, liveVideoUUID }
}
async function ensureLastLiveWorks (liveId: string) {
// Equivalent to PEERTUBE_TEST_CONSTANTS_VIDEO_LIVE_CLEANUP_DELAY
for (let i = 0; i < 100; i++) {
const video = await server.videos.get({ id: liveId })
expect(video.streamingPlaylists).to.have.lengthOf(1)
try {
await server.live.getSegmentFile({ videoUUID: liveId, segment: 0, playlistNumber: 0 })
await makeRawRequest({ url: video.streamingPlaylists[0].playlistUrl, expectedStatus: HttpStatusCode.OK_200 })
await makeRawRequest({ url: video.streamingPlaylists[0].segmentsSha256Url, expectedStatus: HttpStatusCode.OK_200 })
} catch (err) {
// FIXME: try to debug error in CI "Unexpected end of JSON input"
console.error(err)
throw err
}
await wait(100)
}
}
async function runTest (replay: boolean) {
const { ffmpegCommand, liveVideoUUID } = await fastRestreamWrapper({ replay })
// TODO: remove, we try to debug a test timeout failure here
console.log('Ensuring last live works')
await ensureLastLiveWorks(liveVideoUUID)
await stopFfmpeg(ffmpegCommand)
await server.live.waitUntilWaiting({ videoId: liveVideoUUID })
// Wait for replays
await waitJobs([ server ])
const { total, data: sessions } = await server.live.listSessions({ videoId: liveVideoUUID })
expect(total).to.equal(2)
expect(sessions).to.have.lengthOf(2)
for (const session of sessions) {
expect(session.error).to.be.null
if (replay) {
expect(session.replayVideo).to.exist
await server.videos.get({ id: session.replayVideo.uuid })
} else {
expect(session.replayVideo).to.not.exist
}
}
}
before(async function () {
this.timeout(120000)
const env = { PEERTUBE_TEST_CONSTANTS_VIDEO_LIVE_CLEANUP_DELAY: '10000' }
server = await createSingleServer(1, {}, { env })
// Get the access tokens
await setAccessTokensToServers([ server ])
await setDefaultVideoChannel([ server ])
await server.config.enableMinimumTranscoding(false, true)
await server.config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' })
})
it('Should correctly fast restream in a permanent live with and without save replay', async function () {
this.timeout(480000)
// A test can take a long time, so prefer to run them in parallel
await Promise.all([
runTest(true),
runTest(false)
])
})
after(async function () {
await cleanupTests([ server ])
})
})
|