Add ability to customize frames to analyze
This commit is contained in:
parent
9880d2adf5
commit
2bc4d26b94
|
@ -417,6 +417,14 @@ remote_runners:
|
||||||
live: '30 seconds'
|
live: '30 seconds'
|
||||||
vod: '2 minutes'
|
vod: '2 minutes'
|
||||||
|
|
||||||
|
thumbnails:
|
||||||
|
# When automatically generating a thumbnail from the video
|
||||||
|
generation_from_video:
|
||||||
|
# How many frames to analyze at the middle of the video to select the most appropriate one
|
||||||
|
# Increasing this value will increase CPU and memory usage when generating the thumbnail, especially for high video resolution
|
||||||
|
# Minimum value is 2
|
||||||
|
frames_to_analyze: 50
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
previews:
|
previews:
|
||||||
size: 500 # Max number of previews you want to cache
|
size: 500 # Max number of previews you want to cache
|
||||||
|
|
|
@ -415,6 +415,14 @@ remote_runners:
|
||||||
live: '30 seconds'
|
live: '30 seconds'
|
||||||
vod: '2 minutes'
|
vod: '2 minutes'
|
||||||
|
|
||||||
|
thumbnails:
|
||||||
|
# When automatically generating a thumbnail from the video
|
||||||
|
generation_from_video:
|
||||||
|
# How many frames to analyze at the middle of the video to select the most appropriate one
|
||||||
|
# Increasing this value will increase CPU and memory usage when generating the thumbnail, especially for high video resolution
|
||||||
|
# Minimum value is 2
|
||||||
|
frames_to_analyze: 50
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# From this point, almost all following keys can be overridden by the web interface
|
# From this point, almost all following keys can be overridden by the web interface
|
||||||
|
|
|
@ -39,16 +39,17 @@ export class FFmpegImage {
|
||||||
async generateThumbnailFromVideo (options: {
|
async generateThumbnailFromVideo (options: {
|
||||||
fromPath: string
|
fromPath: string
|
||||||
output: string
|
output: string
|
||||||
|
framesToAnalyze: number
|
||||||
ffprobe?: FfprobeData
|
ffprobe?: FfprobeData
|
||||||
}) {
|
}) {
|
||||||
const { fromPath, output, ffprobe } = options
|
const { fromPath, output, ffprobe, framesToAnalyze } = options
|
||||||
|
|
||||||
let duration = await getVideoStreamDuration(fromPath, ffprobe)
|
let duration = await getVideoStreamDuration(fromPath, ffprobe)
|
||||||
if (isNaN(duration)) duration = 0
|
if (isNaN(duration)) duration = 0
|
||||||
|
|
||||||
this.commandWrapper.buildCommand(fromPath)
|
this.commandWrapper.buildCommand(fromPath)
|
||||||
.seekInput(duration / 2)
|
.seekInput(duration / 2)
|
||||||
.videoFilter('thumbnail=50')
|
.videoFilter('thumbnail=' + framesToAnalyze)
|
||||||
.outputOption('-frames:v 1')
|
.outputOption('-frames:v 1')
|
||||||
.output(output)
|
.output(output)
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ function checkConfig () {
|
||||||
checkLiveConfig()
|
checkLiveConfig()
|
||||||
checkObjectStorageConfig()
|
checkObjectStorageConfig()
|
||||||
checkVideoStudioConfig()
|
checkVideoStudioConfig()
|
||||||
|
checkThumbnailsConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We get db by param to not import it in this file (import orders)
|
// We get db by param to not import it in this file (import orders)
|
||||||
|
@ -331,3 +332,9 @@ function checkVideoStudioConfig () {
|
||||||
throw new Error('Video studio cannot be enabled if transcoding is disabled')
|
throw new Error('Video studio cannot be enabled if transcoding is disabled')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkThumbnailsConfig () {
|
||||||
|
if (CONFIG.THUMBNAILS.GENERATION_FROM_VIDEO.FRAMES_TO_ANALYZE < 2) {
|
||||||
|
throw new Error('thumbnails.generation_from_video.frames_to_analyze must be a number greater than 1')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ function checkMissedConfig () {
|
||||||
'video_studio.enabled', 'video_studio.remote_runners.enabled',
|
'video_studio.enabled', 'video_studio.remote_runners.enabled',
|
||||||
'video_file.update.enabled',
|
'video_file.update.enabled',
|
||||||
'remote_runners.stalled_jobs.vod', 'remote_runners.stalled_jobs.live',
|
'remote_runners.stalled_jobs.vod', 'remote_runners.stalled_jobs.live',
|
||||||
|
'thumbnails.generation_from_video.frames_to_analyze',
|
||||||
'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'import.videos.timeout',
|
'import.videos.http.enabled', 'import.videos.torrent.enabled', 'import.videos.concurrency', 'import.videos.timeout',
|
||||||
'import.video_channel_synchronization.enabled', 'import.video_channel_synchronization.max_per_user',
|
'import.video_channel_synchronization.enabled', 'import.video_channel_synchronization.max_per_user',
|
||||||
'import.video_channel_synchronization.check_interval', 'import.video_channel_synchronization.videos_limit_per_synchronization',
|
'import.video_channel_synchronization.check_interval', 'import.video_channel_synchronization.videos_limit_per_synchronization',
|
||||||
|
|
|
@ -344,6 +344,11 @@ const CONFIG = {
|
||||||
VOD: parseDurationToMs(config.get<string>('remote_runners.stalled_jobs.vod'))
|
VOD: parseDurationToMs(config.get<string>('remote_runners.stalled_jobs.vod'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
THUMBNAILS: {
|
||||||
|
GENERATION_FROM_VIDEO: {
|
||||||
|
FRAMES_TO_ANALYZE: config.get<number>('thumbnails.generation_from_video.frames_to_analyze')
|
||||||
|
}
|
||||||
|
},
|
||||||
ADMIN: {
|
ADMIN: {
|
||||||
get EMAIL () { return config.get<string>('admin.email') }
|
get EMAIL () { return config.get<string>('admin.email') }
|
||||||
},
|
},
|
||||||
|
|
|
@ -379,7 +379,8 @@ async function generateImageFromVideoFile (options: {
|
||||||
const pendingImagePath = join(folder, pendingImageName)
|
const pendingImagePath = join(folder, pendingImageName)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await generateThumbnailFromVideo({ fromPath, output: pendingImagePath, ffprobe })
|
const framesToAnalyze = CONFIG.THUMBNAILS.GENERATION_FROM_VIDEO.FRAMES_TO_ANALYZE
|
||||||
|
await generateThumbnailFromVideo({ fromPath, output: pendingImagePath, framesToAnalyze, ffprobe })
|
||||||
|
|
||||||
const destination = join(folder, imageName)
|
const destination = join(folder, imageName)
|
||||||
await processImageFromWorker({ path: pendingImagePath, destination, newSize: size })
|
await processImageFromWorker({ path: pendingImagePath, destination, newSize: size })
|
||||||
|
|
Loading…
Reference in New Issue