aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/transcoding/video-studio.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/tests/api/transcoding/video-studio.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/tests/api/transcoding/video-studio.ts')
-rw-r--r--server/tests/api/transcoding/video-studio.ts377
1 files changed, 0 insertions, 377 deletions
diff --git a/server/tests/api/transcoding/video-studio.ts b/server/tests/api/transcoding/video-studio.ts
deleted file mode 100644
index ba68f8e24..000000000
--- a/server/tests/api/transcoding/video-studio.ts
+++ /dev/null
@@ -1,377 +0,0 @@
1import { expect } from 'chai'
2import { checkPersistentTmpIsEmpty, checkVideoDuration, expectStartWith } from '@server/tests/shared'
3import { areMockObjectStorageTestsDisabled, getAllFiles } from '@shared/core-utils'
4import { VideoStudioTask } from '@shared/models'
5import {
6 cleanupTests,
7 createMultipleServers,
8 doubleFollow,
9 ObjectStorageCommand,
10 PeerTubeServer,
11 setAccessTokensToServers,
12 setDefaultVideoChannel,
13 VideoStudioCommand,
14 waitJobs
15} from '@shared/server-commands'
16
17describe('Test video studio', function () {
18 let servers: PeerTubeServer[] = []
19 let videoUUID: string
20
21 async function renewVideo (fixture = 'video_short.webm') {
22 const video = await servers[0].videos.quickUpload({ name: 'video', fixture })
23 videoUUID = video.uuid
24
25 await waitJobs(servers)
26 }
27
28 async function createTasks (tasks: VideoStudioTask[]) {
29 await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks })
30 await waitJobs(servers)
31 }
32
33 before(async function () {
34 this.timeout(120_000)
35
36 servers = await createMultipleServers(2)
37
38 await setAccessTokensToServers(servers)
39 await setDefaultVideoChannel(servers)
40
41 await doubleFollow(servers[0], servers[1])
42
43 await servers[0].config.enableMinimumTranscoding()
44
45 await servers[0].config.enableStudio()
46 })
47
48 describe('Cutting', function () {
49
50 it('Should cut the beginning of the video', async function () {
51 this.timeout(120_000)
52
53 await renewVideo()
54 await waitJobs(servers)
55
56 const beforeTasks = new Date()
57
58 await createTasks([
59 {
60 name: 'cut',
61 options: {
62 start: 2
63 }
64 }
65 ])
66
67 for (const server of servers) {
68 await checkVideoDuration(server, videoUUID, 3)
69
70 const video = await server.videos.get({ id: videoUUID })
71 expect(new Date(video.publishedAt)).to.be.below(beforeTasks)
72 }
73 })
74
75 it('Should cut the end of the video', async function () {
76 this.timeout(120_000)
77 await renewVideo()
78
79 await createTasks([
80 {
81 name: 'cut',
82 options: {
83 end: 2
84 }
85 }
86 ])
87
88 for (const server of servers) {
89 await checkVideoDuration(server, videoUUID, 2)
90 }
91 })
92
93 it('Should cut start/end of the video', async function () {
94 this.timeout(120_000)
95 await renewVideo('video_short1.webm') // 10 seconds video duration
96
97 await createTasks([
98 {
99 name: 'cut',
100 options: {
101 start: 2,
102 end: 6
103 }
104 }
105 ])
106
107 for (const server of servers) {
108 await checkVideoDuration(server, videoUUID, 4)
109 }
110 })
111 })
112
113 describe('Intro/Outro', function () {
114
115 it('Should add an intro', async function () {
116 this.timeout(120_000)
117 await renewVideo()
118
119 await createTasks([
120 {
121 name: 'add-intro',
122 options: {
123 file: 'video_short.webm'
124 }
125 }
126 ])
127
128 for (const server of servers) {
129 await checkVideoDuration(server, videoUUID, 10)
130 }
131 })
132
133 it('Should add an outro', async function () {
134 this.timeout(120_000)
135 await renewVideo()
136
137 await createTasks([
138 {
139 name: 'add-outro',
140 options: {
141 file: 'video_very_short_240p.mp4'
142 }
143 }
144 ])
145
146 for (const server of servers) {
147 await checkVideoDuration(server, videoUUID, 7)
148 }
149 })
150
151 it('Should add an intro/outro', async function () {
152 this.timeout(120_000)
153 await renewVideo()
154
155 await createTasks([
156 {
157 name: 'add-intro',
158 options: {
159 file: 'video_very_short_240p.mp4'
160 }
161 },
162 {
163 name: 'add-outro',
164 options: {
165 // Different frame rate
166 file: 'video_short2.webm'
167 }
168 }
169 ])
170
171 for (const server of servers) {
172 await checkVideoDuration(server, videoUUID, 12)
173 }
174 })
175
176 it('Should add an intro to a video without audio', async function () {
177 this.timeout(120_000)
178 await renewVideo('video_short_no_audio.mp4')
179
180 await createTasks([
181 {
182 name: 'add-intro',
183 options: {
184 file: 'video_very_short_240p.mp4'
185 }
186 }
187 ])
188
189 for (const server of servers) {
190 await checkVideoDuration(server, videoUUID, 7)
191 }
192 })
193
194 it('Should add an outro without audio to a video with audio', async function () {
195 this.timeout(120_000)
196 await renewVideo()
197
198 await createTasks([
199 {
200 name: 'add-outro',
201 options: {
202 file: 'video_short_no_audio.mp4'
203 }
204 }
205 ])
206
207 for (const server of servers) {
208 await checkVideoDuration(server, videoUUID, 10)
209 }
210 })
211
212 it('Should add an outro without audio to a video with audio', async function () {
213 this.timeout(120_000)
214 await renewVideo('video_short_no_audio.mp4')
215
216 await createTasks([
217 {
218 name: 'add-outro',
219 options: {
220 file: 'video_short_no_audio.mp4'
221 }
222 }
223 ])
224
225 for (const server of servers) {
226 await checkVideoDuration(server, videoUUID, 10)
227 }
228 })
229 })
230
231 describe('Watermark', function () {
232
233 it('Should add a watermark to the video', async function () {
234 this.timeout(120_000)
235 await renewVideo()
236
237 const video = await servers[0].videos.get({ id: videoUUID })
238 const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
239
240 await createTasks([
241 {
242 name: 'add-watermark',
243 options: {
244 file: 'custom-thumbnail.png'
245 }
246 }
247 ])
248
249 for (const server of servers) {
250 const video = await server.videos.get({ id: videoUUID })
251 const fileUrls = getAllFiles(video).map(f => f.fileUrl)
252
253 for (const oldUrl of oldFileUrls) {
254 expect(fileUrls).to.not.include(oldUrl)
255 }
256 }
257 })
258 })
259
260 describe('Complex tasks', function () {
261 it('Should run a complex task', async function () {
262 this.timeout(240_000)
263 await renewVideo()
264
265 await createTasks(VideoStudioCommand.getComplexTask())
266
267 for (const server of servers) {
268 await checkVideoDuration(server, videoUUID, 9)
269 }
270 })
271 })
272
273 describe('HLS only studio edition', function () {
274
275 before(async function () {
276 // Disable Web Videos
277 await servers[0].config.updateExistingSubConfig({
278 newConfig: {
279 transcoding: {
280 webVideos: {
281 enabled: false
282 }
283 }
284 }
285 })
286 })
287
288 it('Should run a complex task on HLS only video', async function () {
289 this.timeout(240_000)
290 await renewVideo()
291
292 await createTasks(VideoStudioCommand.getComplexTask())
293
294 for (const server of servers) {
295 const video = await server.videos.get({ id: videoUUID })
296 expect(video.files).to.have.lengthOf(0)
297
298 await checkVideoDuration(server, videoUUID, 9)
299 }
300 })
301 })
302
303 describe('Server restart', function () {
304
305 it('Should still be able to run video edition after a server restart', async function () {
306 this.timeout(240_000)
307
308 await renewVideo()
309 await servers[0].videoStudio.createEditionTasks({ videoId: videoUUID, tasks: VideoStudioCommand.getComplexTask() })
310
311 await servers[0].kill()
312 await servers[0].run()
313
314 await waitJobs(servers)
315
316 for (const server of servers) {
317 await checkVideoDuration(server, videoUUID, 9)
318 }
319 })
320
321 it('Should have an empty persistent tmp directory', async function () {
322 await checkPersistentTmpIsEmpty(servers[0])
323 })
324 })
325
326 describe('Object storage studio edition', function () {
327 if (areMockObjectStorageTestsDisabled()) return
328
329 const objectStorage = new ObjectStorageCommand()
330
331 before(async function () {
332 await objectStorage.prepareDefaultMockBuckets()
333
334 await servers[0].kill()
335 await servers[0].run(objectStorage.getDefaultMockConfig())
336
337 await servers[0].config.enableMinimumTranscoding()
338 })
339
340 it('Should run a complex task on a video in object storage', async function () {
341 this.timeout(240_000)
342 await renewVideo()
343
344 const video = await servers[0].videos.get({ id: videoUUID })
345 const oldFileUrls = getAllFiles(video).map(f => f.fileUrl)
346
347 await createTasks(VideoStudioCommand.getComplexTask())
348
349 for (const server of servers) {
350 const video = await server.videos.get({ id: videoUUID })
351 const files = getAllFiles(video)
352
353 for (const f of files) {
354 expect(oldFileUrls).to.not.include(f.fileUrl)
355 }
356
357 for (const webVideoFile of video.files) {
358 expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
359 }
360
361 for (const hlsFile of video.streamingPlaylists[0].files) {
362 expectStartWith(hlsFile.fileUrl, objectStorage.getMockPlaylistBaseUrl())
363 }
364
365 await checkVideoDuration(server, videoUUID, 9)
366 }
367 })
368
369 after(async function () {
370 await objectStorage.cleanupMock()
371 })
372 })
373
374 after(async function () {
375 await cleanupTests(servers)
376 })
377})