diff options
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 7 | ||||
-rw-r--r-- | server/tests/api/videos/video-transcoder.ts | 37 | ||||
-rw-r--r-- | server/tests/fixtures/low-bitrate.mp4 | bin | 0 -> 43850 bytes | |||
-rw-r--r-- | shared/extra-utils/miscs/miscs.ts | 9 | ||||
-rw-r--r-- | shared/extra-utils/server/servers.ts | 9 |
5 files changed, 59 insertions, 3 deletions
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 1d610eff2..c8d6969ff 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts | |||
@@ -674,7 +674,12 @@ async function presetH264 (command: ffmpeg.FfmpegCommand, input: string, resolut | |||
674 | // Constrained Encoding (VBV) | 674 | // Constrained Encoding (VBV) |
675 | // https://slhck.info/video/2017/03/01/rate-control.html | 675 | // https://slhck.info/video/2017/03/01/rate-control.html |
676 | // https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate | 676 | // https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate |
677 | const targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) | 677 | let targetBitrate = getTargetBitrate(resolution, fps, VIDEO_TRANSCODING_FPS) |
678 | |||
679 | // Don't transcode to an higher bitrate than the original file | ||
680 | const fileBitrate = await getVideoFileBitrate(input) | ||
681 | targetBitrate = Math.min(targetBitrate, fileBitrate) | ||
682 | |||
678 | localCommand = localCommand.outputOptions([ `-maxrate ${targetBitrate}`, `-bufsize ${targetBitrate * 2}` ]) | 683 | localCommand = localCommand.outputOptions([ `-maxrate ${targetBitrate}`, `-bufsize ${targetBitrate * 2}` ]) |
679 | 684 | ||
680 | // Keyframe interval of 2 seconds for faster seeking and resolution switching. | 685 | // Keyframe interval of 2 seconds for faster seeking and resolution switching. |
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts index a1959e1a9..a3d7b8707 100644 --- a/server/tests/api/videos/video-transcoder.ts +++ b/server/tests/api/videos/video-transcoder.ts | |||
@@ -20,6 +20,7 @@ import { | |||
20 | generateHighBitrateVideo, | 20 | generateHighBitrateVideo, |
21 | generateVideoWithFramerate, | 21 | generateVideoWithFramerate, |
22 | getMyVideos, | 22 | getMyVideos, |
23 | getServerFileSize, | ||
23 | getVideo, | 24 | getVideo, |
24 | getVideoFileMetadataUrl, | 25 | getVideoFileMetadataUrl, |
25 | getVideosList, | 26 | getVideosList, |
@@ -27,6 +28,7 @@ import { | |||
27 | root, | 28 | root, |
28 | ServerInfo, | 29 | ServerInfo, |
29 | setAccessTokensToServers, | 30 | setAccessTokensToServers, |
31 | updateCustomSubConfig, | ||
30 | uploadVideo, uploadVideoAndGetId, | 32 | uploadVideo, uploadVideoAndGetId, |
31 | waitJobs, | 33 | waitJobs, |
32 | webtorrentAdd | 34 | webtorrentAdd |
@@ -468,6 +470,41 @@ describe('Test video transcoding', function () { | |||
468 | } | 470 | } |
469 | }) | 471 | }) |
470 | 472 | ||
473 | it('Should not transcode to an higher bitrate than the original file', async function () { | ||
474 | this.timeout(160000) | ||
475 | |||
476 | const config = { | ||
477 | transcoding: { | ||
478 | enabled: true, | ||
479 | resolutions: { | ||
480 | '240p': true, | ||
481 | '360p': true, | ||
482 | '480p': true, | ||
483 | '720p': true, | ||
484 | '1080p': true | ||
485 | }, | ||
486 | webtorrent: { enabled: true }, | ||
487 | hls: { enabled: true } | ||
488 | } | ||
489 | } | ||
490 | await updateCustomSubConfig(servers[1].url, servers[1].accessToken, config) | ||
491 | |||
492 | const videoAttributes = { | ||
493 | name: 'low bitrate', | ||
494 | fixture: 'low-bitrate.mp4' | ||
495 | } | ||
496 | |||
497 | const resUpload = await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes) | ||
498 | const videoUUID = resUpload.body.video.uuid | ||
499 | |||
500 | await waitJobs(servers) | ||
501 | |||
502 | const resolutions = [ 240, 360, 480, 720, 1080 ] | ||
503 | for (const r of resolutions) { | ||
504 | expect(await getServerFileSize(servers[1], `videos/${videoUUID}-${r}.mp4`)).to.be.below(43) | ||
505 | } | ||
506 | }) | ||
507 | |||
471 | it('Should provide valid ffprobe data', async function () { | 508 | it('Should provide valid ffprobe data', async function () { |
472 | this.timeout(160000) | 509 | this.timeout(160000) |
473 | 510 | ||
diff --git a/server/tests/fixtures/low-bitrate.mp4 b/server/tests/fixtures/low-bitrate.mp4 new file mode 100644 index 000000000..69004eccc --- /dev/null +++ b/server/tests/fixtures/low-bitrate.mp4 | |||
Binary files differ | |||
diff --git a/shared/extra-utils/miscs/miscs.ts b/shared/extra-utils/miscs/miscs.ts index dfd6e28cb..3c8191ae8 100644 --- a/shared/extra-utils/miscs/miscs.ts +++ b/shared/extra-utils/miscs/miscs.ts | |||
@@ -4,7 +4,7 @@ import * as chai from 'chai' | |||
4 | import { basename, dirname, isAbsolute, join, resolve } from 'path' | 4 | import { basename, dirname, isAbsolute, join, resolve } from 'path' |
5 | import * as request from 'supertest' | 5 | import * as request from 'supertest' |
6 | import * as WebTorrent from 'webtorrent' | 6 | import * as WebTorrent from 'webtorrent' |
7 | import { ensureDir, pathExists, readFile } from 'fs-extra' | 7 | import { ensureDir, pathExists, readFile, stat } from 'fs-extra' |
8 | import * as ffmpeg from 'fluent-ffmpeg' | 8 | import * as ffmpeg from 'fluent-ffmpeg' |
9 | 9 | ||
10 | const expect = chai.expect | 10 | const expect = chai.expect |
@@ -130,6 +130,12 @@ async function generateVideoWithFramerate (fps = 60) { | |||
130 | return tempFixturePath | 130 | return tempFixturePath |
131 | } | 131 | } |
132 | 132 | ||
133 | async function getFileSize (path: string) { | ||
134 | const stats = await stat(path) | ||
135 | |||
136 | return stats.size | ||
137 | } | ||
138 | |||
133 | // --------------------------------------------------------------------------- | 139 | // --------------------------------------------------------------------------- |
134 | 140 | ||
135 | export { | 141 | export { |
@@ -138,6 +144,7 @@ export { | |||
138 | areHttpImportTestsDisabled, | 144 | areHttpImportTestsDisabled, |
139 | buildServerDirectory, | 145 | buildServerDirectory, |
140 | webtorrentAdd, | 146 | webtorrentAdd, |
147 | getFileSize, | ||
141 | immutableAssign, | 148 | immutableAssign, |
142 | testImage, | 149 | testImage, |
143 | buildAbsoluteFixturePath, | 150 | buildAbsoluteFixturePath, |
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts index 6140cebb5..a647b0eb4 100644 --- a/shared/extra-utils/server/servers.ts +++ b/shared/extra-utils/server/servers.ts | |||
@@ -6,7 +6,7 @@ import { copy, pathExists, readdir, readFile, remove } from 'fs-extra' | |||
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { randomInt } from '../../core-utils/miscs/miscs' | 7 | import { randomInt } from '../../core-utils/miscs/miscs' |
8 | import { VideoChannel } from '../../models/videos' | 8 | import { VideoChannel } from '../../models/videos' |
9 | import { root, wait } from '../miscs/miscs' | 9 | import { getFileSize, root, wait } from '../miscs/miscs' |
10 | 10 | ||
11 | interface ServerInfo { | 11 | interface ServerInfo { |
12 | app: ChildProcess | 12 | app: ChildProcess |
@@ -318,11 +318,18 @@ async function waitUntilLog (server: ServerInfo, str: string, count = 1, strictC | |||
318 | } | 318 | } |
319 | } | 319 | } |
320 | 320 | ||
321 | async function getServerFileSize (server: ServerInfo, subPath: string) { | ||
322 | const path = join(root(), 'test' + server.internalServerNumber, subPath) | ||
323 | |||
324 | return getFileSize(path) | ||
325 | } | ||
326 | |||
321 | // --------------------------------------------------------------------------- | 327 | // --------------------------------------------------------------------------- |
322 | 328 | ||
323 | export { | 329 | export { |
324 | checkDirectoryIsEmpty, | 330 | checkDirectoryIsEmpty, |
325 | checkTmpIsEmpty, | 331 | checkTmpIsEmpty, |
332 | getServerFileSize, | ||
326 | ServerInfo, | 333 | ServerInfo, |
327 | parallelTests, | 334 | parallelTests, |
328 | cleanupTests, | 335 | cleanupTests, |