aboutsummaryrefslogtreecommitdiffhomepage
path: root/packages/tests/src/api/videos/video-storyboard.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/tests/src/api/videos/video-storyboard.ts')
-rw-r--r--packages/tests/src/api/videos/video-storyboard.ts213
1 files changed, 213 insertions, 0 deletions
diff --git a/packages/tests/src/api/videos/video-storyboard.ts b/packages/tests/src/api/videos/video-storyboard.ts
new file mode 100644
index 000000000..7d156aa7f
--- /dev/null
+++ b/packages/tests/src/api/videos/video-storyboard.ts
@@ -0,0 +1,213 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { readdir } from 'fs/promises'
5import { basename } from 'path'
6import { FIXTURE_URLS } from '@tests/shared/tests.js'
7import { areHttpImportTestsDisabled } from '@peertube/peertube-node-utils'
8import { HttpStatusCode, VideoPrivacy } from '@peertube/peertube-models'
9import {
10 cleanupTests,
11 createMultipleServers,
12 doubleFollow,
13 makeGetRequest,
14 PeerTubeServer,
15 sendRTMPStream,
16 setAccessTokensToServers,
17 setDefaultVideoChannel,
18 stopFfmpeg,
19 waitJobs
20} from '@peertube/peertube-server-commands'
21
22async function checkStoryboard (options: {
23 server: PeerTubeServer
24 uuid: string
25 tilesCount?: number
26 minSize?: number
27}) {
28 const { server, uuid, tilesCount, minSize = 1000 } = options
29
30 const { storyboards } = await server.storyboard.list({ id: uuid })
31
32 expect(storyboards).to.have.lengthOf(1)
33
34 const storyboard = storyboards[0]
35
36 expect(storyboard.spriteDuration).to.equal(1)
37 expect(storyboard.spriteHeight).to.equal(108)
38 expect(storyboard.spriteWidth).to.equal(192)
39 expect(storyboard.storyboardPath).to.exist
40
41 if (tilesCount) {
42 expect(storyboard.totalWidth).to.equal(192 * Math.min(tilesCount, 10))
43 expect(storyboard.totalHeight).to.equal(108 * Math.max((tilesCount / 10), 1))
44 }
45
46 const { body } = await makeGetRequest({ url: server.url, path: storyboard.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
47 expect(body.length).to.be.above(minSize)
48}
49
50describe('Test video storyboard', function () {
51 let servers: PeerTubeServer[]
52
53 let baseUUID: string
54
55 before(async function () {
56 this.timeout(120000)
57
58 servers = await createMultipleServers(2)
59 await setAccessTokensToServers(servers)
60 await setDefaultVideoChannel(servers)
61
62 await doubleFollow(servers[0], servers[1])
63 })
64
65 it('Should generate a storyboard after upload without transcoding', async function () {
66 this.timeout(120000)
67
68 // 5s video
69 const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_short.webm' })
70 baseUUID = uuid
71 await waitJobs(servers)
72
73 for (const server of servers) {
74 await checkStoryboard({ server, uuid, tilesCount: 5 })
75 }
76 })
77
78 it('Should generate a storyboard after upload without transcoding with a long video', async function () {
79 this.timeout(120000)
80
81 // 124s video
82 const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_very_long_10p.mp4' })
83 await waitJobs(servers)
84
85 for (const server of servers) {
86 await checkStoryboard({ server, uuid, tilesCount: 100 })
87 }
88 })
89
90 it('Should generate a storyboard after upload with transcoding', async function () {
91 this.timeout(120000)
92
93 await servers[0].config.enableMinimumTranscoding()
94
95 // 5s video
96 const { uuid } = await servers[0].videos.quickUpload({ name: 'upload', fixture: 'video_short.webm' })
97 await waitJobs(servers)
98
99 for (const server of servers) {
100 await checkStoryboard({ server, uuid, tilesCount: 5 })
101 }
102 })
103
104 it('Should generate a storyboard after an audio upload', async function () {
105 this.timeout(120000)
106
107 // 6s audio
108 const attributes = { name: 'audio', fixture: 'sample.ogg' }
109 const { uuid } = await servers[0].videos.upload({ attributes, mode: 'legacy' })
110 await waitJobs(servers)
111
112 for (const server of servers) {
113 try {
114 await checkStoryboard({ server, uuid, tilesCount: 6, minSize: 250 })
115 } catch { // FIXME: to remove after ffmpeg CI upgrade, ffmpeg CI version (4.3) generates a 7.6s length video
116 await checkStoryboard({ server, uuid, tilesCount: 8, minSize: 250 })
117 }
118 }
119 })
120
121 it('Should generate a storyboard after HTTP import', async function () {
122 this.timeout(120000)
123
124 if (areHttpImportTestsDisabled()) return
125
126 // 3s video
127 const { video } = await servers[0].imports.importVideo({
128 attributes: {
129 targetUrl: FIXTURE_URLS.goodVideo,
130 channelId: servers[0].store.channel.id,
131 privacy: VideoPrivacy.PUBLIC
132 }
133 })
134 await waitJobs(servers)
135
136 for (const server of servers) {
137 await checkStoryboard({ server, uuid: video.uuid, tilesCount: 3 })
138 }
139 })
140
141 it('Should generate a storyboard after torrent import', async function () {
142 this.timeout(120000)
143
144 if (areHttpImportTestsDisabled()) return
145
146 // 10s video
147 const { video } = await servers[0].imports.importVideo({
148 attributes: {
149 magnetUri: FIXTURE_URLS.magnet,
150 channelId: servers[0].store.channel.id,
151 privacy: VideoPrivacy.PUBLIC
152 }
153 })
154 await waitJobs(servers)
155
156 for (const server of servers) {
157 await checkStoryboard({ server, uuid: video.uuid, tilesCount: 10 })
158 }
159 })
160
161 it('Should generate a storyboard after a live', async function () {
162 this.timeout(240000)
163
164 await servers[0].config.enableLive({ allowReplay: true, transcoding: true, resolutions: 'min' })
165
166 const { live, video } = await servers[0].live.quickCreate({
167 saveReplay: true,
168 permanentLive: false,
169 privacy: VideoPrivacy.PUBLIC
170 })
171
172 const ffmpegCommand = sendRTMPStream({ rtmpBaseUrl: live.rtmpUrl, streamKey: live.streamKey })
173 await servers[0].live.waitUntilPublished({ videoId: video.id })
174
175 await stopFfmpeg(ffmpegCommand)
176
177 await servers[0].live.waitUntilReplacedByReplay({ videoId: video.id })
178 await waitJobs(servers)
179
180 for (const server of servers) {
181 await checkStoryboard({ server, uuid: video.uuid })
182 }
183 })
184
185 it('Should cleanup storyboards on video deletion', async function () {
186 this.timeout(60000)
187
188 const { storyboards } = await servers[0].storyboard.list({ id: baseUUID })
189 const storyboardName = basename(storyboards[0].storyboardPath)
190
191 const listFiles = () => {
192 const storyboardPath = servers[0].getDirectoryPath('storyboards')
193 return readdir(storyboardPath)
194 }
195
196 {
197 const storyboads = await listFiles()
198 expect(storyboads).to.include(storyboardName)
199 }
200
201 await servers[0].videos.remove({ id: baseUUID })
202 await waitJobs(servers)
203
204 {
205 const storyboads = await listFiles()
206 expect(storyboads).to.not.include(storyboardName)
207 }
208 })
209
210 after(async function () {
211 await cleanupTests(servers)
212 })
213})