aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/videos/video-transcoder.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/tests/api/videos/video-transcoder.ts')
-rw-r--r--server/tests/api/videos/video-transcoder.ts373
1 files changed, 184 insertions, 189 deletions
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index ea5ffd239..2a09e95bf 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -2,36 +2,23 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { FfprobeData } from 'fluent-ffmpeg'
6import { omit } from 'lodash' 5import { omit } from 'lodash'
7import { join } from 'path'
8import { Job } from '@shared/models'
9import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants'
10import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
11import { 6import {
12 buildAbsoluteFixturePath, 7 buildAbsoluteFixturePath,
13 buildServerDirectory,
14 cleanupTests, 8 cleanupTests,
9 createMultipleServers,
15 doubleFollow, 10 doubleFollow,
16 flushAndRunMultipleServers,
17 generateHighBitrateVideo, 11 generateHighBitrateVideo,
18 generateVideoWithFramerate, 12 generateVideoWithFramerate,
19 getJobsListPaginationAndSort, 13 getFileSize,
20 getMyVideos,
21 getServerFileSize,
22 getVideo,
23 getVideoFileMetadataUrl,
24 getVideosList,
25 makeGetRequest, 14 makeGetRequest,
26 ServerInfo, 15 PeerTubeServer,
27 setAccessTokensToServers, 16 setAccessTokensToServers,
28 updateCustomSubConfig,
29 uploadVideo,
30 uploadVideoAndGetId,
31 waitJobs, 17 waitJobs,
32 webtorrentAdd 18 webtorrentAdd
33} from '../../../../shared/extra-utils' 19} from '@shared/extra-utils'
34import { getMaxBitrate, VideoDetails, VideoResolution, VideoState } from '../../../../shared/models/videos' 20import { getMaxBitrate, HttpStatusCode, VideoResolution, VideoState } from '@shared/models'
21import { VIDEO_TRANSCODING_FPS } from '../../../../server/initializers/constants'
35import { 22import {
36 canDoQuickTranscode, 23 canDoQuickTranscode,
37 getAudioStream, 24 getAudioStream,
@@ -43,37 +30,39 @@ import {
43 30
44const expect = chai.expect 31const expect = chai.expect
45 32
46function updateConfigForTranscoding (server: ServerInfo) { 33function updateConfigForTranscoding (server: PeerTubeServer) {
47 return updateCustomSubConfig(server.url, server.accessToken, { 34 return server.config.updateCustomSubConfig({
48 transcoding: { 35 newConfig: {
49 enabled: true, 36 transcoding: {
50 allowAdditionalExtensions: true, 37 enabled: true,
51 allowAudioFiles: true, 38 allowAdditionalExtensions: true,
52 hls: { enabled: true }, 39 allowAudioFiles: true,
53 webtorrent: { enabled: true }, 40 hls: { enabled: true },
54 resolutions: { 41 webtorrent: { enabled: true },
55 '0p': false, 42 resolutions: {
56 '240p': true, 43 '0p': false,
57 '360p': true, 44 '240p': true,
58 '480p': true, 45 '360p': true,
59 '720p': true, 46 '480p': true,
60 '1080p': true, 47 '720p': true,
61 '1440p': true, 48 '1080p': true,
62 '2160p': true 49 '1440p': true,
50 '2160p': true
51 }
63 } 52 }
64 } 53 }
65 }) 54 })
66} 55}
67 56
68describe('Test video transcoding', function () { 57describe('Test video transcoding', function () {
69 let servers: ServerInfo[] = [] 58 let servers: PeerTubeServer[] = []
70 let video4k: string 59 let video4k: string
71 60
72 before(async function () { 61 before(async function () {
73 this.timeout(30_000) 62 this.timeout(30_000)
74 63
75 // Run servers 64 // Run servers
76 servers = await flushAndRunMultipleServers(2) 65 servers = await createMultipleServers(2)
77 66
78 await setAccessTokensToServers(servers) 67 await setAccessTokensToServers(servers)
79 68
@@ -87,21 +76,20 @@ describe('Test video transcoding', function () {
87 it('Should not transcode video on server 1', async function () { 76 it('Should not transcode video on server 1', async function () {
88 this.timeout(60_000) 77 this.timeout(60_000)
89 78
90 const videoAttributes = { 79 const attributes = {
91 name: 'my super name for server 1', 80 name: 'my super name for server 1',
92 description: 'my super description for server 1', 81 description: 'my super description for server 1',
93 fixture: 'video_short.webm' 82 fixture: 'video_short.webm'
94 } 83 }
95 await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes) 84 await servers[0].videos.upload({ attributes })
96 85
97 await waitJobs(servers) 86 await waitJobs(servers)
98 87
99 for (const server of servers) { 88 for (const server of servers) {
100 const res = await getVideosList(server.url) 89 const { data } = await server.videos.list()
101 const video = res.body.data[0] 90 const video = data[0]
102 91
103 const res2 = await getVideo(server.url, video.id) 92 const videoDetails = await server.videos.get({ id: video.id })
104 const videoDetails = res2.body
105 expect(videoDetails.files).to.have.lengthOf(1) 93 expect(videoDetails.files).to.have.lengthOf(1)
106 94
107 const magnetUri = videoDetails.files[0].magnetUri 95 const magnetUri = videoDetails.files[0].magnetUri
@@ -117,21 +105,20 @@ describe('Test video transcoding', function () {
117 it('Should transcode video on server 2', async function () { 105 it('Should transcode video on server 2', async function () {
118 this.timeout(120_000) 106 this.timeout(120_000)
119 107
120 const videoAttributes = { 108 const attributes = {
121 name: 'my super name for server 2', 109 name: 'my super name for server 2',
122 description: 'my super description for server 2', 110 description: 'my super description for server 2',
123 fixture: 'video_short.webm' 111 fixture: 'video_short.webm'
124 } 112 }
125 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 113 await servers[1].videos.upload({ attributes })
126 114
127 await waitJobs(servers) 115 await waitJobs(servers)
128 116
129 for (const server of servers) { 117 for (const server of servers) {
130 const res = await getVideosList(server.url) 118 const { data } = await server.videos.list()
131 119
132 const video = res.body.data.find(v => v.name === videoAttributes.name) 120 const video = data.find(v => v.name === attributes.name)
133 const res2 = await getVideo(server.url, video.id) 121 const videoDetails = await server.videos.get({ id: video.id })
134 const videoDetails = res2.body
135 122
136 expect(videoDetails.files).to.have.lengthOf(4) 123 expect(videoDetails.files).to.have.lengthOf(4)
137 124
@@ -150,47 +137,50 @@ describe('Test video transcoding', function () {
150 137
151 { 138 {
152 // Upload the video, but wait transcoding 139 // Upload the video, but wait transcoding
153 const videoAttributes = { 140 const attributes = {
154 name: 'waiting video', 141 name: 'waiting video',
155 fixture: 'video_short1.webm', 142 fixture: 'video_short1.webm',
156 waitTranscoding: true 143 waitTranscoding: true
157 } 144 }
158 const resVideo = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 145 const { uuid } = await servers[1].videos.upload({ attributes })
159 const videoId = resVideo.body.video.uuid 146 const videoId = uuid
160 147
161 // Should be in transcode state 148 // Should be in transcode state
162 const { body } = await getVideo(servers[1].url, videoId) 149 const body = await servers[1].videos.get({ id: videoId })
163 expect(body.name).to.equal('waiting video') 150 expect(body.name).to.equal('waiting video')
164 expect(body.state.id).to.equal(VideoState.TO_TRANSCODE) 151 expect(body.state.id).to.equal(VideoState.TO_TRANSCODE)
165 expect(body.state.label).to.equal('To transcode') 152 expect(body.state.label).to.equal('To transcode')
166 expect(body.waitTranscoding).to.be.true 153 expect(body.waitTranscoding).to.be.true
167 154
168 // Should have my video 155 {
169 const resMyVideos = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 10) 156 // Should have my video
170 const videoToFindInMine = resMyVideos.body.data.find(v => v.name === videoAttributes.name) 157 const { data } = await servers[1].videos.listMyVideos()
171 expect(videoToFindInMine).not.to.be.undefined 158 const videoToFindInMine = data.find(v => v.name === attributes.name)
172 expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE) 159 expect(videoToFindInMine).not.to.be.undefined
173 expect(videoToFindInMine.state.label).to.equal('To transcode') 160 expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE)
174 expect(videoToFindInMine.waitTranscoding).to.be.true 161 expect(videoToFindInMine.state.label).to.equal('To transcode')
162 expect(videoToFindInMine.waitTranscoding).to.be.true
163 }
175 164
176 // Should not list this video 165 {
177 const resVideos = await getVideosList(servers[1].url) 166 // Should not list this video
178 const videoToFindInList = resVideos.body.data.find(v => v.name === videoAttributes.name) 167 const { data } = await servers[1].videos.list()
179 expect(videoToFindInList).to.be.undefined 168 const videoToFindInList = data.find(v => v.name === attributes.name)
169 expect(videoToFindInList).to.be.undefined
170 }
180 171
181 // Server 1 should not have the video yet 172 // Server 1 should not have the video yet
182 await getVideo(servers[0].url, videoId, HttpStatusCode.NOT_FOUND_404) 173 await servers[0].videos.get({ id: videoId, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
183 } 174 }
184 175
185 await waitJobs(servers) 176 await waitJobs(servers)
186 177
187 for (const server of servers) { 178 for (const server of servers) {
188 const res = await getVideosList(server.url) 179 const { data } = await server.videos.list()
189 const videoToFind = res.body.data.find(v => v.name === 'waiting video') 180 const videoToFind = data.find(v => v.name === 'waiting video')
190 expect(videoToFind).not.to.be.undefined 181 expect(videoToFind).not.to.be.undefined
191 182
192 const res2 = await getVideo(server.url, videoToFind.id) 183 const videoDetails = await server.videos.get({ id: videoToFind.id })
193 const videoDetails: VideoDetails = res2.body
194 184
195 expect(videoDetails.state.id).to.equal(VideoState.PUBLISHED) 185 expect(videoDetails.state.id).to.equal(VideoState.PUBLISHED)
196 expect(videoDetails.state.label).to.equal('Published') 186 expect(videoDetails.state.label).to.equal('Published')
@@ -211,22 +201,20 @@ describe('Test video transcoding', function () {
211 } 201 }
212 202
213 for (const fixture of [ 'video_short.mkv', 'video_short.avi' ]) { 203 for (const fixture of [ 'video_short.mkv', 'video_short.avi' ]) {
214 const videoAttributes = { 204 const attributes = {
215 name: fixture, 205 name: fixture,
216 fixture 206 fixture
217 } 207 }
218 208
219 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 209 await servers[1].videos.upload({ attributes })
220 210
221 await waitJobs(servers) 211 await waitJobs(servers)
222 212
223 for (const server of servers) { 213 for (const server of servers) {
224 const res = await getVideosList(server.url) 214 const { data } = await server.videos.list()
225
226 const video = res.body.data.find(v => v.name === videoAttributes.name)
227 const res2 = await getVideo(server.url, video.id)
228 const videoDetails = res2.body
229 215
216 const video = data.find(v => v.name === attributes.name)
217 const videoDetails = await server.videos.get({ id: video.id })
230 expect(videoDetails.files).to.have.lengthOf(4) 218 expect(videoDetails.files).to.have.lengthOf(4)
231 219
232 const magnetUri = videoDetails.files[0].magnetUri 220 const magnetUri = videoDetails.files[0].magnetUri
@@ -238,22 +226,20 @@ describe('Test video transcoding', function () {
238 it('Should transcode a 4k video', async function () { 226 it('Should transcode a 4k video', async function () {
239 this.timeout(200_000) 227 this.timeout(200_000)
240 228
241 const videoAttributes = { 229 const attributes = {
242 name: '4k video', 230 name: '4k video',
243 fixture: 'video_short_4k.mp4' 231 fixture: 'video_short_4k.mp4'
244 } 232 }
245 233
246 const resUpload = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 234 const { uuid } = await servers[1].videos.upload({ attributes })
247 video4k = resUpload.body.video.uuid 235 video4k = uuid
248 236
249 await waitJobs(servers) 237 await waitJobs(servers)
250 238
251 const resolutions = [ 240, 360, 480, 720, 1080, 1440, 2160 ] 239 const resolutions = [ 240, 360, 480, 720, 1080, 1440, 2160 ]
252 240
253 for (const server of servers) { 241 for (const server of servers) {
254 const res = await getVideo(server.url, video4k) 242 const videoDetails = await server.videos.get({ id: video4k })
255 const videoDetails: VideoDetails = res.body
256
257 expect(videoDetails.files).to.have.lengthOf(resolutions.length) 243 expect(videoDetails.files).to.have.lengthOf(resolutions.length)
258 244
259 for (const r of resolutions) { 245 for (const r of resolutions) {
@@ -269,24 +255,24 @@ describe('Test video transcoding', function () {
269 it('Should transcode high bit rate mp3 to proper bit rate', async function () { 255 it('Should transcode high bit rate mp3 to proper bit rate', async function () {
270 this.timeout(60_000) 256 this.timeout(60_000)
271 257
272 const videoAttributes = { 258 const attributes = {
273 name: 'mp3_256k', 259 name: 'mp3_256k',
274 fixture: 'video_short_mp3_256k.mp4' 260 fixture: 'video_short_mp3_256k.mp4'
275 } 261 }
276 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 262 await servers[1].videos.upload({ attributes })
277 263
278 await waitJobs(servers) 264 await waitJobs(servers)
279 265
280 for (const server of servers) { 266 for (const server of servers) {
281 const res = await getVideosList(server.url) 267 const { data } = await server.videos.list()
282 268
283 const video = res.body.data.find(v => v.name === videoAttributes.name) 269 const video = data.find(v => v.name === attributes.name)
284 const res2 = await getVideo(server.url, video.id) 270 const videoDetails = await server.videos.get({ id: video.id })
285 const videoDetails: VideoDetails = res2.body
286 271
287 expect(videoDetails.files).to.have.lengthOf(4) 272 expect(videoDetails.files).to.have.lengthOf(4)
288 273
289 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4')) 274 const file = videoDetails.files.find(f => f.resolution.id === 240)
275 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
290 const probe = await getAudioStream(path) 276 const probe = await getAudioStream(path)
291 277
292 if (probe.audioStream) { 278 if (probe.audioStream) {
@@ -301,23 +287,23 @@ describe('Test video transcoding', function () {
301 it('Should transcode video with no audio and have no audio itself', async function () { 287 it('Should transcode video with no audio and have no audio itself', async function () {
302 this.timeout(60_000) 288 this.timeout(60_000)
303 289
304 const videoAttributes = { 290 const attributes = {
305 name: 'no_audio', 291 name: 'no_audio',
306 fixture: 'video_short_no_audio.mp4' 292 fixture: 'video_short_no_audio.mp4'
307 } 293 }
308 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 294 await servers[1].videos.upload({ attributes })
309 295
310 await waitJobs(servers) 296 await waitJobs(servers)
311 297
312 for (const server of servers) { 298 for (const server of servers) {
313 const res = await getVideosList(server.url) 299 const { data } = await server.videos.list()
314 300
315 const video = res.body.data.find(v => v.name === videoAttributes.name) 301 const video = data.find(v => v.name === attributes.name)
316 const res2 = await getVideo(server.url, video.id) 302 const videoDetails = await server.videos.get({ id: video.id })
317 const videoDetails: VideoDetails = res2.body 303
304 const file = videoDetails.files.find(f => f.resolution.id === 240)
305 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
318 306
319 expect(videoDetails.files).to.have.lengthOf(4)
320 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4'))
321 const probe = await getAudioStream(path) 307 const probe = await getAudioStream(path)
322 expect(probe).to.not.have.property('audioStream') 308 expect(probe).to.not.have.property('audioStream')
323 } 309 }
@@ -326,26 +312,27 @@ describe('Test video transcoding', function () {
326 it('Should leave the audio untouched, but properly transcode the video', async function () { 312 it('Should leave the audio untouched, but properly transcode the video', async function () {
327 this.timeout(60_000) 313 this.timeout(60_000)
328 314
329 const videoAttributes = { 315 const attributes = {
330 name: 'untouched_audio', 316 name: 'untouched_audio',
331 fixture: 'video_short.mp4' 317 fixture: 'video_short.mp4'
332 } 318 }
333 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 319 await servers[1].videos.upload({ attributes })
334 320
335 await waitJobs(servers) 321 await waitJobs(servers)
336 322
337 for (const server of servers) { 323 for (const server of servers) {
338 const res = await getVideosList(server.url) 324 const { data } = await server.videos.list()
339 325
340 const video = res.body.data.find(v => v.name === videoAttributes.name) 326 const video = data.find(v => v.name === attributes.name)
341 const res2 = await getVideo(server.url, video.id) 327 const videoDetails = await server.videos.get({ id: video.id })
342 const videoDetails: VideoDetails = res2.body
343 328
344 expect(videoDetails.files).to.have.lengthOf(4) 329 expect(videoDetails.files).to.have.lengthOf(4)
345 330
346 const fixturePath = buildAbsoluteFixturePath(videoAttributes.fixture) 331 const fixturePath = buildAbsoluteFixturePath(attributes.fixture)
347 const fixtureVideoProbe = await getAudioStream(fixturePath) 332 const fixtureVideoProbe = await getAudioStream(fixturePath)
348 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4')) 333
334 const file = videoDetails.files.find(f => f.resolution.id === 240)
335 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
349 336
350 const videoProbe = await getAudioStream(path) 337 const videoProbe = await getAudioStream(path)
351 338
@@ -364,19 +351,21 @@ describe('Test video transcoding', function () {
364 function runSuite (mode: 'legacy' | 'resumable') { 351 function runSuite (mode: 'legacy' | 'resumable') {
365 352
366 before(async function () { 353 before(async function () {
367 await updateCustomSubConfig(servers[1].url, servers[1].accessToken, { 354 await servers[1].config.updateCustomSubConfig({
368 transcoding: { 355 newConfig: {
369 hls: { enabled: true }, 356 transcoding: {
370 webtorrent: { enabled: true }, 357 hls: { enabled: true },
371 resolutions: { 358 webtorrent: { enabled: true },
372 '0p': false, 359 resolutions: {
373 '240p': false, 360 '0p': false,
374 '360p': false, 361 '240p': false,
375 '480p': false, 362 '360p': false,
376 '720p': false, 363 '480p': false,
377 '1080p': false, 364 '720p': false,
378 '1440p': false, 365 '1080p': false,
379 '2160p': false 366 '1440p': false,
367 '2160p': false
368 }
380 } 369 }
381 } 370 }
382 }) 371 })
@@ -385,22 +374,21 @@ describe('Test video transcoding', function () {
385 it('Should merge an audio file with the preview file', async function () { 374 it('Should merge an audio file with the preview file', async function () {
386 this.timeout(60_000) 375 this.timeout(60_000)
387 376
388 const videoAttributesArg = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' } 377 const attributes = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
389 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode) 378 await servers[1].videos.upload({ attributes, mode })
390 379
391 await waitJobs(servers) 380 await waitJobs(servers)
392 381
393 for (const server of servers) { 382 for (const server of servers) {
394 const res = await getVideosList(server.url) 383 const { data } = await server.videos.list()
395 384
396 const video = res.body.data.find(v => v.name === 'audio_with_preview') 385 const video = data.find(v => v.name === 'audio_with_preview')
397 const res2 = await getVideo(server.url, video.id) 386 const videoDetails = await server.videos.get({ id: video.id })
398 const videoDetails: VideoDetails = res2.body
399 387
400 expect(videoDetails.files).to.have.lengthOf(1) 388 expect(videoDetails.files).to.have.lengthOf(1)
401 389
402 await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, statusCodeExpected: HttpStatusCode.OK_200 }) 390 await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
403 await makeGetRequest({ url: server.url, path: videoDetails.previewPath, statusCodeExpected: HttpStatusCode.OK_200 }) 391 await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
404 392
405 const magnetUri = videoDetails.files[0].magnetUri 393 const magnetUri = videoDetails.files[0].magnetUri
406 expect(magnetUri).to.contain('.mp4') 394 expect(magnetUri).to.contain('.mp4')
@@ -410,22 +398,21 @@ describe('Test video transcoding', function () {
410 it('Should upload an audio file and choose a default background image', async function () { 398 it('Should upload an audio file and choose a default background image', async function () {
411 this.timeout(60_000) 399 this.timeout(60_000)
412 400
413 const videoAttributesArg = { name: 'audio_without_preview', fixture: 'sample.ogg' } 401 const attributes = { name: 'audio_without_preview', fixture: 'sample.ogg' }
414 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode) 402 await servers[1].videos.upload({ attributes, mode })
415 403
416 await waitJobs(servers) 404 await waitJobs(servers)
417 405
418 for (const server of servers) { 406 for (const server of servers) {
419 const res = await getVideosList(server.url) 407 const { data } = await server.videos.list()
420 408
421 const video = res.body.data.find(v => v.name === 'audio_without_preview') 409 const video = data.find(v => v.name === 'audio_without_preview')
422 const res2 = await getVideo(server.url, video.id) 410 const videoDetails = await server.videos.get({ id: video.id })
423 const videoDetails = res2.body
424 411
425 expect(videoDetails.files).to.have.lengthOf(1) 412 expect(videoDetails.files).to.have.lengthOf(1)
426 413
427 await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, statusCodeExpected: HttpStatusCode.OK_200 }) 414 await makeGetRequest({ url: server.url, path: videoDetails.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
428 await makeGetRequest({ url: server.url, path: videoDetails.previewPath, statusCodeExpected: HttpStatusCode.OK_200 }) 415 await makeGetRequest({ url: server.url, path: videoDetails.previewPath, expectedStatus: HttpStatusCode.OK_200 })
429 416
430 const magnetUri = videoDetails.files[0].magnetUri 417 const magnetUri = videoDetails.files[0].magnetUri
431 expect(magnetUri).to.contain('.mp4') 418 expect(magnetUri).to.contain('.mp4')
@@ -435,26 +422,27 @@ describe('Test video transcoding', function () {
435 it('Should upload an audio file and create an audio version only', async function () { 422 it('Should upload an audio file and create an audio version only', async function () {
436 this.timeout(60_000) 423 this.timeout(60_000)
437 424
438 await updateCustomSubConfig(servers[1].url, servers[1].accessToken, { 425 await servers[1].config.updateCustomSubConfig({
439 transcoding: { 426 newConfig: {
440 hls: { enabled: true }, 427 transcoding: {
441 webtorrent: { enabled: true }, 428 hls: { enabled: true },
442 resolutions: { 429 webtorrent: { enabled: true },
443 '0p': true, 430 resolutions: {
444 '240p': false, 431 '0p': true,
445 '360p': false 432 '240p': false,
433 '360p': false
434 }
446 } 435 }
447 } 436 }
448 }) 437 })
449 438
450 const videoAttributesArg = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' } 439 const attributes = { name: 'audio_with_preview', previewfile: 'preview.jpg', fixture: 'sample.ogg' }
451 const resVideo = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributesArg, HttpStatusCode.OK_200, mode) 440 const { id } = await servers[1].videos.upload({ attributes, mode })
452 441
453 await waitJobs(servers) 442 await waitJobs(servers)
454 443
455 for (const server of servers) { 444 for (const server of servers) {
456 const res2 = await getVideo(server.url, resVideo.body.video.id) 445 const videoDetails = await server.videos.get({ id })
457 const videoDetails: VideoDetails = res2.body
458 446
459 for (const files of [ videoDetails.files, videoDetails.streamingPlaylists[0].files ]) { 447 for (const files of [ videoDetails.files, videoDetails.streamingPlaylists[0].files ]) {
460 expect(files).to.have.lengthOf(2) 448 expect(files).to.have.lengthOf(2)
@@ -480,21 +468,20 @@ describe('Test video transcoding', function () {
480 it('Should transcode a 60 FPS video', async function () { 468 it('Should transcode a 60 FPS video', async function () {
481 this.timeout(60_000) 469 this.timeout(60_000)
482 470
483 const videoAttributes = { 471 const attributes = {
484 name: 'my super 30fps name for server 2', 472 name: 'my super 30fps name for server 2',
485 description: 'my super 30fps description for server 2', 473 description: 'my super 30fps description for server 2',
486 fixture: '60fps_720p_small.mp4' 474 fixture: '60fps_720p_small.mp4'
487 } 475 }
488 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 476 await servers[1].videos.upload({ attributes })
489 477
490 await waitJobs(servers) 478 await waitJobs(servers)
491 479
492 for (const server of servers) { 480 for (const server of servers) {
493 const res = await getVideosList(server.url) 481 const { data } = await server.videos.list()
494 482
495 const video = res.body.data.find(v => v.name === videoAttributes.name) 483 const video = data.find(v => v.name === attributes.name)
496 const res2 = await getVideo(server.url, video.id) 484 const videoDetails = await server.videos.get({ id: video.id })
497 const videoDetails: VideoDetails = res2.body
498 485
499 expect(videoDetails.files).to.have.lengthOf(4) 486 expect(videoDetails.files).to.have.lengthOf(4)
500 expect(videoDetails.files[0].fps).to.be.above(58).and.below(62) 487 expect(videoDetails.files[0].fps).to.be.above(58).and.below(62)
@@ -502,14 +489,16 @@ describe('Test video transcoding', function () {
502 expect(videoDetails.files[2].fps).to.be.below(31) 489 expect(videoDetails.files[2].fps).to.be.below(31)
503 expect(videoDetails.files[3].fps).to.be.below(31) 490 expect(videoDetails.files[3].fps).to.be.below(31)
504 491
505 for (const resolution of [ '240', '360', '480' ]) { 492 for (const resolution of [ 240, 360, 480 ]) {
506 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-' + resolution + '.mp4')) 493 const file = videoDetails.files.find(f => f.resolution.id === resolution)
494 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
507 const fps = await getVideoFileFPS(path) 495 const fps = await getVideoFileFPS(path)
508 496
509 expect(fps).to.be.below(31) 497 expect(fps).to.be.below(31)
510 } 498 }
511 499
512 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-720.mp4')) 500 const file = videoDetails.files.find(f => f.resolution.id === 720)
501 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
513 const fps = await getVideoFileFPS(path) 502 const fps = await getVideoFileFPS(path)
514 503
515 expect(fps).to.be.above(58).and.below(62) 504 expect(fps).to.be.above(58).and.below(62)
@@ -528,29 +517,32 @@ describe('Test video transcoding', function () {
528 expect(fps).to.be.equal(59) 517 expect(fps).to.be.equal(59)
529 } 518 }
530 519
531 const videoAttributes = { 520 const attributes = {
532 name: '59fps video', 521 name: '59fps video',
533 description: '59fps video', 522 description: '59fps video',
534 fixture: tempFixturePath 523 fixture: tempFixturePath
535 } 524 }
536 525
537 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 526 await servers[1].videos.upload({ attributes })
538 527
539 await waitJobs(servers) 528 await waitJobs(servers)
540 529
541 for (const server of servers) { 530 for (const server of servers) {
542 const res = await getVideosList(server.url) 531 const { data } = await server.videos.list()
543 532
544 const video = res.body.data.find(v => v.name === videoAttributes.name) 533 const { id } = data.find(v => v.name === attributes.name)
534 const video = await server.videos.get({ id })
545 535
546 { 536 {
547 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-240.mp4')) 537 const file = video.files.find(f => f.resolution.id === 240)
538 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
548 const fps = await getVideoFileFPS(path) 539 const fps = await getVideoFileFPS(path)
549 expect(fps).to.be.equal(25) 540 expect(fps).to.be.equal(25)
550 } 541 }
551 542
552 { 543 {
553 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-720.mp4')) 544 const file = video.files.find(f => f.resolution.id === 720)
545 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
554 const fps = await getVideoFileFPS(path) 546 const fps = await getVideoFileFPS(path)
555 expect(fps).to.be.equal(59) 547 expect(fps).to.be.equal(59)
556 } 548 }
@@ -559,6 +551,7 @@ describe('Test video transcoding', function () {
559 }) 551 })
560 552
561 describe('Bitrate control', function () { 553 describe('Bitrate control', function () {
554
562 it('Should respect maximum bitrate values', async function () { 555 it('Should respect maximum bitrate values', async function () {
563 this.timeout(160_000) 556 this.timeout(160_000)
564 557
@@ -571,30 +564,32 @@ describe('Test video transcoding', function () {
571 expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 25, VIDEO_TRANSCODING_FPS)) 564 expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 25, VIDEO_TRANSCODING_FPS))
572 } 565 }
573 566
574 const videoAttributes = { 567 const attributes = {
575 name: 'high bitrate video', 568 name: 'high bitrate video',
576 description: 'high bitrate video', 569 description: 'high bitrate video',
577 fixture: tempFixturePath 570 fixture: tempFixturePath
578 } 571 }
579 572
580 await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 573 await servers[1].videos.upload({ attributes })
581 574
582 await waitJobs(servers) 575 await waitJobs(servers)
583 576
584 for (const server of servers) { 577 for (const server of servers) {
585 const res = await getVideosList(server.url) 578 const { data } = await server.videos.list()
586 579
587 const video = res.body.data.find(v => v.name === videoAttributes.name) 580 const { id } = data.find(v => v.name === attributes.name)
581 const video = await server.videos.get({ id })
588 582
589 for (const resolution of [ '240', '360', '480', '720', '1080' ]) { 583 for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
590 const path = buildServerDirectory(servers[1], join('videos', video.uuid + '-' + resolution + '.mp4')) 584 const file = video.files.find(f => f.resolution.id === resolution)
585 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
591 586
592 const bitrate = await getVideoFileBitrate(path) 587 const bitrate = await getVideoFileBitrate(path)
593 const fps = await getVideoFileFPS(path) 588 const fps = await getVideoFileFPS(path)
594 const resolution2 = await getVideoFileResolution(path) 589 const { videoFileResolution } = await getVideoFileResolution(path)
595 590
596 expect(resolution2.videoFileResolution.toString()).to.equal(resolution) 591 expect(videoFileResolution).to.equal(resolution)
597 expect(bitrate).to.be.below(getMaxBitrate(resolution2.videoFileResolution, fps, VIDEO_TRANSCODING_FPS)) 592 expect(bitrate).to.be.below(getMaxBitrate(videoFileResolution, fps, VIDEO_TRANSCODING_FPS))
598 } 593 }
599 } 594 }
600 }) 595 })
@@ -602,7 +597,7 @@ describe('Test video transcoding', function () {
602 it('Should not transcode to an higher bitrate than the original file', async function () { 597 it('Should not transcode to an higher bitrate than the original file', async function () {
603 this.timeout(160_000) 598 this.timeout(160_000)
604 599
605 const config = { 600 const newConfig = {
606 transcoding: { 601 transcoding: {
607 enabled: true, 602 enabled: true,
608 resolutions: { 603 resolutions: {
@@ -618,22 +613,25 @@ describe('Test video transcoding', function () {
618 hls: { enabled: true } 613 hls: { enabled: true }
619 } 614 }
620 } 615 }
621 await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config) 616 await servers[1].config.updateCustomSubConfig({ newConfig })
622 617
623 const videoAttributes = { 618 const attributes = {
624 name: 'low bitrate', 619 name: 'low bitrate',
625 fixture: 'low-bitrate.mp4' 620 fixture: 'low-bitrate.mp4'
626 } 621 }
627 622
628 const resUpload = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) 623 const { id } = await servers[1].videos.upload({ attributes })
629 const videoUUID = resUpload.body.video.uuid
630 624
631 await waitJobs(servers) 625 await waitJobs(servers)
632 626
627 const video = await servers[1].videos.get({ id })
628
633 const resolutions = [ 240, 360, 480, 720, 1080 ] 629 const resolutions = [ 240, 360, 480, 720, 1080 ]
634 for (const r of resolutions) { 630 for (const r of resolutions) {
635 const path = `videos/${videoUUID}-${r}.mp4` 631 const file = video.files.find(f => f.resolution.id === r)
636 const size = await getServerFileSize(servers[1], path) 632
633 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
634 const size = await getFileSize(path)
637 expect(size, `${path} not below ${60_000}`).to.be.below(60_000) 635 expect(size, `${path} not below ${60_000}`).to.be.below(60_000)
638 } 636 }
639 }) 637 })
@@ -644,11 +642,13 @@ describe('Test video transcoding', function () {
644 it('Should provide valid ffprobe data', async function () { 642 it('Should provide valid ffprobe data', async function () {
645 this.timeout(160_000) 643 this.timeout(160_000)
646 644
647 const videoUUID = (await uploadVideoAndGetId({ server: servers[1], videoName: 'ffprobe data' })).uuid 645 const videoUUID = (await servers[1].videos.quickUpload({ name: 'ffprobe data' })).uuid
648 await waitJobs(servers) 646 await waitJobs(servers)
649 647
650 { 648 {
651 const path = buildServerDirectory(servers[1], join('videos', videoUUID + '-240.mp4')) 649 const video = await servers[1].videos.get({ id: videoUUID })
650 const file = video.files.find(f => f.resolution.id === 240)
651 const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl)
652 const metadata = await getMetadataFromFile(path) 652 const metadata = await getMetadataFromFile(path)
653 653
654 // expected format properties 654 // expected format properties
@@ -678,8 +678,7 @@ describe('Test video transcoding', function () {
678 } 678 }
679 679
680 for (const server of servers) { 680 for (const server of servers) {
681 const res2 = await getVideo(server.url, videoUUID) 681 const videoDetails = await server.videos.get({ id: videoUUID })
682 const videoDetails: VideoDetails = res2.body
683 682
684 const videoFiles = videoDetails.files 683 const videoFiles = videoDetails.files
685 .concat(videoDetails.streamingPlaylists[0].files) 684 .concat(videoDetails.streamingPlaylists[0].files)
@@ -691,8 +690,7 @@ describe('Test video transcoding', function () {
691 expect(file.metadataUrl).to.contain(servers[1].url) 690 expect(file.metadataUrl).to.contain(servers[1].url)
692 expect(file.metadataUrl).to.contain(videoUUID) 691 expect(file.metadataUrl).to.contain(videoUUID)
693 692
694 const res3 = await getVideoFileMetadataUrl(file.metadataUrl) 693 const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
695 const metadata: FfprobeData = res3.body
696 expect(metadata).to.have.nested.property('format.size') 694 expect(metadata).to.have.nested.property('format.size')
697 } 695 }
698 } 696 }
@@ -709,17 +707,14 @@ describe('Test video transcoding', function () {
709 describe('Transcoding job queue', function () { 707 describe('Transcoding job queue', function () {
710 708
711 it('Should have the appropriate priorities for transcoding jobs', async function () { 709 it('Should have the appropriate priorities for transcoding jobs', async function () {
712 const res = await getJobsListPaginationAndSort({ 710 const body = await servers[1].jobs.getJobsList({
713 url: servers[1].url,
714 accessToken: servers[1].accessToken,
715 start: 0, 711 start: 0,
716 count: 100, 712 count: 100,
717 sort: '-createdAt', 713 sort: '-createdAt',
718 jobType: 'video-transcoding' 714 jobType: 'video-transcoding'
719 }) 715 })
720 716
721 const jobs = res.body.data as Job[] 717 const jobs = body.data
722
723 const transcodingJobs = jobs.filter(j => j.data.videoUUID === video4k) 718 const transcodingJobs = jobs.filter(j => j.data.videoUUID === video4k)
724 719
725 expect(transcodingJobs).to.have.lengthOf(14) 720 expect(transcodingJobs).to.have.lengthOf(14)