]>
Commit | Line | Data |
---|---|---|
d102de1b C |
1 | import { expect } from 'chai' |
2 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | |
3 | import { expectStartWith, PeerTubeRunnerProcess, SQLCommand, testLiveVideoResolutions } from '@server/tests/shared' | |
4 | import { areMockObjectStorageTestsDisabled, wait } from '@shared/core-utils' | |
5 | import { HttpStatusCode, VideoPrivacy } from '@shared/models' | |
6 | import { | |
7 | cleanupTests, | |
8 | createMultipleServers, | |
9 | doubleFollow, | |
10 | findExternalSavedVideo, | |
11 | makeRawRequest, | |
12 | ObjectStorageCommand, | |
13 | PeerTubeServer, | |
14 | setAccessTokensToServers, | |
15 | setDefaultVideoChannel, | |
16 | stopFfmpeg, | |
17 | waitJobs, | |
18 | waitUntilLivePublishedOnAllServers, | |
19 | waitUntilLiveWaitingOnAllServers | |
20 | } from '@shared/server-commands' | |
21 | ||
22 | describe('Test Live transcoding in peertube-runner program', function () { | |
23 | let servers: PeerTubeServer[] = [] | |
24 | let peertubeRunner: PeerTubeRunnerProcess | |
25 | let sqlCommandServer1: SQLCommand | |
26 | ||
27 | function runSuite (options: { | |
28 | objectStorage: boolean | |
29 | }) { | |
30 | const { objectStorage } = options | |
31 | ||
32 | it('Should enable transcoding without additional resolutions', async function () { | |
33 | this.timeout(120000) | |
34 | ||
35 | const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.PUBLIC }) | |
36 | ||
37 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid }) | |
38 | await waitUntilLivePublishedOnAllServers(servers, video.uuid) | |
39 | await waitJobs(servers) | |
40 | ||
41 | await testLiveVideoResolutions({ | |
42 | originServer: servers[0], | |
43 | sqlCommand: sqlCommandServer1, | |
44 | servers, | |
45 | liveVideoId: video.uuid, | |
46 | resolutions: [ 720, 480, 360, 240, 144 ], | |
47 | objectStorage, | |
48 | transcoded: true | |
49 | }) | |
50 | ||
51 | await stopFfmpeg(ffmpegCommand) | |
52 | ||
53 | await waitUntilLiveWaitingOnAllServers(servers, video.uuid) | |
54 | await servers[0].videos.remove({ id: video.id }) | |
55 | }) | |
56 | ||
57 | it('Should transcode audio only RTMP stream', async function () { | |
58 | this.timeout(120000) | |
59 | ||
60 | const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: false, privacy: VideoPrivacy.UNLISTED }) | |
61 | ||
62 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid, fixtureName: 'video_short_no_audio.mp4' }) | |
63 | await waitUntilLivePublishedOnAllServers(servers, video.uuid) | |
64 | await waitJobs(servers) | |
65 | ||
66 | await stopFfmpeg(ffmpegCommand) | |
67 | ||
68 | await waitUntilLiveWaitingOnAllServers(servers, video.uuid) | |
69 | await servers[0].videos.remove({ id: video.id }) | |
70 | }) | |
71 | ||
72 | it('Should save a replay', async function () { | |
73 | this.timeout(120000) | |
74 | ||
75 | const { video } = await servers[0].live.quickCreate({ permanentLive: true, saveReplay: true }) | |
76 | ||
77 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ videoId: video.uuid }) | |
78 | await waitUntilLivePublishedOnAllServers(servers, video.uuid) | |
79 | ||
80 | await testLiveVideoResolutions({ | |
81 | originServer: servers[0], | |
82 | sqlCommand: sqlCommandServer1, | |
83 | servers, | |
84 | liveVideoId: video.uuid, | |
85 | resolutions: [ 720, 480, 360, 240, 144 ], | |
86 | objectStorage, | |
87 | transcoded: true | |
88 | }) | |
89 | ||
90 | await stopFfmpeg(ffmpegCommand) | |
91 | ||
92 | await waitUntilLiveWaitingOnAllServers(servers, video.uuid) | |
93 | await waitJobs(servers) | |
94 | ||
95 | const session = await servers[0].live.findLatestSession({ videoId: video.uuid }) | |
96 | expect(session.endingProcessed).to.be.true | |
97 | expect(session.endDate).to.exist | |
98 | expect(session.saveReplay).to.be.true | |
99 | ||
100 | const videoLiveDetails = await servers[0].videos.get({ id: video.uuid }) | |
101 | const replay = await findExternalSavedVideo(servers[0], videoLiveDetails) | |
102 | ||
103 | for (const server of servers) { | |
104 | const video = await server.videos.get({ id: replay.uuid }) | |
105 | ||
106 | expect(video.files).to.have.lengthOf(0) | |
107 | expect(video.streamingPlaylists).to.have.lengthOf(1) | |
108 | ||
109 | const files = video.streamingPlaylists[0].files | |
110 | expect(files).to.have.lengthOf(5) | |
111 | ||
112 | for (const file of files) { | |
113 | if (objectStorage) { | |
114 | expectStartWith(file.fileUrl, ObjectStorageCommand.getMockPlaylistBaseUrl()) | |
115 | } | |
116 | ||
117 | await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 }) | |
118 | } | |
119 | } | |
120 | }) | |
121 | } | |
122 | ||
123 | before(async function () { | |
124 | this.timeout(120_000) | |
125 | ||
126 | servers = await createMultipleServers(2) | |
127 | ||
128 | await setAccessTokensToServers(servers) | |
129 | await setDefaultVideoChannel(servers) | |
130 | ||
131 | await doubleFollow(servers[0], servers[1]) | |
132 | ||
133 | sqlCommandServer1 = new SQLCommand(servers[0]) | |
134 | ||
135 | await servers[0].config.enableRemoteTranscoding() | |
136 | await servers[0].config.enableTranscoding(true, true, true) | |
137 | await servers[0].config.enableLive({ allowReplay: true, resolutions: 'max', transcoding: true }) | |
138 | ||
139 | const registrationToken = await servers[0].runnerRegistrationTokens.getFirstRegistrationToken() | |
140 | ||
141 | peertubeRunner = new PeerTubeRunnerProcess() | |
142 | await peertubeRunner.runServer({ hideLogs: false }) | |
143 | await peertubeRunner.registerPeerTubeInstance({ server: servers[0], registrationToken, runnerName: 'runner' }) | |
144 | }) | |
145 | ||
146 | describe('With lives on local filesystem storage', function () { | |
147 | ||
148 | before(async function () { | |
149 | await servers[0].config.enableTranscoding(true, false, true) | |
150 | }) | |
151 | ||
152 | runSuite({ objectStorage: false }) | |
153 | }) | |
154 | ||
155 | describe('With lives on object storage', function () { | |
156 | if (areMockObjectStorageTestsDisabled()) return | |
157 | ||
158 | before(async function () { | |
159 | await ObjectStorageCommand.prepareDefaultMockBuckets() | |
160 | ||
161 | await servers[0].kill() | |
162 | ||
163 | await servers[0].run(ObjectStorageCommand.getDefaultMockConfig()) | |
164 | ||
165 | // Wait for peertube runner socket reconnection | |
166 | await wait(1500) | |
167 | }) | |
168 | ||
169 | runSuite({ objectStorage: true }) | |
170 | }) | |
171 | ||
172 | after(async function () { | |
173 | await peertubeRunner.unregisterPeerTubeInstance({ server: servers[0] }) | |
174 | peertubeRunner.kill() | |
175 | ||
176 | await cleanupTests(servers) | |
177 | }) | |
178 | }) |