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