1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } from 'chai'
4 import { readFile } from 'fs-extra'
5 import { checkPersistentTmpIsEmpty, checkVideoDuration } from '@server/tests/shared'
6 import { buildAbsoluteFixturePath } from '@shared/core-utils'
8 RunnerJobStudioTranscodingPayload,
9 VideoStudioTranscodingSuccess,
13 } from '@shared/models'
16 createMultipleServers,
19 setAccessTokensToServers,
20 setDefaultVideoChannel,
23 } from '@shared/server-commands'
25 describe('Test runner video studio transcoding', function () {
26 let servers: PeerTubeServer[] = []
27 let runnerToken: string
31 async function renewStudio (tasks: VideoStudioTask[] = VideoStudioCommand.getComplexTask()) {
32 const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
35 await waitJobs(servers)
37 await servers[0].videoStudio.createEditionTasks({ videoId: uuid, tasks })
38 await waitJobs(servers)
40 const { availableJobs } = await servers[0].runnerJobs.request({ runnerToken })
41 expect(availableJobs).to.have.lengthOf(1)
43 jobUUID = availableJobs[0].uuid
46 before(async function () {
49 servers = await createMultipleServers(2)
51 await setAccessTokensToServers(servers)
52 await setDefaultVideoChannel(servers)
54 await doubleFollow(servers[0], servers[1])
56 await servers[0].config.enableTranscoding(true, true)
57 await servers[0].config.enableStudio()
58 await servers[0].config.enableRemoteStudio()
60 runnerToken = await servers[0].runners.autoRegisterRunner()
63 it('Should error a studio transcoding job', async function () {
68 for (let i = 0; i < 5; i++) {
69 const { job } = await servers[0].runnerJobs.accept({ runnerToken, jobUUID })
70 const jobToken = job.jobToken
72 await servers[0].runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error' })
75 const video = await servers[0].videos.get({ id: videoUUID })
76 expect(video.state.id).to.equal(VideoState.PUBLISHED)
78 await checkPersistentTmpIsEmpty(servers[0])
81 it('Should cancel a transcoding job', async function () {
86 await servers[0].runnerJobs.cancelByAdmin({ jobUUID })
88 const video = await servers[0].videos.get({ id: videoUUID })
89 expect(video.state.id).to.equal(VideoState.PUBLISHED)
91 await checkPersistentTmpIsEmpty(servers[0])
94 it('Should execute a remote studio job', async function () {
99 name: 'add-outro' as 'add-outro',
101 file: 'video_short.webm'
105 name: 'add-watermark' as 'add-watermark',
107 file: 'thumbnail.png'
111 name: 'add-intro' as 'add-intro',
113 file: 'video_very_short_240p.mp4'
118 await renewStudio(tasks)
120 for (const server of servers) {
121 await checkVideoDuration(server, videoUUID, 5)
124 const { job } = await servers[0].runnerJobs.accept<RunnerJobStudioTranscodingPayload>({ runnerToken, jobUUID })
125 const jobToken = job.jobToken
127 expect(job.type === 'video-studio-transcoding')
128 expect(job.payload.input.videoFileUrl).to.exist
130 // Check video input file
132 await servers[0].runnerJobs.getJobFile({ url: job.payload.input.videoFileUrl, jobToken, runnerToken })
136 for (let i = 0; i < tasks.length; i++) {
137 const task = tasks[i]
138 const payloadTask = job.payload.tasks[i]
140 expect(payloadTask.name).to.equal(task.name)
142 const inputFile = await readFile(buildAbsoluteFixturePath(task.options.file))
144 const { body } = await servers[0].runnerJobs.getJobFile({
145 url: (payloadTask as VideoStudioTaskIntro).options.file as string,
150 expect(body).to.deep.equal(inputFile)
153 const payload: VideoStudioTranscodingSuccess = { videoFile: 'video_very_short_240p.mp4' }
154 await servers[0].runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
156 await waitJobs(servers)
158 for (const server of servers) {
159 await checkVideoDuration(server, videoUUID, 2)
162 await checkPersistentTmpIsEmpty(servers[0])
165 after(async function () {
166 await cleanupTests(servers)