]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/tests/api/object-storage/live.ts
7e16b4c890483bde7560bf37f35d39b5a45a358e
[github/Chocobozzz/PeerTube.git] / server / tests / api / object-storage / live.ts
1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3 import { expect } from 'chai'
4 import { expectStartWith, testVideoResolutions } from '@server/tests/shared'
5 import { areObjectStorageTestsDisabled } from '@shared/core-utils'
6 import { HttpStatusCode, LiveVideoCreate, VideoPrivacy } from '@shared/models'
7 import {
8 createMultipleServers,
9 doubleFollow,
10 findExternalSavedVideo,
11 killallServers,
12 makeRawRequest,
13 ObjectStorageCommand,
14 PeerTubeServer,
15 setAccessTokensToServers,
16 setDefaultVideoChannel,
17 stopFfmpeg,
18 waitJobs,
19 waitUntilLivePublishedOnAllServers,
20 waitUntilLiveReplacedByReplayOnAllServers,
21 waitUntilLiveWaitingOnAllServers
22 } from '@shared/server-commands'
23
24 async function createLive (server: PeerTubeServer, permanent: boolean) {
25 const attributes: LiveVideoCreate = {
26 channelId: server.store.channel.id,
27 privacy: VideoPrivacy.PUBLIC,
28 name: 'my super live',
29 saveReplay: true,
30 permanentLive: permanent
31 }
32
33 const { uuid } = await server.live.create({ fields: attributes })
34
35 return uuid
36 }
37
38 async function checkFilesExist (servers: PeerTubeServer[], videoUUID: string, numberOfFiles: number) {
39 for (const server of servers) {
40 const video = await server.videos.get({ id: videoUUID })
41
42 expect(video.files).to.have.lengthOf(0)
43 expect(video.streamingPlaylists).to.have.lengthOf(1)
44
45 const files = video.streamingPlaylists[0].files
46 expect(files).to.have.lengthOf(numberOfFiles)
47
48 for (const file of files) {
49 expectStartWith(file.fileUrl, ObjectStorageCommand.getPlaylistBaseUrl())
50
51 await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
52 }
53 }
54 }
55
56 async function checkFilesCleanup (server: PeerTubeServer, videoUUID: string, resolutions: number[]) {
57 const resolutionFiles = resolutions.map((_value, i) => `${i}.m3u8`)
58
59 for (const playlistName of [ 'master.m3u8' ].concat(resolutionFiles)) {
60 await server.live.getPlaylistFile({
61 videoUUID,
62 playlistName,
63 expectedStatus: HttpStatusCode.NOT_FOUND_404,
64 objectStorage: true
65 })
66 }
67
68 await server.live.getSegmentFile({
69 videoUUID,
70 playlistNumber: 0,
71 segment: 0,
72 objectStorage: true,
73 expectedStatus: HttpStatusCode.NOT_FOUND_404
74 })
75 }
76
77 describe('Object storage for lives', function () {
78 if (areObjectStorageTestsDisabled()) return
79
80 let servers: PeerTubeServer[]
81
82 before(async function () {
83 this.timeout(120000)
84
85 await ObjectStorageCommand.prepareDefaultBuckets()
86
87 servers = await createMultipleServers(2, ObjectStorageCommand.getDefaultConfig())
88
89 await setAccessTokensToServers(servers)
90 await setDefaultVideoChannel(servers)
91 await doubleFollow(servers[0], servers[1])
92
93 await servers[0].config.enableTranscoding()
94 })
95
96 describe('Without live transcoding', async function () {
97 let videoUUID: string
98
99 before(async function () {
100 await servers[0].config.enableLive({ transcoding: false })
101
102 videoUUID = await createLive(servers[0], false)
103 })
104
105 it('Should create a live and publish it on object storage', async function () {
106 this.timeout(220000)
107
108 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUID })
109 await waitUntilLivePublishedOnAllServers(servers, videoUUID)
110
111 await testVideoResolutions({
112 originServer: servers[0],
113 servers,
114 liveVideoId: videoUUID,
115 resolutions: [ 720 ],
116 transcoded: false,
117 objectStorage: true
118 })
119
120 await stopFfmpeg(ffmpegCommand)
121 })
122
123 it('Should have saved the replay on object storage', async function () {
124 this.timeout(220000)
125
126 await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUID)
127 await waitJobs(servers)
128
129 await checkFilesExist(servers, videoUUID, 1)
130 })
131
132 it('Should have cleaned up live files from object storage', async function () {
133 await checkFilesCleanup(servers[0], videoUUID, [ 720 ])
134 })
135 })
136
137 describe('With live transcoding', async function () {
138 const resolutions = [ 720, 480, 360, 240, 144 ]
139
140 before(async function () {
141 await servers[0].config.enableLive({ transcoding: true })
142 })
143
144 describe('Normal replay', function () {
145 let videoUUIDNonPermanent: string
146
147 before(async function () {
148 videoUUIDNonPermanent = await createLive(servers[0], false)
149 })
150
151 it('Should create a live and publish it on object storage', async function () {
152 this.timeout(240000)
153
154 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDNonPermanent })
155 await waitUntilLivePublishedOnAllServers(servers, videoUUIDNonPermanent)
156
157 await testVideoResolutions({
158 originServer: servers[0],
159 servers,
160 liveVideoId: videoUUIDNonPermanent,
161 resolutions,
162 transcoded: true,
163 objectStorage: true
164 })
165
166 await stopFfmpeg(ffmpegCommand)
167 })
168
169 it('Should have saved the replay on object storage', async function () {
170 this.timeout(220000)
171
172 await waitUntilLiveReplacedByReplayOnAllServers(servers, videoUUIDNonPermanent)
173 await waitJobs(servers)
174
175 await checkFilesExist(servers, videoUUIDNonPermanent, 5)
176 })
177
178 it('Should have cleaned up live files from object storage', async function () {
179 await checkFilesCleanup(servers[0], videoUUIDNonPermanent, resolutions)
180 })
181 })
182
183 describe('Permanent replay', function () {
184 let videoUUIDPermanent: string
185
186 before(async function () {
187 videoUUIDPermanent = await createLive(servers[0], true)
188 })
189
190 it('Should create a live and publish it on object storage', async function () {
191 this.timeout(240000)
192
193 const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: videoUUIDPermanent })
194 await waitUntilLivePublishedOnAllServers(servers, videoUUIDPermanent)
195
196 await testVideoResolutions({
197 originServer: servers[0],
198 servers,
199 liveVideoId: videoUUIDPermanent,
200 resolutions,
201 transcoded: true,
202 objectStorage: true
203 })
204
205 await stopFfmpeg(ffmpegCommand)
206 })
207
208 it('Should have saved the replay on object storage', async function () {
209 this.timeout(220000)
210
211 await waitUntilLiveWaitingOnAllServers(servers, videoUUIDPermanent)
212 await waitJobs(servers)
213
214 const videoLiveDetails = await servers[0].videos.get({ id: videoUUIDPermanent })
215 const replay = await findExternalSavedVideo(servers[0], videoLiveDetails)
216
217 await checkFilesExist(servers, replay.uuid, 5)
218 })
219
220 it('Should have cleaned up live files from object storage', async function () {
221 await checkFilesCleanup(servers[0], videoUUIDPermanent, resolutions)
222 })
223 })
224 })
225
226 after(async function () {
227 await killallServers(servers)
228 })
229 })