]>
Commit | Line | Data |
---|---|---|
a1587156 | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
0c948c16 C |
2 | |
3 | import 'mocha' | |
4 | import * as chai from 'chai' | |
c55e3d72 | 5 | import { areObjectStorageTestsDisabled } from '@shared/core-utils' |
0305db28 | 6 | import { HttpStatusCode, VideoFile } from '@shared/models' |
0c948c16 | 7 | import { |
7c3b7976 | 8 | cleanupTests, |
254d3579 | 9 | createMultipleServers, |
4c7e60bc | 10 | doubleFollow, |
0305db28 JB |
11 | makeRawRequest, |
12 | ObjectStorageCommand, | |
254d3579 | 13 | PeerTubeServer, |
a1587156 | 14 | setAccessTokensToServers, |
d23dd9fb | 15 | waitJobs |
c55e3d72 | 16 | } from '@shared/server-commands' |
a2caee9f | 17 | import { checkResolutionsInMasterPlaylist, expectStartWith } from '../shared' |
3cd0734f C |
18 | |
19 | const expect = chai.expect | |
0c948c16 | 20 | |
0305db28 JB |
21 | async function checkFilesInObjectStorage (files: VideoFile[], type: 'webtorrent' | 'playlist') { |
22 | for (const file of files) { | |
23 | const shouldStartWith = type === 'webtorrent' | |
24 | ? ObjectStorageCommand.getWebTorrentBaseUrl() | |
25 | : ObjectStorageCommand.getPlaylistBaseUrl() | |
dee6fe1e | 26 | |
0305db28 JB |
27 | expectStartWith(file.fileUrl, shouldStartWith) |
28 | ||
29 | await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200) | |
dee6fe1e | 30 | } |
0305db28 JB |
31 | } |
32 | ||
33 | function runTests (objectStorage: boolean) { | |
34 | let servers: PeerTubeServer[] = [] | |
35 | const videosUUID: string[] = [] | |
9db2330e | 36 | const publishedAt: string[] = [] |
0c948c16 C |
37 | |
38 | before(async function () { | |
9db2330e | 39 | this.timeout(120000) |
0c948c16 | 40 | |
0305db28 JB |
41 | const config = objectStorage |
42 | ? ObjectStorageCommand.getDefaultConfig() | |
43 | : {} | |
44 | ||
0c948c16 | 45 | // Run server 2 to have transcoding enabled |
0305db28 | 46 | servers = await createMultipleServers(2, config) |
0c948c16 C |
47 | await setAccessTokensToServers(servers) |
48 | ||
0305db28 | 49 | await servers[0].config.disableTranscoding() |
dee6fe1e | 50 | |
0c948c16 C |
51 | await doubleFollow(servers[0], servers[1]) |
52 | ||
0305db28 JB |
53 | if (objectStorage) await ObjectStorageCommand.prepareDefaultBuckets() |
54 | ||
dee6fe1e | 55 | for (let i = 1; i <= 5; i++) { |
c186a67f C |
56 | const { uuid, shortUUID } = await servers[0].videos.upload({ attributes: { name: 'video' + i } }) |
57 | ||
9db2330e C |
58 | await waitJobs(servers) |
59 | ||
60 | const video = await servers[0].videos.get({ id: uuid }) | |
61 | publishedAt.push(video.publishedAt as string) | |
62 | ||
c186a67f C |
63 | if (i > 2) { |
64 | videosUUID.push(uuid) | |
65 | } else { | |
66 | videosUUID.push(shortUUID) | |
67 | } | |
dee6fe1e | 68 | } |
0c948c16 | 69 | |
3cd0734f | 70 | await waitJobs(servers) |
0c948c16 C |
71 | }) |
72 | ||
73 | it('Should have two video files on each server', async function () { | |
74 | this.timeout(30000) | |
75 | ||
76 | for (const server of servers) { | |
89d241a7 | 77 | const { data } = await server.videos.list() |
d23dd9fb | 78 | expect(data).to.have.lengthOf(videosUUID.length) |
0c948c16 | 79 | |
d23dd9fb | 80 | for (const video of data) { |
89d241a7 | 81 | const videoDetail = await server.videos.get({ id: video.uuid }) |
0c948c16 | 82 | expect(videoDetail.files).to.have.lengthOf(1) |
dee6fe1e | 83 | expect(videoDetail.streamingPlaylists).to.have.lengthOf(0) |
0c948c16 C |
84 | } |
85 | } | |
86 | }) | |
87 | ||
88 | it('Should run a transcoding job on video 2', async function () { | |
89 | this.timeout(60000) | |
90 | ||
89d241a7 | 91 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[1]}`) |
3cd0734f | 92 | await waitJobs(servers) |
0c948c16 C |
93 | |
94 | for (const server of servers) { | |
89d241a7 | 95 | const { data } = await server.videos.list() |
0c948c16 | 96 | |
a1587156 | 97 | let infoHashes: { [id: number]: string } |
04bf312c | 98 | |
d23dd9fb | 99 | for (const video of data) { |
0305db28 | 100 | const videoDetails = await server.videos.get({ id: video.uuid }) |
0c948c16 | 101 | |
c186a67f | 102 | if (video.shortUUID === videosUUID[1] || video.uuid === videosUUID[1]) { |
0305db28 JB |
103 | expect(videoDetails.files).to.have.lengthOf(4) |
104 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) | |
105 | ||
106 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
04bf312c C |
107 | |
108 | if (!infoHashes) { | |
109 | infoHashes = {} | |
110 | ||
0305db28 | 111 | for (const file of videoDetails.files) { |
04bf312c C |
112 | infoHashes[file.resolution.id.toString()] = file.magnetUri |
113 | } | |
114 | } else { | |
115 | for (const resolution of Object.keys(infoHashes)) { | |
0305db28 | 116 | const file = videoDetails.files.find(f => f.resolution.id.toString() === resolution) |
04bf312c C |
117 | expect(file.magnetUri).to.equal(infoHashes[resolution]) |
118 | } | |
119 | } | |
0c948c16 | 120 | } else { |
0305db28 JB |
121 | expect(videoDetails.files).to.have.lengthOf(1) |
122 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) | |
0c948c16 C |
123 | } |
124 | } | |
125 | } | |
126 | }) | |
127 | ||
05623b90 F |
128 | it('Should run a transcoding job on video 1 with resolution', async function () { |
129 | this.timeout(60000) | |
130 | ||
89d241a7 | 131 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[0]} -r 480`) |
05623b90 F |
132 | |
133 | await waitJobs(servers) | |
134 | ||
135 | for (const server of servers) { | |
89d241a7 | 136 | const { data } = await server.videos.list() |
d23dd9fb | 137 | expect(data).to.have.lengthOf(videosUUID.length) |
05623b90 | 138 | |
89d241a7 | 139 | const videoDetails = await server.videos.get({ id: videosUUID[0] }) |
05623b90 | 140 | |
d23dd9fb C |
141 | expect(videoDetails.files).to.have.lengthOf(2) |
142 | expect(videoDetails.files[0].resolution.id).to.equal(720) | |
143 | expect(videoDetails.files[1].resolution.id).to.equal(480) | |
dee6fe1e | 144 | |
d23dd9fb | 145 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(0) |
0305db28 JB |
146 | |
147 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
dee6fe1e C |
148 | } |
149 | }) | |
150 | ||
151 | it('Should generate an HLS resolution', async function () { | |
152 | this.timeout(120000) | |
153 | ||
89d241a7 | 154 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`) |
dee6fe1e C |
155 | |
156 | await waitJobs(servers) | |
157 | ||
158 | for (const server of servers) { | |
89d241a7 | 159 | const videoDetails = await server.videos.get({ id: videosUUID[2] }) |
dee6fe1e | 160 | |
d23dd9fb | 161 | expect(videoDetails.files).to.have.lengthOf(1) |
0305db28 JB |
162 | if (objectStorage) await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') |
163 | ||
d23dd9fb | 164 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) |
dee6fe1e | 165 | |
a2caee9f C |
166 | const hlsPlaylist = videoDetails.streamingPlaylists[0] |
167 | ||
168 | const files = hlsPlaylist.files | |
dee6fe1e C |
169 | expect(files).to.have.lengthOf(1) |
170 | expect(files[0].resolution.id).to.equal(480) | |
0305db28 | 171 | |
a2caee9f C |
172 | if (objectStorage) { |
173 | await checkFilesInObjectStorage(files, 'playlist') | |
174 | ||
175 | const resolutions = files.map(f => f.resolution.id) | |
176 | await checkResolutionsInMasterPlaylist({ server, playlistUrl: hlsPlaylist.playlistUrl, resolutions }) | |
177 | } | |
dee6fe1e C |
178 | } |
179 | }) | |
180 | ||
181 | it('Should not duplicate an HLS resolution', async function () { | |
182 | this.timeout(120000) | |
183 | ||
89d241a7 | 184 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`) |
dee6fe1e C |
185 | |
186 | await waitJobs(servers) | |
187 | ||
188 | for (const server of servers) { | |
89d241a7 | 189 | const videoDetails = await server.videos.get({ id: videosUUID[2] }) |
dee6fe1e | 190 | |
d23dd9fb | 191 | const files = videoDetails.streamingPlaylists[0].files |
dee6fe1e C |
192 | expect(files).to.have.lengthOf(1) |
193 | expect(files[0].resolution.id).to.equal(480) | |
0305db28 JB |
194 | |
195 | if (objectStorage) await checkFilesInObjectStorage(files, 'playlist') | |
dee6fe1e C |
196 | } |
197 | }) | |
198 | ||
199 | it('Should generate all HLS resolutions', async function () { | |
200 | this.timeout(120000) | |
201 | ||
89d241a7 | 202 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[3]} --generate-hls`) |
dee6fe1e C |
203 | |
204 | await waitJobs(servers) | |
205 | ||
206 | for (const server of servers) { | |
89d241a7 | 207 | const videoDetails = await server.videos.get({ id: videosUUID[3] }) |
dee6fe1e | 208 | |
d23dd9fb C |
209 | expect(videoDetails.files).to.have.lengthOf(1) |
210 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) | |
dee6fe1e | 211 | |
d23dd9fb | 212 | const files = videoDetails.streamingPlaylists[0].files |
dee6fe1e | 213 | expect(files).to.have.lengthOf(4) |
0305db28 JB |
214 | |
215 | if (objectStorage) await checkFilesInObjectStorage(files, 'playlist') | |
dee6fe1e C |
216 | } |
217 | }) | |
218 | ||
219 | it('Should optimize the video file and generate HLS videos if enabled in config', async function () { | |
220 | this.timeout(120000) | |
221 | ||
0305db28 | 222 | await servers[0].config.enableTranscoding() |
89d241a7 | 223 | await servers[0].cli.execWithEnv(`npm run create-transcoding-job -- -v ${videosUUID[4]}`) |
dee6fe1e C |
224 | |
225 | await waitJobs(servers) | |
226 | ||
227 | for (const server of servers) { | |
89d241a7 | 228 | const videoDetails = await server.videos.get({ id: videosUUID[4] }) |
dee6fe1e | 229 | |
8dd754c7 | 230 | expect(videoDetails.files).to.have.lengthOf(5) |
d23dd9fb | 231 | expect(videoDetails.streamingPlaylists).to.have.lengthOf(1) |
8dd754c7 | 232 | expect(videoDetails.streamingPlaylists[0].files).to.have.lengthOf(5) |
0305db28 JB |
233 | |
234 | if (objectStorage) { | |
235 | await checkFilesInObjectStorage(videoDetails.files, 'webtorrent') | |
236 | await checkFilesInObjectStorage(videoDetails.streamingPlaylists[0].files, 'playlist') | |
237 | } | |
05623b90 F |
238 | } |
239 | }) | |
240 | ||
9db2330e C |
241 | it('Should not have updated published at attributes', async function () { |
242 | for (const id of videosUUID) { | |
243 | const video = await servers[0].videos.get({ id }) | |
244 | ||
245 | expect(publishedAt.some(p => video.publishedAt === p)).to.be.true | |
246 | } | |
247 | }) | |
248 | ||
7c3b7976 C |
249 | after(async function () { |
250 | await cleanupTests(servers) | |
0c948c16 | 251 | }) |
0305db28 JB |
252 | } |
253 | ||
254 | describe('Test create transcoding jobs', function () { | |
255 | ||
256 | describe('On filesystem', function () { | |
257 | runTests(false) | |
258 | }) | |
259 | ||
260 | describe('On object storage', function () { | |
261 | if (areObjectStorageTestsDisabled()) return | |
262 | ||
263 | runTests(true) | |
264 | }) | |
0c948c16 | 265 | }) |