1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
4 import { expect } from 'chai'
5 import { join } from 'path'
6 import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
12 setAccessTokensToServers,
13 setDefaultVideoChannel,
14 testFfmpegStreamError,
16 } from '@shared/extra-utils'
17 import { VideoPrivacy } from '@shared/models'
19 async function createLiveWrapper (server: ServerInfo) {
20 const liveAttributes = {
22 channelId: server.videoChannel.id,
23 privacy: VideoPrivacy.PUBLIC
26 const { uuid } = await server.liveCommand.create({ fields: liveAttributes })
31 function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
32 return server.configCommand.updateCustomSubConfig({
66 describe('Test transcoding plugins', function () {
67 let server: ServerInfo
69 before(async function () {
72 server = await flushAndRunServer(1)
73 await setAccessTokensToServers([ server ])
74 await setDefaultVideoChannel([ server ])
76 await updateConf(server, 'default', 'default')
79 describe('When using a plugin adding profiles to existing encoders', function () {
81 async function checkVideoFPS (uuid: string, type: 'above' | 'below', fps: number) {
82 const video = await server.videosCommand.get({ id: uuid })
83 const files = video.files.concat(...video.streamingPlaylists.map(p => p.files))
85 for (const file of files) {
86 if (type === 'above') {
87 expect(file.fps).to.be.above(fps)
89 expect(file.fps).to.be.below(fps)
94 async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) {
95 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8`
96 const videoFPS = await getVideoFileFPS(playlistUrl)
98 if (type === 'above') {
99 expect(videoFPS).to.be.above(fps)
101 expect(videoFPS).to.be.below(fps)
105 before(async function () {
106 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
109 it('Should have the appropriate available profiles', async function () {
110 const config = await server.configCommand.getConfig()
112 expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ])
113 expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'low-live', 'input-options-live', 'bad-scale-live' ])
116 it('Should not use the plugin profile if not chosen by the admin', async function () {
119 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video' })).uuid
120 await waitJobs([ server ])
122 await checkVideoFPS(videoUUID, 'above', 20)
125 it('Should use the vod profile', async function () {
128 await updateConf(server, 'low-vod', 'default')
130 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video' })).uuid
131 await waitJobs([ server ])
133 await checkVideoFPS(videoUUID, 'below', 12)
136 it('Should apply input options in vod profile', async function () {
139 await updateConf(server, 'input-options-vod', 'default')
141 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video' })).uuid
142 await waitJobs([ server ])
144 await checkVideoFPS(videoUUID, 'below', 6)
147 it('Should apply the scale filter in vod profile', async function () {
150 await updateConf(server, 'bad-scale-vod', 'default')
152 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video' })).uuid
153 await waitJobs([ server ])
155 // Transcoding failed
156 const video = await server.videosCommand.get({ id: videoUUID })
157 expect(video.files).to.have.lengthOf(1)
158 expect(video.streamingPlaylists).to.have.lengthOf(0)
161 it('Should not use the plugin profile if not chosen by the admin', async function () {
164 const liveVideoId = await createLiveWrapper(server)
166 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
167 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
168 await waitJobs([ server ])
170 await checkLiveFPS(liveVideoId, 'above', 20)
173 it('Should use the live profile', async function () {
176 await updateConf(server, 'low-vod', 'low-live')
178 const liveVideoId = await createLiveWrapper(server)
180 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
181 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
182 await waitJobs([ server ])
184 await checkLiveFPS(liveVideoId, 'below', 12)
187 it('Should apply the input options on live profile', async function () {
190 await updateConf(server, 'low-vod', 'input-options-live')
192 const liveVideoId = await createLiveWrapper(server)
194 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
195 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
196 await waitJobs([ server ])
198 await checkLiveFPS(liveVideoId, 'below', 6)
201 it('Should apply the scale filter name on live profile', async function () {
204 await updateConf(server, 'low-vod', 'bad-scale-live')
206 const liveVideoId = await createLiveWrapper(server)
208 const command = await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
209 await testFfmpegStreamError(command, true)
212 it('Should default to the default profile if the specified profile does not exist', async function () {
215 await server.pluginsCommand.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
217 const config = await server.configCommand.getConfig()
219 expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
220 expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
222 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video' })).uuid
223 await waitJobs([ server ])
225 await checkVideoFPS(videoUUID, 'above', 20)
230 describe('When using a plugin adding new encoders', function () {
232 before(async function () {
233 await server.pluginsCommand.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
235 await updateConf(server, 'test-vod-profile', 'test-live-profile')
238 it('Should use the new vod encoders', async function () {
241 const videoUUID = (await server.videosCommand.quickUpload({ name: 'video', fixture: 'video_short_240p.mp4' })).uuid
242 await waitJobs([ server ])
244 const path = server.serversCommand.buildDirectory(join('videos', videoUUID + '-240.mp4'))
245 const audioProbe = await getAudioStream(path)
246 expect(audioProbe.audioStream.codec_name).to.equal('opus')
248 const videoProbe = await getVideoStreamFromFile(path)
249 expect(videoProbe.codec_name).to.equal('vp9')
252 it('Should use the new live encoders', async function () {
255 const liveVideoId = await createLiveWrapper(server)
257 await server.liveCommand.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
258 await server.liveCommand.waitUntilPublished({ videoId: liveVideoId })
259 await waitJobs([ server ])
261 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${liveVideoId}/0.m3u8`
262 const audioProbe = await getAudioStream(playlistUrl)
263 expect(audioProbe.audioStream.codec_name).to.equal('opus')
265 const videoProbe = await getVideoStreamFromFile(playlistUrl)
266 expect(videoProbe.codec_name).to.equal('h264')
270 after(async function () {
271 await cleanupTests([ server ])