1 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
3 import { expect } from 'chai'
4 import { getAudioStream, getVideoStream, getVideoStreamFPS } from '@shared/ffmpeg'
5 import { VideoPrivacy } from '@shared/models'
11 setAccessTokensToServers,
12 setDefaultVideoChannel,
13 testFfmpegStreamError,
15 } from '@shared/server-commands'
17 async function createLiveWrapper (server: PeerTubeServer) {
18 const liveAttributes = {
20 channelId: server.store.channel.id,
21 privacy: VideoPrivacy.PUBLIC
24 const { uuid } = await server.live.create({ fields: liveAttributes })
29 function updateConf (server: PeerTubeServer, vodProfile: string, liveProfile: string) {
30 return server.config.updateCustomSubConfig({
64 describe('Test transcoding plugins', function () {
65 let server: PeerTubeServer
67 before(async function () {
70 server = await createSingleServer(1)
71 await setAccessTokensToServers([ server ])
72 await setDefaultVideoChannel([ server ])
74 await updateConf(server, 'default', 'default')
77 describe('When using a plugin adding profiles to existing encoders', function () {
79 async function checkVideoFPS (uuid: string, type: 'above' | 'below', fps: number) {
80 const video = await server.videos.get({ id: uuid })
81 const files = video.files.concat(...video.streamingPlaylists.map(p => p.files))
83 for (const file of files) {
84 if (type === 'above') {
85 expect(file.fps).to.be.above(fps)
87 expect(file.fps).to.be.below(fps)
92 async function checkLiveFPS (uuid: string, type: 'above' | 'below', fps: number) {
93 const playlistUrl = `${server.url}/static/streaming-playlists/hls/${uuid}/0.m3u8`
94 const videoFPS = await getVideoStreamFPS(playlistUrl)
96 if (type === 'above') {
97 expect(videoFPS).to.be.above(fps)
99 expect(videoFPS).to.be.below(fps)
103 before(async function () {
104 await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-one') })
107 it('Should have the appropriate available profiles', async function () {
108 const config = await server.config.getConfig()
110 expect(config.transcoding.availableProfiles).to.have.members([ 'default', 'low-vod', 'input-options-vod', 'bad-scale-vod' ])
111 expect(config.live.transcoding.availableProfiles).to.have.members([ 'default', 'high-live', 'input-options-live', 'bad-scale-live' ])
114 describe('VOD', function () {
116 it('Should not use the plugin profile if not chosen by the admin', async function () {
119 const videoUUID = (await server.videos.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.videos.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.videos.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.videos.quickUpload({ name: 'video' })).uuid
153 await waitJobs([ server ])
155 // Transcoding failed
156 const video = await server.videos.get({ id: videoUUID })
157 expect(video.files).to.have.lengthOf(1)
158 expect(video.streamingPlaylists).to.have.lengthOf(0)
162 describe('Live', function () {
164 it('Should not use the plugin profile if not chosen by the admin', async function () {
167 const liveVideoId = await createLiveWrapper(server)
169 await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
170 await server.live.waitUntilPublished({ videoId: liveVideoId })
171 await waitJobs([ server ])
173 await checkLiveFPS(liveVideoId, 'above', 20)
176 it('Should use the live profile', async function () {
179 await updateConf(server, 'low-vod', 'high-live')
181 const liveVideoId = await createLiveWrapper(server)
183 await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
184 await server.live.waitUntilPublished({ videoId: liveVideoId })
185 await waitJobs([ server ])
187 await checkLiveFPS(liveVideoId, 'above', 45)
190 it('Should apply the input options on live profile', async function () {
193 await updateConf(server, 'low-vod', 'input-options-live')
195 const liveVideoId = await createLiveWrapper(server)
197 await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
198 await server.live.waitUntilPublished({ videoId: liveVideoId })
199 await waitJobs([ server ])
201 await checkLiveFPS(liveVideoId, 'above', 45)
204 it('Should apply the scale filter name on live profile', async function () {
207 await updateConf(server, 'low-vod', 'bad-scale-live')
209 const liveVideoId = await createLiveWrapper(server)
211 const command = await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_very_short_240p.mp4' })
212 await testFfmpegStreamError(command, true)
215 it('Should default to the default profile if the specified profile does not exist', async function () {
218 await server.plugins.uninstall({ npmName: 'peertube-plugin-test-transcoding-one' })
220 const config = await server.config.getConfig()
222 expect(config.transcoding.availableProfiles).to.deep.equal([ 'default' ])
223 expect(config.live.transcoding.availableProfiles).to.deep.equal([ 'default' ])
225 const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
226 await waitJobs([ server ])
228 await checkVideoFPS(videoUUID, 'above', 20)
234 describe('When using a plugin adding new encoders', function () {
236 before(async function () {
237 await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-transcoding-two') })
239 await updateConf(server, 'test-vod-profile', 'test-live-profile')
242 it('Should use the new vod encoders', async function () {
245 const videoUUID = (await server.videos.quickUpload({ name: 'video', fixture: 'video_very_short_240p.mp4' })).uuid
246 await waitJobs([ server ])
248 const video = await server.videos.get({ id: videoUUID })
250 const path = server.servers.buildWebTorrentFilePath(video.files[0].fileUrl)
251 const audioProbe = await getAudioStream(path)
252 expect(audioProbe.audioStream.codec_name).to.equal('opus')
254 const videoProbe = await getVideoStream(path)
255 expect(videoProbe.codec_name).to.equal('vp9')
258 it('Should use the new live encoders', async function () {
261 const liveVideoId = await createLiveWrapper(server)
263 await server.live.sendRTMPStreamInVideo({ videoId: liveVideoId, fixtureName: 'video_short2.webm' })
264 await server.live.waitUntilPublished({ videoId: liveVideoId })
265 await waitJobs([ server ])
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')
271 const videoProbe = await getVideoStream(playlistUrl)
272 expect(videoProbe.codec_name).to.equal('h264')
276 after(async function () {
277 await cleanupTests([ server ])