]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/plugins/plugin-transcoding.ts
Introduce user 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 7import {
ae2abfd3 8 cleanupTests,
ae2abfd3 9 flushAndRunServer,
1896bca0 10 getVideo,
ae2abfd3 11 PluginsCommand,
ae2abfd3 12 ServerInfo,
1896bca0
C
13 setAccessTokensToServers,
14 setDefaultVideoChannel,
3e03b961 15 testFfmpegStreamError,
1896bca0 16 uploadVideoAndGetId,
4f219914 17 waitJobs
ae2abfd3 18} from '@shared/extra-utils'
65e6e260 19import { VideoDetails, VideoPrivacy } from '@shared/models'
1896bca0
C
20
21async function createLiveWrapper (server: ServerInfo) {
22 const liveAttributes = {
23 name: 'live video',
24 channelId: server.videoChannel.id,
25 privacy: VideoPrivacy.PUBLIC
26 }
27
04aed767 28 const { uuid } = await server.liveCommand.create({ fields: liveAttributes })
4f219914
C
29
30 return uuid
1896bca0
C
31}
32
33function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
65e6e260
C
34 return server.configCommand.updateCustomSubConfig({
35 newConfig: {
1896bca0 36 transcoding: {
b3eafc5f 37 enabled: true,
65e6e260
C
38 profile: vodProfile,
39 hls: {
40 enabled: true
41 },
42 webtorrent: {
43 enabled: true
44 },
b3eafc5f
C
45 resolutions: {
46 '240p': true,
47 '360p': false,
48 '480p': false,
49 '720p': true
50 }
65e6e260
C
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 }
1896bca0
C
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 () {
ae2abfd3 109 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
1896bca0
C
110 })
111
112 it('Should have the appropriate available profiles', async function () {
65e6e260 113 const config = await server.configCommand.getConfig()
1896bca0 114
3e03b961
C
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' ])
1896bca0
C
117 })
118
119 it('Should not use the plugin profile if not chosen by the admin', async function () {
fc8f15d2 120 this.timeout(240000)
1896bca0
C
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 () {
fc8f15d2 129 this.timeout(240000)
1896bca0
C
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
3e03b961 139 it('Should apply input options in vod profile', async function () {
fc8f15d2 140 this.timeout(240000)
d2351bcf 141
3e03b961 142 await updateConf(server, 'input-options-vod', 'default')
d2351bcf
TLC
143
144 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
145 await waitJobs([ server ])
146
3e03b961 147 await checkVideoFPS(videoUUID, 'below', 6)
d2351bcf
TLC
148 })
149
3e03b961 150 it('Should apply the scale filter in vod profile', async function () {
fc8f15d2 151 this.timeout(240000)
d2351bcf 152
3e03b961 153 await updateConf(server, 'bad-scale-vod', 'default')
d2351bcf
TLC
154
155 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video' })).uuid
156 await waitJobs([ server ])
157
3e03b961
C
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)
d2351bcf
TLC
164 })
165
1896bca0 166 it('Should not use the plugin profile if not chosen by the admin', async function () {
fc8f15d2 167 this.timeout(240000)
1896bca0
C
168
169 const liveVideoId = await createLiveWrapper(server)
170
4f219914 171 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
04aed767 172 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
1896bca0
C
173 await waitJobs([ server ])
174
175 await checkLiveFPS(liveVideoId, 'above', 20)
176 })
177
178 it('Should use the live profile', async function () {
fc8f15d2 179 this.timeout(240000)
1896bca0
C
180
181 await updateConf(server, 'low-vod', 'low-live')
182
183 const liveVideoId = await createLiveWrapper(server)
184
4f219914 185 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
04aed767 186 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
1896bca0
C
187 await waitJobs([ server ])
188
189 await checkLiveFPS(liveVideoId, 'below', 12)
190 })
191
d2351bcf 192 it('Should apply the input options on live profile', async function () {
fc8f15d2 193 this.timeout(240000)
d2351bcf
TLC
194
195 await updateConf(server, 'low-vod', 'input-options-live')
196
197 const liveVideoId = await createLiveWrapper(server)
198
4f219914 199 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
04aed767 200 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
d2351bcf
TLC
201 await waitJobs([ server ])
202
203 await checkLiveFPS(liveVideoId, 'below', 6)
204 })
205
3e03b961 206 it('Should apply the scale filter name on live profile', async function () {
fc8f15d2 207 this.timeout(240000)
3e03b961
C
208
209 await updateConf(server, 'low-vod', 'bad-scale-live')
210
211 const liveVideoId = await createLiveWrapper(server)
212
4f219914 213 const command = await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
3e03b961
C
214 await testFfmpegStreamError(command, true)
215 })
216
1896bca0 217 it('Should default to the default profile if the specified profile does not exist', async function () {
fc8f15d2 218 this.timeout(240000)
1896bca0 219
ae2abfd3 220 await server.pluginsCommand.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
1896bca0 221
65e6e260 222 const config = await server.configCommand.getConfig()
1896bca0
C
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 () {
ae2abfd3 238 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
1896bca0
C
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
a8537c62 246 const videoUUID = (await uploadVideoAndGetId({ server, videoName: 'video', fixture: 'video_short_240p.mp4' })).uuid
1896bca0
C
247 await waitJobs([ server ])
248
6c5065a0 249 const path = server.serversCommand.buildDirectory(join('videos', videoUUID + '-240.mp4'))
1896bca0
C
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 () {
fc8f15d2 258 this.timeout(240000)
1896bca0
C
259
260 const liveVideoId = await createLiveWrapper(server)
261
4f219914 262 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
04aed767 263 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
1896bca0
C
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})