Add tests for video downscale framerate matching
This commit is contained in:
parent
06bcfbd9f7
commit
837666fe48
|
@ -263,6 +263,10 @@ async function canDoQuickTranscode (path: string): Promise<boolean> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getClosestFramerateStandard (fps: number, hd = false): number {
|
||||||
|
return VIDEO_TRANSCODING_FPS[hd ? 'HD_STANDARD' : 'STANDARD'].slice(0).sort((a, b) => fps % a - fps % b)[0]
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -291,11 +295,11 @@ async function buildx264Command (command: ffmpeg.FfmpegCommand, options: Transco
|
||||||
options.resolution !== undefined &&
|
options.resolution !== undefined &&
|
||||||
options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
|
options.resolution < VIDEO_TRANSCODING_FPS.KEEP_ORIGIN_FPS_RESOLUTION_MIN &&
|
||||||
fps > VIDEO_TRANSCODING_FPS.AVERAGE ||
|
fps > VIDEO_TRANSCODING_FPS.AVERAGE ||
|
||||||
// If the video is doesn't match had standard
|
// If the video is doesn't match hd standard
|
||||||
!VIDEO_TRANSCODING_FPS.HD_STANDARD.map(value => fps % value).includes(0)
|
!VIDEO_TRANSCODING_FPS.HD_STANDARD.some(value => fps % value === 0)
|
||||||
) {
|
) {
|
||||||
// Get closest standard framerate by modulo: downsampling has to be done to a divisor of the nominal fps value
|
// Get closest standard framerate by modulo: downsampling has to be done to a divisor of the nominal fps value
|
||||||
fps = VIDEO_TRANSCODING_FPS.STANDARD.sort((a, b) => fps % a - fps % b)[0]
|
fps = getClosestFramerateStandard(fps)
|
||||||
}
|
}
|
||||||
|
|
||||||
command = await presetH264(command, options.inputPath, options.resolution, fps)
|
command = await presetH264(command, options.inputPath, options.resolution, fps)
|
||||||
|
@ -308,7 +312,7 @@ async function buildx264Command (command: ffmpeg.FfmpegCommand, options: Transco
|
||||||
|
|
||||||
if (fps) {
|
if (fps) {
|
||||||
// Hard FPS limits
|
// Hard FPS limits
|
||||||
if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = VIDEO_TRANSCODING_FPS.HD_STANDARD.sort((a, b) => fps % a - fps % b)[0]
|
if (fps > VIDEO_TRANSCODING_FPS.MAX) fps = getClosestFramerateStandard(fps, true)
|
||||||
else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
|
else if (fps < VIDEO_TRANSCODING_FPS.MIN) fps = VIDEO_TRANSCODING_FPS.MIN
|
||||||
|
|
||||||
command = command.withFPS(fps)
|
command = command.withFPS(fps)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as winston from 'winston'
|
||||||
import { FileTransportOptions } from 'winston/lib/winston/transports'
|
import { FileTransportOptions } from 'winston/lib/winston/transports'
|
||||||
import { CONFIG } from '../initializers/config'
|
import { CONFIG } from '../initializers/config'
|
||||||
import { omit } from 'lodash'
|
import { omit } from 'lodash'
|
||||||
import { LOG_FILENAME } from '@server/initializers/constants'
|
import { LOG_FILENAME } from '../initializers/constants'
|
||||||
|
|
||||||
const label = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
const label = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
doubleFollow,
|
doubleFollow,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
generateHighBitrateVideo,
|
generateHighBitrateVideo,
|
||||||
|
generateVideoWithFramerate,
|
||||||
getMyVideos,
|
getMyVideos,
|
||||||
getVideo,
|
getVideo,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
|
@ -416,6 +417,39 @@ describe('Test video transcoding', function () {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should downscale to the closest divisor standard framerate', async function () {
|
||||||
|
this.timeout(160000)
|
||||||
|
|
||||||
|
let tempFixturePath: string
|
||||||
|
|
||||||
|
{
|
||||||
|
tempFixturePath = await generateVideoWithFramerate()
|
||||||
|
|
||||||
|
const fps = await getVideoFileFPS(tempFixturePath)
|
||||||
|
expect(fps).to.be.equal(59)
|
||||||
|
}
|
||||||
|
|
||||||
|
const videoAttributes = {
|
||||||
|
name: '59fps video',
|
||||||
|
description: '59fps video',
|
||||||
|
fixture: tempFixturePath
|
||||||
|
}
|
||||||
|
|
||||||
|
await uploadVideo(servers[1].url, servers[1].accessToken, videoAttributes)
|
||||||
|
|
||||||
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
for (const server of servers) {
|
||||||
|
const res = await getVideosList(server.url)
|
||||||
|
|
||||||
|
const video = res.body.data.find(v => v.name === videoAttributes.name)
|
||||||
|
const path = join(root(), 'test' + servers[1].internalServerNumber, 'videos', video.uuid + '-240.mp4')
|
||||||
|
const fps = await getVideoFileFPS(path)
|
||||||
|
|
||||||
|
expect(fps).to.be.equal(25)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
await cleanupTests(servers)
|
await cleanupTests(servers)
|
||||||
})
|
})
|
||||||
|
|
|
@ -104,6 +104,28 @@ async function generateHighBitrateVideo () {
|
||||||
return tempFixturePath
|
return tempFixturePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function generateVideoWithFramerate (fps = 60) {
|
||||||
|
const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
|
||||||
|
|
||||||
|
await ensureDir(dirname(tempFixturePath))
|
||||||
|
|
||||||
|
const exists = await pathExists(tempFixturePath)
|
||||||
|
if (!exists) {
|
||||||
|
return new Promise<string>(async (res, rej) => {
|
||||||
|
ffmpeg()
|
||||||
|
.outputOptions([ '-f rawvideo', '-video_size 320x240', '-i /dev/urandom' ])
|
||||||
|
.outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
|
||||||
|
.outputOptions([ `-r ${fps}` ])
|
||||||
|
.output(tempFixturePath)
|
||||||
|
.on('error', rej)
|
||||||
|
.on('end', () => res(tempFixturePath))
|
||||||
|
.run()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempFixturePath
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -115,5 +137,6 @@ export {
|
||||||
testImage,
|
testImage,
|
||||||
buildAbsoluteFixturePath,
|
buildAbsoluteFixturePath,
|
||||||
root,
|
root,
|
||||||
generateHighBitrateVideo
|
generateHighBitrateVideo,
|
||||||
|
generateVideoWithFramerate
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue