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