From 954f31da9aaddf9c7b2d5ab318293a8f06df71f7 Mon Sep 17 00:00:00 2001 From: JoeSmithStarkers Date: Wed, 25 Jan 2023 18:41:43 +1100 Subject: [PATCH] added vfr detection, to improve preview generation performance --- internal/manager/task_generate_preview.go | 14 ++++++++++---- pkg/scene/generate/preview.go | 20 ++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/internal/manager/task_generate_preview.go b/internal/manager/task_generate_preview.go index 37ec51ec2fe..30845a3ca01 100644 --- a/internal/manager/task_generate_preview.go +++ b/internal/manager/task_generate_preview.go @@ -40,7 +40,7 @@ func (t *GeneratePreviewTask) Start(ctx context.Context) { videoChecksum := t.Scene.GetHash(t.fileNamingAlgorithm) - if err := t.generateVideo(videoChecksum, videoFile.VideoStreamDuration); err != nil { + if err := t.generateVideo(videoChecksum, videoFile.VideoStreamDuration, videoFile.FrameRate); err != nil { logger.Errorf("error generating preview: %v", err) logErrorOutput(err) return @@ -54,12 +54,18 @@ func (t *GeneratePreviewTask) Start(ctx context.Context) { } } -func (t GeneratePreviewTask) generateVideo(videoChecksum string, videoDuration float64) error { +func (t GeneratePreviewTask) generateVideo(videoChecksum string, videoDuration float64, videoFrameRate float64) error { videoFilename := t.Scene.Path + useVsync2 := false - if err := t.generator.PreviewVideo(context.TODO(), videoFilename, videoDuration, videoChecksum, t.Options, true); err != nil { + if videoFrameRate <= 0.01 { + logger.Errorf("[generator] Video framerate very low/high (%f) most likely vfr so using -vsync 2", videoFrameRate) + useVsync2 = true + } + + if err := t.generator.PreviewVideo(context.TODO(), videoFilename, videoDuration, videoChecksum, t.Options, false, useVsync2); err != nil { logger.Warnf("[generator] failed generating scene preview, trying fallback") - if err := t.generator.PreviewVideo(context.TODO(), videoFilename, videoDuration, videoChecksum, t.Options, true); err != nil { + if err := t.generator.PreviewVideo(context.TODO(), videoFilename, videoDuration, videoChecksum, t.Options, true, useVsync2); err != nil { return err } } diff --git a/pkg/scene/generate/preview.go b/pkg/scene/generate/preview.go index ff7167f1d4e..19b98876028 100644 --- a/pkg/scene/generate/preview.go +++ b/pkg/scene/generate/preview.go @@ -68,7 +68,7 @@ func (g PreviewOptions) getStepSizeAndOffset(videoDuration float64) (stepSize fl return } -func (g Generator) PreviewVideo(ctx context.Context, input string, videoDuration float64, hash string, options PreviewOptions, fallback bool) error { +func (g Generator) PreviewVideo(ctx context.Context, input string, videoDuration float64, hash string, options PreviewOptions, fallback bool, useVsync2 bool) error { lockCtx := g.LockManager.ReadLock(ctx, input) defer lockCtx.Cancel() @@ -81,7 +81,7 @@ func (g Generator) PreviewVideo(ctx context.Context, input string, videoDuration logger.Infof("[generator] generating video preview for %s", input) - if err := g.generateFile(lockCtx, g.ScenePaths, mp4Pattern, output, g.previewVideo(input, videoDuration, options, fallback)); err != nil { + if err := g.generateFile(lockCtx, g.ScenePaths, mp4Pattern, output, g.previewVideo(input, videoDuration, options, fallback, useVsync2)); err != nil { return err } @@ -90,10 +90,10 @@ func (g Generator) PreviewVideo(ctx context.Context, input string, videoDuration return nil } -func (g *Generator) previewVideo(input string, videoDuration float64, options PreviewOptions, fallback bool) generateFn { +func (g *Generator) previewVideo(input string, videoDuration float64, options PreviewOptions, fallback bool, useVsync2 bool) generateFn { // #2496 - generate a single preview video for videos shorter than segments * segment duration if videoDuration < options.SegmentDuration*float64(options.Segments) { - return g.previewVideoSingle(input, videoDuration, options, fallback) + return g.previewVideoSingle(input, videoDuration, options, fallback, useVsync2) } return func(lockCtx *fsutil.LockContext, tmpFn string) error { @@ -131,7 +131,7 @@ func (g *Generator) previewVideo(input string, videoDuration float64, options Pr Preset: options.Preset, } - if err := g.previewVideoChunk(lockCtx, input, chunkOptions, fallback); err != nil { + if err := g.previewVideoChunk(lockCtx, input, chunkOptions, fallback, useVsync2); err != nil { return err } } @@ -150,7 +150,7 @@ func (g *Generator) previewVideo(input string, videoDuration float64, options Pr } } -func (g *Generator) previewVideoSingle(input string, videoDuration float64, options PreviewOptions, fallback bool) generateFn { +func (g *Generator) previewVideoSingle(input string, videoDuration float64, options PreviewOptions, fallback bool, useVsync2 bool) generateFn { return func(lockCtx *fsutil.LockContext, tmpFn string) error { chunkOptions := previewChunkOptions{ StartTime: 0, @@ -160,7 +160,7 @@ func (g *Generator) previewVideoSingle(input string, videoDuration float64, opti Preset: options.Preset, } - return g.previewVideoChunk(lockCtx, input, chunkOptions, fallback) + return g.previewVideoChunk(lockCtx, input, chunkOptions, fallback, useVsync2) } } @@ -172,7 +172,7 @@ type previewChunkOptions struct { Preset string } -func (g Generator) previewVideoChunk(lockCtx *fsutil.LockContext, fn string, options previewChunkOptions, fallback bool) error { +func (g Generator) previewVideoChunk(lockCtx *fsutil.LockContext, fn string, options previewChunkOptions, fallback bool, useVsync2 bool) error { var videoFilter ffmpeg.VideoFilter videoFilter = videoFilter.ScaleWidth(scenePreviewWidth) @@ -189,6 +189,10 @@ func (g Generator) previewVideoChunk(lockCtx *fsutil.LockContext, fn string, opt "-strict", "-2", ) + if useVsync2 { + videoArgs = append(videoArgs, "-vsync", "2") + } + trimOptions := transcoder.TranscodeOptions{ OutputPath: options.OutputPath, StartTime: options.StartTime,