mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
added vfr detection, to improve preview generation performance (#3376)
This commit is contained in:
@@ -44,7 +44,7 @@ func (t *GeneratePreviewTask) Start(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
logger.Errorf("error generating preview: %v", err)
|
||||||
logErrorOutput(err)
|
logErrorOutput(err)
|
||||||
return
|
return
|
||||||
@@ -59,12 +59,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
|
videoFilename := t.Scene.Path
|
||||||
|
useVsync2 := false
|
||||||
|
|
||||||
if err := t.generator.PreviewVideo(context.TODO(), videoFilename, videoDuration, videoChecksum, t.Options, false); 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")
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func (g PreviewOptions) getStepSizeAndOffset(videoDuration float64) (stepSize fl
|
|||||||
return
|
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)
|
lockCtx := g.LockManager.ReadLock(ctx, input)
|
||||||
defer lockCtx.Cancel()
|
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)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,10 +90,10 @@ func (g Generator) PreviewVideo(ctx context.Context, input string, videoDuration
|
|||||||
return nil
|
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
|
// #2496 - generate a single preview video for videos shorter than segments * segment duration
|
||||||
if videoDuration < options.SegmentDuration*float64(options.Segments) {
|
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 {
|
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,
|
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
|
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 {
|
return func(lockCtx *fsutil.LockContext, tmpFn string) error {
|
||||||
chunkOptions := previewChunkOptions{
|
chunkOptions := previewChunkOptions{
|
||||||
StartTime: 0,
|
StartTime: 0,
|
||||||
@@ -160,7 +160,7 @@ func (g *Generator) previewVideoSingle(input string, videoDuration float64, opti
|
|||||||
Preset: options.Preset,
|
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
|
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
|
var videoFilter ffmpeg.VideoFilter
|
||||||
videoFilter = videoFilter.ScaleWidth(scenePreviewWidth)
|
videoFilter = videoFilter.ScaleWidth(scenePreviewWidth)
|
||||||
|
|
||||||
@@ -189,6 +189,10 @@ func (g Generator) previewVideoChunk(lockCtx *fsutil.LockContext, fn string, opt
|
|||||||
"-strict", "-2",
|
"-strict", "-2",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if useVsync2 {
|
||||||
|
videoArgs = append(videoArgs, "-vsync", "2")
|
||||||
|
}
|
||||||
|
|
||||||
trimOptions := transcoder.TranscodeOptions{
|
trimOptions := transcoder.TranscodeOptions{
|
||||||
OutputPath: options.OutputPath,
|
OutputPath: options.OutputPath,
|
||||||
StartTime: options.StartTime,
|
StartTime: options.StartTime,
|
||||||
|
|||||||
Reference in New Issue
Block a user