]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame_incremental - server/tests/plugins/plugin-transcoding.ts
Introduce user command
[github/Chocobozzz/PeerTube.git] / server / tests / plugins / plugin-transcoding.ts
... / ...
CommitLineData
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import 'mocha'
4import { expect } from 'chai'
5import { join } from 'path'
6import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
7import {
8 cleanupTests,
9 flushAndRunServer,
10 getVideo,
11 PluginsCommand,
12 ServerInfo,
13 setAccessTokensToServers,
14 setDefaultVideoChannel,
15 testFfmpegStreamError,
16 uploadVideoAndGetId,
17 waitJobs
18} from '@shared/extra-utils'
19import { VideoDetails, VideoPrivacy } from '@shared/models'
20
21async function createLiveWrapper (server: ServerInfo) {
22 const liveAttributes = {
23 name: 'live video',
24 channelId: server.videoChannel.id,
25 privacy: VideoPrivacy.PUBLIC
26 }
27
28 const { uuid } = await server.liveCommand.create({ fields: liveAttributes })
29
30 return uuid
31}
32
33function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
34 return server.configCommand.updateCustomSubConfig({
35 newConfig: {
36 transcoding: {
37 enabled: true,
38 profile: vodProfile,
39 hls: {
40 enabled: true
41 },
42 webtorrent: {
43 enabled: true
44 },
45 resolutions: {
46 '240p': true,
47 '360p': false,
48 '480p': false,
49 '720p': true
50 }
51 },
52 live: {
53 transcoding: {
54 profile: liveProfile,
55 enabled: true,
56 resolutions: {
57 '240p': true,
58 '360p': false,
59 '480p': false,
60 '720p': true
61 }
62 }
63 }
64 }
65 })
66}
67
68describe('Test transcoding plugins', function () {
69 let server: ServerInfo
70
71 before(async function () {
72 this.timeout(60000)
73
74 server = await flushAndRunServer(1)
75 await setAccessTokensToServers([ server ])
76 await setDefaultVideoChannel([ server ])
77
78 await updateConf(server, 'default', 'default')
79 })
80
81 describe('When using a plugin adding profiles to existing encoders', function () {
82
83 async function checkVideoFPS (uuid: string, type: 'above' | 'below', fps: number) {
84 const res = await getVideo(server.url, uuid)
85 const video = res.body as VideoDetails
86 const files = video.files.concat(...video.streamingPlaylists.map(p => p.files))
87
88 for (const file of files) {
89 if (type === 'above') {
90 expect(file.fps).to.be.above(fps)
91 } else {
92 expect(file.fps).to.be.below(fps)
93 }
94 }
95 }
96
97 async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) {
98 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8`
99 const videoFPS = await getVideoFileFPS(playlistUrl)
100
101 if (type === 'above') {
102 expect(videoFPS).to.be.above(fps)
103 } else {
104 expect(videoFPS).to.be.below(fps)
105 }
106 }
107
108 before(async function () {
109 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
110 })
111
112 it('Should have the appropriate available profiles', async function () {
113 const config = await server.configCommand.getConfig()
114
115 expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ])
116 expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'low-live', 'input-options-live', 'bad-scale-live' ])
117 })
118
119 it('Should not use the plugin profile if not chosen by the admin', async function () {
120 this.timeout(240000)
121
122 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
123 await waitJobs([ server ])
124
125 await checkVideoFPS(videoUUID, 'above', 20)
126 })
127
128 it('Should use the vod profile', async function () {
129 this.timeout(240000)
130
131 await updateConf(server, 'low-vod', 'default')
132
133 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
134 await waitJobs([ server ])
135
136 await checkVideoFPS(videoUUID, 'below', 12)
137 })
138
139 it('Should apply input options in vod profile', async function () {
140 this.timeout(240000)
141
142 await updateConf(server, 'input-options-vod', 'default')
143
144 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
145 await waitJobs([ server ])
146
147 await checkVideoFPS(videoUUID, 'below', 6)
148 })
149
150 it('Should apply the scale filter in vod profile', async function () {
151 this.timeout(240000)
152
153 await updateConf(server, 'bad-scale-vod', 'default')
154
155 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
156 await waitJobs([ server ])
157
158 // Transcoding failed
159 const res = await getVideo(server.url, videoUUID)
160 const video: VideoDetails = res.body
161
162 expect(video.files).to.have.lengthOf(1)
163 expect(video.streamingPlaylists).to.have.lengthOf(0)
164 })
165
166 it('Should not use the plugin profile if not chosen by the admin', async function () {
167 this.timeout(240000)
168
169 const liveVideoId = await createLiveWrapper(server)
170
171 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
172 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
173 await waitJobs([ server ])
174
175 await checkLiveFPS(liveVideoId, 'above', 20)
176 })
177
178 it('Should use the live profile', async function () {
179 this.timeout(240000)
180
181 await updateConf(server, 'low-vod', 'low-live')
182
183 const liveVideoId = await createLiveWrapper(server)
184
185 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
186 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
187 await waitJobs([ server ])
188
189 await checkLiveFPS(liveVideoId, 'below', 12)
190 })
191
192 it('Should apply the input options on live profile', async function () {
193 this.timeout(240000)
194
195 await updateConf(server, 'low-vod', 'input-options-live')
196
197 const liveVideoId = await createLiveWrapper(server)
198
199 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
200 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
201 await waitJobs([ server ])
202
203 await checkLiveFPS(liveVideoId, 'below', 6)
204 })
205
206 it('Should apply the scale filter name on live profile', async function () {
207 this.timeout(240000)
208
209 await updateConf(server, 'low-vod', 'bad-scale-live')
210
211 const liveVideoId = await createLiveWrapper(server)
212
213 const command = await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
214 await testFfmpegStreamError(command, true)
215 })
216
217 it('Should default to the default profile if the specified profile does not exist', async function () {
218 this.timeout(240000)
219
220 await server.pluginsCommand.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
221
222 const config = await server.configCommand.getConfig()
223
224 expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
225 expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
226
227 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
228 await waitJobs([ server ])
229
230 await checkVideoFPS(videoUUID, 'above', 20)
231 })
232
233 })
234
235 describe('When using a plugin adding new encoders', function () {
236
237 before(async function () {
238 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
239
240 await updateConf(server, 'test-vod-profile', 'test-live-profile')
241 })
242
243 it('Should use the new vod encoders', async function () {
244 this.timeout(240000)
245
246 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video', fixture: 'video_short_240p.mp4' })).uuid
247 await waitJobs([ server ])
248
249 const path = server.serversCommand.buildDirectory(join('videos', videoUUID + '-240.mp4'))
250 const audioProbe = await getAudioStream(path)
251 expect(audioProbe.audioStream.codec_name).to.equal('opus')
252
253 const videoProbe = await getVideoStreamFromFile(path)
254 expect(videoProbe.codec_name).to.equal('vp9')
255 })
256
257 it('Should use the new live encoders', async function () {
258 this.timeout(240000)
259
260 const liveVideoId = await createLiveWrapper(server)
261
262 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
263 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
264 await waitJobs([ server ])
265
266 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
267 const audioProbe = await getAudioStream(playlistUrl)
268 expect(audioProbe.audioStream.codec_name).to.equal('opus')
269
270 const videoProbe = await getVideoStreamFromFile(playlistUrl)
271 expect(videoProbe.codec_name).to.equal('h264')
272 })
273 })
274
275 after(async function () {
276 await cleanupTests([ server ])
277 })
278})