Handle higher FPS for high resolution (test)
[oweals/peertube.git] / server / tests / api / videos / video-transcoder.ts
1 /* tslint:disable:no-unused-expression */
2
3 import * as chai from 'chai'
4 import 'mocha'
5 import { VideoDetails, VideoState } from '../../../../shared/models/videos'
6 import { getVideoFileFPS } from '../../../helpers/ffmpeg-utils'
7 import {
8   doubleFollow,
9   flushAndRunMultipleServers,
10   getMyVideos,
11   getVideo,
12   getVideosList,
13   killallServers,
14   root,
15   ServerInfo,
16   setAccessTokensToServers,
17   uploadVideo,
18   webtorrentAdd
19 } from '../../utils'
20 import { join } from 'path'
21 import { waitJobs } from '../../utils/server/jobs'
22
23 const expect = chai.expect
24
25 describe('Test video transcoding', function () {
26   let servers: ServerInfo[] = []
27
28   before(async function () {
29     this.timeout(30000)
30
31     // Run servers
32     servers = await flushAndRunMultipleServers(2)
33
34     await setAccessTokensToServers(servers)
35   })
36
37   it('Should not transcode video on server 1', async function () {
38     this.timeout(60000)
39
40     const videoAttributes = {
41       name: 'my super name for server 1',
42       description: 'my super description for server 1',
43       fixture: 'video_short.webm'
44     }
45     await uploadVideo(servers[0].url, servers[0].accessToken, videoAttributes)
46
47     await waitJobs(servers)
48
49     const res = await getVideosList(servers[0].url)
50     const video = res.body.data[0]
51
52     const res2 = await getVideo(servers[0].url, video.id)
53     const videoDetails = res2.body
54     expect(videoDetails.files).to.have.lengthOf(1)
55
56     const magnetUri = videoDetails.files[0].magnetUri
57     expect(magnetUri).to.match(/\.webm/)
58
59     const torrent = await webtorrentAdd(magnetUri)
60     expect(torrent.files).to.be.an('array')
61     expect(torrent.files.length).to.equal(1)
62     expect(torrent.files[0].path).match(/\.webm$/)
63   })
64
65   it('Should transcode video on server 2', async function () {
66     this.timeout(60000)
67
68     const videoAttributes = {
69       name: 'my super name for server 2',
70       description: 'my super description for server 2',
71       fixture: 'video_short.webm'
72     }
73     await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
74
75     await waitJobs(servers)
76
77     const res = await getVideosList(servers[1].url)
78
79     const video = res.body.data[0]
80     const res2 = await getVideo(servers[1].url, video.id)
81     const videoDetails = res2.body
82
83     expect(videoDetails.files).to.have.lengthOf(4)
84
85     const magnetUri = videoDetails.files[0].magnetUri
86     expect(magnetUri).to.match(/\.mp4/)
87
88     const torrent = await webtorrentAdd(magnetUri)
89     expect(torrent.files).to.be.an('array')
90     expect(torrent.files.length).to.equal(1)
91     expect(torrent.files[0].path).match(/\.mp4$/)
92   })
93
94   it('Should transcode a 60 FPS video', async function () {
95     this.timeout(60000)
96
97     const videoAttributes = {
98       name: 'my super 30fps name for server 2',
99       description: 'my super 30fps description for server 2',
100       fixture: '60fps_720p_small.mp4'
101     }
102     await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
103
104     await waitJobs(servers)
105
106     const res = await getVideosList(servers[1].url)
107
108     const video = res.body.data[0]
109     const res2 = await getVideo(servers[1].url, video.id)
110     const videoDetails: VideoDetails = res2.body
111
112     expect(videoDetails.files).to.have.lengthOf(4)
113     expect(videoDetails.files[0].fps).to.be.above(58).and.below(62)
114     expect(videoDetails.files[1].fps).to.be.below(31)
115     expect(videoDetails.files[2].fps).to.be.below(31)
116     expect(videoDetails.files[3].fps).to.be.below(31)
117
118     for (const resolution of [ '240', '360', '480' ]) {
119       const path = join(root(), 'test2', 'videos', video.uuid + '-' + resolution + '.mp4')
120       const fps = await getVideoFileFPS(path)
121
122       expect(fps).to.be.below(31)
123     }
124
125     const path = join(root(), 'test2', 'videos', video.uuid + '-720.mp4')
126     const fps = await getVideoFileFPS(path)
127
128     expect(fps).to.be.above(58).and.below(62)
129   })
130
131   it('Should wait transcoding before publishing the video', async function () {
132     this.timeout(80000)
133
134     await doubleFollow(servers[0], servers[1])
135
136     await waitJobs(servers)
137
138     {
139       // Upload the video, but wait transcoding
140       const videoAttributes = {
141         name: 'waiting video',
142         fixture: 'video_short1.webm',
143         waitTranscoding: true
144       }
145       const resVideo = await uploadVideo(servers[ 1 ].url, servers[ 1 ].accessToken, videoAttributes)
146       const videoId = resVideo.body.video.uuid
147
148       // Should be in transcode state
149       const { body } = await getVideo(servers[ 1 ].url, videoId)
150       expect(body.name).to.equal('waiting video')
151       expect(body.state.id).to.equal(VideoState.TO_TRANSCODE)
152       expect(body.state.label).to.equal('To transcode')
153       expect(body.waitTranscoding).to.be.true
154
155       // Should have my video
156       const resMyVideos = await getMyVideos(servers[1].url, servers[1].accessToken, 0, 10)
157       const videoToFindInMine = resMyVideos.body.data.find(v => v.name === 'waiting video')
158       expect(videoToFindInMine).not.to.be.undefined
159       expect(videoToFindInMine.state.id).to.equal(VideoState.TO_TRANSCODE)
160       expect(videoToFindInMine.state.label).to.equal('To transcode')
161       expect(videoToFindInMine.waitTranscoding).to.be.true
162
163       // Should not list this video
164       const resVideos = await getVideosList(servers[1].url)
165       const videoToFindInList = resVideos.body.data.find(v => v.name === 'waiting video')
166       expect(videoToFindInList).to.be.undefined
167
168       // Server 1 should not have the video yet
169       await getVideo(servers[0].url, videoId, 404)
170     }
171
172     await waitJobs(servers)
173
174     for (const server of servers) {
175       const res = await getVideosList(server.url)
176       const videoToFind = res.body.data.find(v => v.name === 'waiting video')
177       expect(videoToFind).not.to.be.undefined
178
179       const res2 = await getVideo(server.url, videoToFind.id)
180       const videoDetails: VideoDetails = res2.body
181
182       expect(videoDetails.state.id).to.equal(VideoState.PUBLISHED)
183       expect(videoDetails.state.label).to.equal('Published')
184       expect(videoDetails.waitTranscoding).to.be.true
185     }
186   })
187
188   after(async function () {
189     killallServers(servers)
190   })
191 })