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