]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tests/api/videos/video-imports.ts
Introduce playlist command
[github/Chocobozzz/PeerTube.git] / server / tests / api / videos / video-imports.ts
CommitLineData
a1587156 1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
590fb506 2
590fb506 3import 'mocha'
b488ba1e 4import * as chai from 'chai'
590fb506 5import {
7c3b7976 6 cleanupTests,
590fb506
C
7 doubleFollow,
8 flushAndRunMultipleServers,
9 getMyUserInformation,
10 getMyVideos,
11 getVideo,
12 getVideosList,
3e17515e 13 immutableAssign,
590fb506 14 ServerInfo,
b488ba1e 15 setAccessTokensToServers,
65e6e260 16 testCaptionFile
94565d52 17} from '../../../../shared/extra-utils'
b488ba1e 18import { areHttpImportTestsDisabled, testImage } from '../../../../shared/extra-utils/miscs/miscs'
94565d52 19import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
454c20fa
RK
20import {
21 getMagnetURI,
22 getMyVideoImports,
23 getYoutubeHDRVideoUrl,
24 getYoutubeVideoUrl,
25 importVideo
26} from '../../../../shared/extra-utils/videos/video-imports'
a2470c9f 27import { VideoDetails, VideoImport, VideoPrivacy, VideoResolution } from '../../../../shared/models/videos'
590fb506
C
28
29const expect = chai.expect
30
31describe('Test video imports', function () {
32 let servers: ServerInfo[] = []
33 let channelIdServer1: number
34 let channelIdServer2: number
35
b488ba1e
C
36 if (areHttpImportTestsDisabled()) return
37
a2470c9f
C
38 async function checkVideosServer1 (server: ServerInfo, idHttp: string, idMagnet: string, idTorrent: string) {
39 const resHttp = await getVideo(server.url, idHttp)
3e17515e
C
40 const videoHttp: VideoDetails = resHttp.body
41
42 expect(videoHttp.name).to.equal('small video - youtube')
f9b6d51f
C
43 // FIXME: youtube-dl seems broken
44 // expect(videoHttp.category.label).to.equal('News & Politics')
1dee8d68 45 // expect(videoHttp.licence.label).to.equal('Attribution')
3e17515e
C
46 expect(videoHttp.language.label).to.equal('Unknown')
47 expect(videoHttp.nsfw).to.be.false
48 expect(videoHttp.description).to.equal('this is a super description')
49 expect(videoHttp.tags).to.deep.equal([ 'tag1', 'tag2' ])
50 expect(videoHttp.files).to.have.lengthOf(1)
17036be5
C
51
52 const originallyPublishedAt = new Date(videoHttp.originallyPublishedAt)
53 expect(originallyPublishedAt.getDate()).to.equal(14)
54 expect(originallyPublishedAt.getMonth()).to.equal(0)
55 expect(originallyPublishedAt.getFullYear()).to.equal(2019)
3e17515e 56
a2470c9f 57 const resMagnet = await getVideo(server.url, idMagnet)
3e17515e 58 const videoMagnet: VideoDetails = resMagnet.body
a2470c9f 59 const resTorrent = await getVideo(server.url, idTorrent)
3e17515e
C
60 const videoTorrent: VideoDetails = resTorrent.body
61
62 for (const video of [ videoMagnet, videoTorrent ]) {
63 expect(video.category.label).to.equal('Misc')
64 expect(video.licence.label).to.equal('Unknown')
65 expect(video.language.label).to.equal('Unknown')
66 expect(video.nsfw).to.be.false
67 expect(video.description).to.equal('this is a super torrent description')
68 expect(video.tags).to.deep.equal([ 'tag_torrent1', 'tag_torrent2' ])
69 expect(video.files).to.have.lengthOf(1)
70 }
590fb506 71
3e17515e
C
72 expect(videoTorrent.name).to.contain('你好 世界 720p.mp4')
73 expect(videoMagnet.name).to.contain('super peertube2 video')
652c6416 74
a2470c9f
C
75 const bodyCaptions = await server.captionsCommand.listVideoCaptions({ videoId: idHttp })
76 expect(bodyCaptions.total).to.equal(2)
590fb506
C
77 }
78
a2470c9f
C
79 async function checkVideoServer2 (server: ServerInfo, id: number | string) {
80 const res = await getVideo(server.url, id)
652c6416 81 const video: VideoDetails = res.body
590fb506
C
82
83 expect(video.name).to.equal('my super name')
84 expect(video.category.label).to.equal('Entertainment')
85 expect(video.licence.label).to.equal('Public Domain Dedication')
86 expect(video.language.label).to.equal('English')
87 expect(video.nsfw).to.be.false
88 expect(video.description).to.equal('my super description')
89 expect(video.tags).to.deep.equal([ 'supertag1', 'supertag2' ])
90
91 expect(video.files).to.have.lengthOf(1)
652c6416 92
a2470c9f
C
93 const bodyCaptions = await server.captionsCommand.listVideoCaptions({ videoId: id })
94 expect(bodyCaptions.total).to.equal(2)
590fb506
C
95 }
96
97 before(async function () {
454c20fa 98 this.timeout(30_000)
590fb506
C
99
100 // Run servers
101 servers = await flushAndRunMultipleServers(2)
102
103 await setAccessTokensToServers(servers)
104
105 {
106 const res = await getMyUserInformation(servers[0].url, servers[0].accessToken)
a1587156 107 channelIdServer1 = res.body.videoChannels[0].id
590fb506
C
108 }
109
110 {
111 const res = await getMyUserInformation(servers[1].url, servers[1].accessToken)
a1587156 112 channelIdServer2 = res.body.videoChannels[0].id
590fb506
C
113 }
114
115 await doubleFollow(servers[0], servers[1])
116 })
117
3e17515e 118 it('Should import videos on server 1', async function () {
454c20fa 119 this.timeout(60_000)
590fb506 120
3e17515e 121 const baseAttributes = {
590fb506
C
122 channelId: channelIdServer1,
123 privacy: VideoPrivacy.PUBLIC
124 }
3e17515e
C
125
126 {
127 const attributes = immutableAssign(baseAttributes, { targetUrl: getYoutubeVideoUrl() })
128 const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
129 expect(res.body.video.name).to.equal('small video - youtube')
53c06121
C
130
131 expect(res.body.video.thumbnailPath).to.match(new RegExp(`^/static/thumbnails/.+.jpg$`))
132 expect(res.body.video.previewPath).to.match(new RegExp(`^/lazy-static/previews/.+.jpg$`))
133
b1770a0a
K
134 await testImage(servers[0].url, 'video_import_thumbnail', res.body.video.thumbnailPath)
135 await testImage(servers[0].url, 'video_import_preview', res.body.video.previewPath)
ba6e9e8f 136
a2470c9f
C
137 const bodyCaptions = await servers[0].captionsCommand.listVideoCaptions({ videoId: res.body.video.id })
138 const videoCaptions = bodyCaptions.data
ba6e9e8f 139 expect(videoCaptions).to.have.lengthOf(2)
140
652c6416
C
141 const enCaption = videoCaptions.find(caption => caption.language.id === 'en')
142 expect(enCaption).to.exist
143 expect(enCaption.language.label).to.equal('English')
53c06121 144 expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`))
ba6e9e8f 145 await testCaptionFile(servers[0].url, enCaption.captionPath, `WEBVTT
652c6416
C
146Kind: captions
147Language: en
ba6e9e8f 148
652c6416
C
14900:00:01.600 --> 00:00:04.200
150English (US)
ba6e9e8f 151
652c6416
C
15200:00:05.900 --> 00:00:07.999
153This is a subtitle in American English
ba6e9e8f 154
652c6416
C
15500:00:10.000 --> 00:00:14.000
156Adding subtitles is very easy to do`)
ba6e9e8f 157
652c6416
C
158 const frCaption = videoCaptions.find(caption => caption.language.id === 'fr')
159 expect(frCaption).to.exist
160 expect(frCaption.language.label).to.equal('French')
53c06121 161 expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`))
ba6e9e8f 162 await testCaptionFile(servers[0].url, frCaption.captionPath, `WEBVTT
652c6416
C
163Kind: captions
164Language: fr
ba6e9e8f 165
652c6416
C
16600:00:01.600 --> 00:00:04.200
167Français (FR)
ba6e9e8f 168
652c6416
C
16900:00:05.900 --> 00:00:07.999
170C'est un sous-titre français
ba6e9e8f 171
652c6416
C
17200:00:10.000 --> 00:00:14.000
173Ajouter un sous-titre est vraiment facile`)
3e17515e
C
174 }
175
176 {
177 const attributes = immutableAssign(baseAttributes, {
178 magnetUri: getMagnetURI(),
179 description: 'this is a super torrent description',
180 tags: [ 'tag_torrent1', 'tag_torrent2' ]
181 })
182 const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
183 expect(res.body.video.name).to.equal('super peertube2 video')
184 }
185
186 {
187 const attributes = immutableAssign(baseAttributes, {
9a7fd960 188 torrentfile: 'video-720p.torrent' as any,
3e17515e
C
189 description: 'this is a super torrent description',
190 tags: [ 'tag_torrent1', 'tag_torrent2' ]
191 })
192 const res = await importVideo(servers[0].url, servers[0].accessToken, attributes)
193 expect(res.body.video.name).to.equal('你好 世界 720p.mp4')
194 }
590fb506
C
195 })
196
3e17515e
C
197 it('Should list the videos to import in my videos on server 1', async function () {
198 const res = await getMyVideos(servers[0].url, servers[0].accessToken, 0, 5, 'createdAt')
590fb506 199
3e17515e 200 expect(res.body.total).to.equal(3)
590fb506
C
201
202 const videos = res.body.data
3e17515e 203 expect(videos).to.have.lengthOf(3)
590fb506 204 expect(videos[0].name).to.equal('small video - youtube')
3e17515e
C
205 expect(videos[1].name).to.equal('super peertube2 video')
206 expect(videos[2].name).to.equal('你好 世界 720p.mp4')
590fb506
C
207 })
208
3e17515e
C
209 it('Should list the videos to import in my imports on server 1', async function () {
210 const res = await getMyVideoImports(servers[0].url, servers[0].accessToken, '-createdAt')
211
212 expect(res.body.total).to.equal(3)
213 const videoImports: VideoImport[] = res.body.data
214 expect(videoImports).to.have.lengthOf(3)
215
216 expect(videoImports[2].targetUrl).to.equal(getYoutubeVideoUrl())
217 expect(videoImports[2].magnetUri).to.be.null
218 expect(videoImports[2].torrentName).to.be.null
219 expect(videoImports[2].video.name).to.equal('small video - youtube')
590fb506 220
3e17515e
C
221 expect(videoImports[1].targetUrl).to.be.null
222 expect(videoImports[1].magnetUri).to.equal(getMagnetURI())
223 expect(videoImports[1].torrentName).to.be.null
224 expect(videoImports[1].video.name).to.equal('super peertube2 video')
590fb506 225
3e17515e
C
226 expect(videoImports[0].targetUrl).to.be.null
227 expect(videoImports[0].magnetUri).to.be.null
228 expect(videoImports[0].torrentName).to.equal('video-720p.torrent')
229 expect(videoImports[0].video.name).to.equal('你好 世界 720p.mp4')
590fb506
C
230 })
231
3e17515e 232 it('Should have the video listed on the two instances', async function () {
454c20fa 233 this.timeout(120_000)
590fb506
C
234
235 await waitJobs(servers)
236
237 for (const server of servers) {
238 const res = await getVideosList(server.url)
3e17515e
C
239 expect(res.body.total).to.equal(3)
240 expect(res.body.data).to.have.lengthOf(3)
590fb506 241
3e17515e 242 const [ videoHttp, videoMagnet, videoTorrent ] = res.body.data
a2470c9f 243 await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
590fb506
C
244 }
245 })
246
247 it('Should import a video on server 2 with some fields', async function () {
454c20fa 248 this.timeout(60_000)
590fb506
C
249
250 const attributes = {
251 targetUrl: getYoutubeVideoUrl(),
3e17515e 252 channelId: channelIdServer2,
590fb506
C
253 privacy: VideoPrivacy.PUBLIC,
254 category: 10,
255 licence: 7,
256 language: 'en',
257 name: 'my super name',
258 description: 'my super description',
259 tags: [ 'supertag1', 'supertag2' ]
260 }
261 const res = await importVideo(servers[1].url, servers[1].accessToken, attributes)
262 expect(res.body.video.name).to.equal('my super name')
263 })
264
3e17515e 265 it('Should have the videos listed on the two instances', async function () {
454c20fa 266 this.timeout(120_000)
590fb506
C
267
268 await waitJobs(servers)
269
270 for (const server of servers) {
271 const res = await getVideosList(server.url)
3e17515e
C
272 expect(res.body.total).to.equal(4)
273 expect(res.body.data).to.have.lengthOf(4)
590fb506 274
a2470c9f 275 await checkVideoServer2(server, res.body.data[0].uuid)
3e17515e 276
a1587156 277 const [ , videoHttp, videoMagnet, videoTorrent ] = res.body.data
a2470c9f 278 await checkVideosServer1(server, videoHttp.uuid, videoMagnet.uuid, videoTorrent.uuid)
3e17515e
C
279 }
280 })
281
282 it('Should import a video that will be transcoded', async function () {
454c20fa 283 this.timeout(120_000)
3e17515e
C
284
285 const attributes = {
286 name: 'transcoded video',
287 magnetUri: getMagnetURI(),
288 channelId: channelIdServer2,
289 privacy: VideoPrivacy.PUBLIC
290 }
291 const res = await importVideo(servers[1].url, servers[1].accessToken, attributes)
292 const videoUUID = res.body.video.uuid
293
294 await waitJobs(servers)
295
296 for (const server of servers) {
297 const res = await getVideo(server.url, videoUUID)
298 const video: VideoDetails = res.body
299
300 expect(video.name).to.equal('transcoded video')
301 expect(video.files).to.have.lengthOf(4)
590fb506
C
302 }
303 })
304
454c20fa
RK
305 it('Should import no HDR version on a HDR video', async function () {
306 this.timeout(120_000)
307
308 const config = {
309 transcoding: {
310 enabled: true,
311 resolutions: {
312 '240p': false,
313 '360p': false,
314 '480p': false,
315 '720p': false,
316 '1080p': true, // the resulting resolution shouldn't be higher than this, and not vp9.2/av01
317 '1440p': false,
318 '2160p': false
319 },
320 webtorrent: { enabled: true },
321 hls: { enabled: false }
322 },
323 import: {
324 videos: {
325 http: {
326 enabled: true
327 },
328 torrent: {
329 enabled: true
330 }
331 }
332 }
333 }
65e6e260 334 await servers[0].configCommand.updateCustomSubConfig({ newConfig: config })
454c20fa
RK
335
336 const attributes = {
337 name: 'hdr video',
338 targetUrl: getYoutubeHDRVideoUrl(),
339 channelId: channelIdServer1,
340 privacy: VideoPrivacy.PUBLIC
341 }
342 const res1 = await importVideo(servers[0].url, servers[0].accessToken, attributes)
343 const videoUUID = res1.body.video.uuid
344
345 await waitJobs(servers)
346
347 // test resolution
348 const res2 = await getVideo(servers[0].url, videoUUID)
349 const video: VideoDetails = res2.body
350 expect(video.name).to.equal('hdr video')
351 const maxResolution = Math.max.apply(Math, video.files.map(function (o) { return o.resolution.id }))
352 expect(maxResolution, 'expected max resolution not met').to.equals(VideoResolution.H_1080P)
353 })
354
7c3b7976
C
355 after(async function () {
356 await cleanupTests(servers)
590fb506
C
357 })
358})