aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-11-22 10:45:03 +0100
committerChocobozzz <me@florianbigard.com>2019-11-25 10:59:47 +0100
commitdee6fe1e4f5c024fd387e8c2b306c174b24aa8b3 (patch)
tree50e5a19fc99b30c0d230829d20d8185e0d0f4069
parent5a71acd2547c098657ae6e0e31e0862094585088 (diff)
downloadPeerTube-dee6fe1e4f5c024fd387e8c2b306c174b24aa8b3.tar.gz
PeerTube-dee6fe1e4f5c024fd387e8c2b306c174b24aa8b3.tar.zst
PeerTube-dee6fe1e4f5c024fd387e8c2b306c174b24aa8b3.zip
Add ability to generate HLS in CLI
-rwxr-xr-xscripts/create-transcoding-job.ts45
-rw-r--r--server/tests/cli/create-transcoding-job.ts133
2 files changed, 155 insertions, 23 deletions
diff --git a/scripts/create-transcoding-job.ts b/scripts/create-transcoding-job.ts
index 67a270a86..27170299d 100755
--- a/scripts/create-transcoding-job.ts
+++ b/scripts/create-transcoding-job.ts
@@ -6,10 +6,12 @@ import { VideoModel } from '../server/models/video/video'
6import { initDatabaseModels } from '../server/initializers' 6import { initDatabaseModels } from '../server/initializers'
7import { JobQueue } from '../server/lib/job-queue' 7import { JobQueue } from '../server/lib/job-queue'
8import { VideoTranscodingPayload } from '../server/lib/job-queue/handlers/video-transcoding' 8import { VideoTranscodingPayload } from '../server/lib/job-queue/handlers/video-transcoding'
9import { computeResolutionsToTranscode } from '@server/helpers/ffmpeg-utils'
9 10
10program 11program
11 .option('-v, --video [videoUUID]', 'Video UUID') 12 .option('-v, --video [videoUUID]', 'Video UUID')
12 .option('-r, --resolution [resolution]', 'Video resolution (integer)') 13 .option('-r, --resolution [resolution]', 'Video resolution (integer)')
14 .option('--generate-hls', 'Generate HLS playlist')
13 .parse(process.argv) 15 .parse(process.argv)
14 16
15if (program['video'] === undefined) { 17if (program['video'] === undefined) {
@@ -32,14 +34,45 @@ run()
32async function run () { 34async function run () {
33 await initDatabaseModels(true) 35 await initDatabaseModels(true)
34 36
35 const video = await VideoModel.loadByUUID(program['video']) 37 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(program['video'])
36 if (!video) throw new Error('Video not found.') 38 if (!video) throw new Error('Video not found.')
37 39
38 const dataInput: VideoTranscodingPayload = program.resolution !== undefined 40 const dataInput: VideoTranscodingPayload[] = []
39 ? { type: 'new-resolution' as 'new-resolution', videoUUID: video.uuid, isNewVideo: false, resolution: program.resolution } 41 const { videoFileResolution } = await video.getMaxQualityResolution()
40 : { type: 'optimize' as 'optimize', videoUUID: video.uuid, isNewVideo: false } 42
43 if (program.generateHls) {
44 const resolutionsEnabled = program.resolution
45 ? [ program.resolution ]
46 : computeResolutionsToTranscode(videoFileResolution).concat([ videoFileResolution ])
47
48 for (const resolution of resolutionsEnabled) {
49 dataInput.push({
50 type: 'hls',
51 videoUUID: video.uuid,
52 resolution,
53 isPortraitMode: false,
54 copyCodecs: false
55 })
56 }
57 } else if (program.resolution !== undefined) {
58 dataInput.push({
59 type: 'new-resolution' as 'new-resolution',
60 videoUUID: video.uuid,
61 isNewVideo: false,
62 resolution: program.resolution
63 })
64 } else {
65 dataInput.push({
66 type: 'optimize' as 'optimize',
67 videoUUID: video.uuid,
68 isNewVideo: false
69 })
70 }
41 71
42 await JobQueue.Instance.init() 72 await JobQueue.Instance.init()
43 await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) 73
44 console.log('Transcoding job for video %s created.', video.uuid) 74 for (const d of dataInput) {
75 await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: d })
76 console.log('Transcoding job for video %s created.', video.uuid)
77 }
45} 78}
diff --git a/server/tests/cli/create-transcoding-job.ts b/server/tests/cli/create-transcoding-job.ts
index 1c0e10066..7897ff1b3 100644
--- a/server/tests/cli/create-transcoding-job.ts
+++ b/server/tests/cli/create-transcoding-job.ts
@@ -14,7 +14,7 @@ import {
14 getVideosList, 14 getVideosList,
15 killallServers, 15 killallServers,
16 ServerInfo, 16 ServerInfo,
17 setAccessTokensToServers, 17 setAccessTokensToServers, updateCustomSubConfig,
18 uploadVideo, wait 18 uploadVideo, wait
19} from '../../../shared/extra-utils' 19} from '../../../shared/extra-utils'
20import { waitJobs } from '../../../shared/extra-utils/server/jobs' 20import { waitJobs } from '../../../shared/extra-utils/server/jobs'
@@ -23,8 +23,24 @@ const expect = chai.expect
23 23
24describe('Test create transcoding jobs', function () { 24describe('Test create transcoding jobs', function () {
25 let servers: ServerInfo[] = [] 25 let servers: ServerInfo[] = []
26 let video1UUID: string 26 let videosUUID: string[] = []
27 let video2UUID: string 27
28 const config = {
29 transcoding: {
30 enabled: false,
31 resolutions: {
32 '240p': true,
33 '360p': true,
34 '480p': true,
35 '720p': true,
36 '1080p': true,
37 '2160p': true
38 },
39 hls: {
40 enabled: false
41 }
42 }
43 }
28 44
29 before(async function () { 45 before(async function () {
30 this.timeout(60000) 46 this.timeout(60000)
@@ -33,13 +49,14 @@ describe('Test create transcoding jobs', function () {
33 servers = await flushAndRunMultipleServers(2) 49 servers = await flushAndRunMultipleServers(2)
34 await setAccessTokensToServers(servers) 50 await setAccessTokensToServers(servers)
35 51
52 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
53
36 await doubleFollow(servers[0], servers[1]) 54 await doubleFollow(servers[0], servers[1])
37 55
38 // Upload two videos for our needs 56 for (let i = 1; i <= 5; i++) {
39 const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1' }) 57 const res = await uploadVideo(servers[ 0 ].url, servers[ 0 ].accessToken, { name: 'video' + i })
40 video1UUID = res1.body.video.uuid 58 videosUUID.push(res.body.video.uuid)
41 const res2 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video2' }) 59 }
42 video2UUID = res2.body.video.uuid
43 60
44 await waitJobs(servers) 61 await waitJobs(servers)
45 }) 62 })
@@ -50,12 +67,13 @@ describe('Test create transcoding jobs', function () {
50 for (const server of servers) { 67 for (const server of servers) {
51 const res = await getVideosList(server.url) 68 const res = await getVideosList(server.url)
52 const videos = res.body.data 69 const videos = res.body.data
53 expect(videos).to.have.lengthOf(2) 70 expect(videos).to.have.lengthOf(videosUUID.length)
54 71
55 for (const video of videos) { 72 for (const video of videos) {
56 const res2 = await getVideo(server.url, video.uuid) 73 const res2 = await getVideo(server.url, video.uuid)
57 const videoDetail: VideoDetails = res2.body 74 const videoDetail: VideoDetails = res2.body
58 expect(videoDetail.files).to.have.lengthOf(1) 75 expect(videoDetail.files).to.have.lengthOf(1)
76 expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
59 } 77 }
60 } 78 }
61 }) 79 })
@@ -64,14 +82,13 @@ describe('Test create transcoding jobs', function () {
64 this.timeout(60000) 82 this.timeout(60000)
65 83
66 const env = getEnvCli(servers[0]) 84 const env = getEnvCli(servers[0])
67 await execCLI(`${env} npm run create-transcoding-job -- -v ${video2UUID}`) 85 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[1]}`)
68 86
69 await waitJobs(servers) 87 await waitJobs(servers)
70 88
71 for (const server of servers) { 89 for (const server of servers) {
72 const res = await getVideosList(server.url) 90 const res = await getVideosList(server.url)
73 const videos = res.body.data 91 const videos = res.body.data
74 expect(videos).to.have.lengthOf(2)
75 92
76 let infoHashes: { [ id: number ]: string } 93 let infoHashes: { [ id: number ]: string }
77 94
@@ -79,8 +96,9 @@ describe('Test create transcoding jobs', function () {
79 const res2 = await getVideo(server.url, video.uuid) 96 const res2 = await getVideo(server.url, video.uuid)
80 const videoDetail: VideoDetails = res2.body 97 const videoDetail: VideoDetails = res2.body
81 98
82 if (video.uuid === video2UUID) { 99 if (video.uuid === videosUUID[1]) {
83 expect(videoDetail.files).to.have.lengthOf(4) 100 expect(videoDetail.files).to.have.lengthOf(4)
101 expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
84 102
85 if (!infoHashes) { 103 if (!infoHashes) {
86 infoHashes = {} 104 infoHashes = {}
@@ -96,6 +114,7 @@ describe('Test create transcoding jobs', function () {
96 } 114 }
97 } else { 115 } else {
98 expect(videoDetail.files).to.have.lengthOf(1) 116 expect(videoDetail.files).to.have.lengthOf(1)
117 expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
99 } 118 }
100 } 119 }
101 } 120 }
@@ -105,23 +124,103 @@ describe('Test create transcoding jobs', function () {
105 this.timeout(60000) 124 this.timeout(60000)
106 125
107 const env = getEnvCli(servers[0]) 126 const env = getEnvCli(servers[0])
108 await execCLI(`${env} npm run create-transcoding-job -- -v ${video1UUID} -r 480`) 127 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[0]} -r 480`)
109 128
110 await waitJobs(servers) 129 await waitJobs(servers)
111 130
112 for (const server of servers) { 131 for (const server of servers) {
113 const res = await getVideosList(server.url) 132 const res = await getVideosList(server.url)
114 const videos = res.body.data 133 const videos = res.body.data
115 expect(videos).to.have.lengthOf(2) 134 expect(videos).to.have.lengthOf(videosUUID.length)
116 135
117 const res2 = await getVideo(server.url, video1UUID) 136 const res2 = await getVideo(server.url, videosUUID[0])
118 const videoDetail: VideoDetails = res2.body 137 const videoDetail: VideoDetails = res2.body
119 138
120 expect(videoDetail.files).to.have.lengthOf(2) 139 expect(videoDetail.files).to.have.lengthOf(2)
121
122 expect(videoDetail.files[0].resolution.id).to.equal(720) 140 expect(videoDetail.files[0].resolution.id).to.equal(720)
123
124 expect(videoDetail.files[1].resolution.id).to.equal(480) 141 expect(videoDetail.files[1].resolution.id).to.equal(480)
142
143 expect(videoDetail.streamingPlaylists).to.have.lengthOf(0)
144 }
145 })
146
147 it('Should generate an HLS resolution', async function () {
148 this.timeout(120000)
149
150 const env = getEnvCli(servers[0])
151 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
152
153 await waitJobs(servers)
154
155 for (const server of servers) {
156 const res = await getVideo(server.url, videosUUID[2])
157 const videoDetail: VideoDetails = res.body
158
159 expect(videoDetail.files).to.have.lengthOf(1)
160 expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
161
162 const files = videoDetail.streamingPlaylists[0].files
163 expect(files).to.have.lengthOf(1)
164 expect(files[0].resolution.id).to.equal(480)
165 }
166 })
167
168 it('Should not duplicate an HLS resolution', async function () {
169 this.timeout(120000)
170
171 const env = getEnvCli(servers[0])
172 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[2]} --generate-hls -r 480`)
173
174 await waitJobs(servers)
175
176 for (const server of servers) {
177 const res = await getVideo(server.url, videosUUID[2])
178 const videoDetail: VideoDetails = res.body
179
180 const files = videoDetail.streamingPlaylists[0].files
181 expect(files).to.have.lengthOf(1)
182 expect(files[0].resolution.id).to.equal(480)
183 }
184 })
185
186 it('Should generate all HLS resolutions', async function () {
187 this.timeout(120000)
188
189 const env = getEnvCli(servers[0])
190 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[3]} --generate-hls`)
191
192 await waitJobs(servers)
193
194 for (const server of servers) {
195 const res = await getVideo(server.url, videosUUID[3])
196 const videoDetail: VideoDetails = res.body
197
198 expect(videoDetail.files).to.have.lengthOf(1)
199 expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
200
201 const files = videoDetail.streamingPlaylists[0].files
202 expect(files).to.have.lengthOf(4)
203 }
204 })
205
206 it('Should optimize the video file and generate HLS videos if enabled in config', async function () {
207 this.timeout(120000)
208
209 config.transcoding.hls.enabled = true
210 await updateCustomSubConfig(servers[0].url, servers[0].accessToken, config)
211
212 const env = getEnvCli(servers[0])
213 await execCLI(`${env} npm run create-transcoding-job -- -v ${videosUUID[4]}`)
214
215 await waitJobs(servers)
216
217 for (const server of servers) {
218 const res = await getVideo(server.url, videosUUID[4])
219 const videoDetail: VideoDetails = res.body
220
221 expect(videoDetail.files).to.have.lengthOf(4)
222 expect(videoDetail.streamingPlaylists).to.have.lengthOf(1)
223 expect(videoDetail.streamingPlaylists[0].files).to.have.lengthOf(4)
125 } 224 }
126 }) 225 })
127 226