aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/optimize-old-videos.ts8
-rw-r--r--server/tests/api/videos/video-transcoder.ts25
-rw-r--r--server/tests/cli/index.ts1
-rw-r--r--server/tests/cli/optimize-old-videos.ts120
-rw-r--r--server/tests/utils/miscs/miscs.ts31
5 files changed, 161 insertions, 24 deletions
diff --git a/scripts/optimize-old-videos.ts b/scripts/optimize-old-videos.ts
index 02026b3da..c93f82316 100644
--- a/scripts/optimize-old-videos.ts
+++ b/scripts/optimize-old-videos.ts
@@ -1,8 +1,10 @@
1import { VIDEO_TRANSCODING_FPS } from '../server/initializers/constants' 1import { CONFIG, VIDEO_TRANSCODING_FPS } from '../server/initializers/constants'
2import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../server/helpers/ffmpeg-utils' 2import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../server/helpers/ffmpeg-utils'
3import { getMaxBitrate } from '../shared/models/videos' 3import { getMaxBitrate } from '../shared/models/videos'
4import { VideoModel } from '../server/models/video/video' 4import { VideoModel } from '../server/models/video/video'
5import { optimizeVideofile } from '../server/lib/video-transcoding' 5import { optimizeVideofile } from '../server/lib/video-transcoding'
6import { initDatabaseModels } from '../server/initializers'
7import { join } from 'path'
6 8
7run() 9run()
8 .then(() => process.exit(0)) 10 .then(() => process.exit(0))
@@ -12,11 +14,13 @@ run()
12 }) 14 })
13 15
14async function run () { 16async function run () {
17 await initDatabaseModels(true)
18
15 const localVideos = await VideoModel.listLocal() 19 const localVideos = await VideoModel.listLocal()
16 20
17 for (const video of localVideos) { 21 for (const video of localVideos) {
18 for (const file of video.VideoFiles) { 22 for (const file of video.VideoFiles) {
19 const inputPath = video.getVideoFilename(file) 23 const inputPath = join(CONFIG.STORAGE.VIDEOS_DIR, video.getVideoFilename(file))
20 24
21 const [ videoBitrate, fps, resolution ] = await Promise.all([ 25 const [ videoBitrate, fps, resolution ] = await Promise.all([
22 getVideoFileBitrate(inputPath), 26 getVideoFileBitrate(inputPath),
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index 0a567873c..85795d2ed 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -18,7 +18,8 @@ import {
18 ServerInfo, 18 ServerInfo,
19 setAccessTokensToServers, 19 setAccessTokensToServers,
20 uploadVideo, 20 uploadVideo,
21 webtorrentAdd 21 webtorrentAdd,
22 generateHighBitrateVideo
22} from '../../utils' 23} from '../../utils'
23import { join } from 'path' 24import { join } from 'path'
24import { waitJobs } from '../../utils/server/jobs' 25import { waitJobs } from '../../utils/server/jobs'
@@ -283,29 +284,13 @@ describe('Test video transcoding', function () {
283 } 284 }
284 }) 285 })
285 286
286 const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
287 it('Should respect maximum bitrate values', async function () { 287 it('Should respect maximum bitrate values', async function () {
288 this.timeout(160000) 288 this.timeout(160000)
289 289
290 let tempFixturePath: string
291
290 { 292 {
291 const exists = await pathExists(tempFixturePath) 293 tempFixturePath = await generateHighBitrateVideo()
292 if (!exists) {
293
294 // Generate a random, high bitrate video on the fly, so we don't have to include
295 // a large file in the repo. The video needs to have a certain minimum length so
296 // that FFmpeg properly applies bitrate limits.
297 // https://stackoverflow.com/a/15795112
298 await new Promise<void>(async (res, rej) => {
299 ffmpeg()
300 .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
301 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
302 .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
303 .output(tempFixturePath)
304 .on('error', rej)
305 .on('end', res)
306 .run()
307 })
308 }
309 294
310 const bitrate = await getVideoFileBitrate(tempFixturePath) 295 const bitrate = await getVideoFileBitrate(tempFixturePath)
311 expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS)) 296 expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS))
diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts
index 6201314ce..8f8acf56c 100644
--- a/server/tests/cli/index.ts
+++ b/server/tests/cli/index.ts
@@ -4,3 +4,4 @@ import './create-transcoding-job'
4import './peertube' 4import './peertube'
5import './reset-password' 5import './reset-password'
6import './update-host' 6import './update-host'
7import './update-host'
diff --git a/server/tests/cli/optimize-old-videos.ts b/server/tests/cli/optimize-old-videos.ts
new file mode 100644
index 000000000..66dd39cce
--- /dev/null
+++ b/server/tests/cli/optimize-old-videos.ts
@@ -0,0 +1,120 @@
1/* tslint:disable:no-unused-expression */
2
3import 'mocha'
4import * as chai from 'chai'
5import { getMaxBitrate, Video, VideoDetails, VideoResolution } from '../../../shared/models/videos'
6import {
7 doubleFollow,
8 execCLI,
9 flushAndRunMultipleServers,
10 flushTests, generateHighBitrateVideo,
11 getEnvCli,
12 getVideo,
13 getVideosList,
14 killallServers, root,
15 ServerInfo,
16 setAccessTokensToServers,
17 uploadVideo, viewVideo, wait
18} from '../utils'
19import { waitJobs } from '../utils/server/jobs'
20import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '../../helpers/ffmpeg-utils'
21import { VIDEO_TRANSCODING_FPS } from '../../initializers'
22import { join } from 'path'
23
24const expect = chai.expect
25
26describe('Test optimize old videos', function () {
27 let servers: ServerInfo[] = []
28 let video1UUID: string
29 let video2UUID: string
30
31 before(async function () {
32 this.timeout(200000)
33
34 await flushTests()
35
36 // Run server 2 to have transcoding enabled
37 servers = await flushAndRunMultipleServers(2)
38 await setAccessTokensToServers(servers)
39
40 await doubleFollow(servers[0], servers[1])
41
42 let tempFixturePath: string
43
44 {
45 tempFixturePath = await generateHighBitrateVideo()
46
47 const bitrate = await getVideoFileBitrate(tempFixturePath)
48 expect(bitrate).to.be.above(getMaxBitrate(VideoResolution.H_1080P, 60, VIDEO_TRANSCODING_FPS))
49 }
50
51 // Upload two videos for our needs
52 const res1 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video1', fixture: tempFixturePath })
53 video1UUID = res1.body.video.uuid
54 const res2 = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video2', fixture: tempFixturePath })
55 video2UUID = res2.body.video.uuid
56
57 await waitJobs(servers)
58 })
59
60 it('Should have two video files on each server', async function () {
61 this.timeout(30000)
62
63 for (const server of servers) {
64 const res = await getVideosList(server.url)
65 const videos = res.body.data
66 expect(videos).to.have.lengthOf(2)
67
68 for (const video of videos) {
69 const res2 = await getVideo(server.url, video.uuid)
70 const videoDetail: VideoDetails = res2.body
71 expect(videoDetail.files).to.have.lengthOf(1)
72 }
73 }
74 })
75
76 it('Should run optimize script', async function () {
77 this.timeout(120000)
78
79 const env = getEnvCli(servers[0])
80 await execCLI(`${env} npm run optimize-old-videos`)
81
82 await waitJobs(servers)
83
84 for (const server of servers) {
85 const res = await getVideosList(server.url)
86 const videos: Video[] = res.body.data
87
88 expect(videos).to.have.lengthOf(2)
89
90 for (const video of videos) {
91 await viewVideo(server.url, video.uuid)
92
93 // Refresh video
94 await waitJobs(servers)
95 await wait(5000)
96 await waitJobs(servers)
97
98 const res2 = await getVideo(server.url, video.uuid)
99 const videosDetails: VideoDetails = res2.body
100
101 expect(videosDetails.files).to.have.lengthOf(1)
102 const file = videosDetails.files[0]
103
104 expect(file.size).to.be.below(5000000)
105
106 const path = join(root(), 'test1', 'videos', video.uuid + '-' + file.resolution.id + '.mp4')
107 const bitrate = await getVideoFileBitrate(path)
108 const fps = await getVideoFileFPS(path)
109 const resolution = await getVideoFileResolution(path)
110
111 expect(resolution.videoFileResolution).to.equal(file.resolution.id)
112 expect(bitrate).to.be.below(getMaxBitrate(resolution.videoFileResolution, fps, VIDEO_TRANSCODING_FPS))
113 }
114 }
115 })
116
117 after(async function () {
118 killallServers(servers)
119 })
120})
diff --git a/server/tests/utils/miscs/miscs.ts b/server/tests/utils/miscs/miscs.ts
index d20fa96b8..589daa420 100644
--- a/server/tests/utils/miscs/miscs.ts
+++ b/server/tests/utils/miscs/miscs.ts
@@ -4,7 +4,8 @@ import * as chai from 'chai'
4import { isAbsolute, join } from 'path' 4import { isAbsolute, join } from 'path'
5import * as request from 'supertest' 5import * as request from 'supertest'
6import * as WebTorrent from 'webtorrent' 6import * as WebTorrent from 'webtorrent'
7import { readFile } from 'fs-extra' 7import { pathExists, readFile } from 'fs-extra'
8import * as ffmpeg from 'fluent-ffmpeg'
8 9
9const expect = chai.expect 10const expect = chai.expect
10let webtorrent = new WebTorrent() 11let webtorrent = new WebTorrent()
@@ -61,6 +62,31 @@ function buildAbsoluteFixturePath (path: string, customTravisPath = false) {
61 return join(__dirname, '..', '..', 'fixtures', path) 62 return join(__dirname, '..', '..', 'fixtures', path)
62} 63}
63 64
65async function generateHighBitrateVideo () {
66 const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
67
68 const exists = await pathExists(tempFixturePath)
69 if (!exists) {
70
71 // Generate a random, high bitrate video on the fly, so we don't have to include
72 // a large file in the repo. The video needs to have a certain minimum length so
73 // that FFmpeg properly applies bitrate limits.
74 // https://stackoverflow.com/a/15795112
75 return new Promise<string>(async (res, rej) => {
76 ffmpeg()
77 .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
78 .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
79 .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
80 .output(tempFixturePath)
81 .on('error', rej)
82 .on('end', () => res(tempFixturePath))
83 .run()
84 })
85 }
86
87 return tempFixturePath
88}
89
64// --------------------------------------------------------------------------- 90// ---------------------------------------------------------------------------
65 91
66export { 92export {
@@ -70,5 +96,6 @@ export {
70 immutableAssign, 96 immutableAssign,
71 testImage, 97 testImage,
72 buildAbsoluteFixturePath, 98 buildAbsoluteFixturePath,
73 root 99 root,
100 generateHighBitrateVideo
74} 101}