mirror of https://github.com/stashapp/stash.git
106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
package manager
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
|
|
"github.com/stashapp/stash/pkg/ffmpeg"
|
|
"github.com/stashapp/stash/pkg/fsutil"
|
|
"github.com/stashapp/stash/pkg/logger"
|
|
)
|
|
|
|
type generatorInfo struct {
|
|
ChunkCount int
|
|
FrameRate float64
|
|
NumberOfFrames int
|
|
|
|
// NthFrame used for sprite generation
|
|
NthFrame int
|
|
|
|
VideoFile ffmpeg.VideoFile
|
|
}
|
|
|
|
func newGeneratorInfo(videoFile ffmpeg.VideoFile) (*generatorInfo, error) {
|
|
exists, err := fsutil.FileExists(videoFile.Path)
|
|
if !exists {
|
|
logger.Errorf("video file not found")
|
|
return nil, err
|
|
}
|
|
|
|
generator := &generatorInfo{VideoFile: videoFile}
|
|
return generator, nil
|
|
}
|
|
|
|
func (g *generatorInfo) calculateFrameRate(videoStream *ffmpeg.FFProbeStream) error {
|
|
var framerate float64
|
|
if g.VideoFile.FrameRate == 0 {
|
|
framerate, _ = strconv.ParseFloat(videoStream.RFrameRate, 64)
|
|
} else {
|
|
framerate = g.VideoFile.FrameRate
|
|
}
|
|
|
|
numberOfFrames, _ := strconv.Atoi(videoStream.NbFrames)
|
|
|
|
if numberOfFrames == 0 && isValidFloat64(framerate) && g.VideoFile.Duration > 0 { // TODO: test
|
|
numberOfFrames = int(framerate * g.VideoFile.Duration)
|
|
}
|
|
|
|
// If we are missing the frame count or frame rate then seek through the file and extract the info with regex
|
|
if numberOfFrames == 0 || !isValidFloat64(framerate) {
|
|
info, err := instance.FFMPEG.CalculateFrameRate(context.TODO(), &g.VideoFile)
|
|
if err != nil {
|
|
logger.Errorf("error calculating frame rate: %v", err)
|
|
} else {
|
|
if numberOfFrames == 0 {
|
|
numberOfFrames = info.NumberOfFrames
|
|
}
|
|
if !isValidFloat64(framerate) {
|
|
framerate = info.FrameRate
|
|
}
|
|
}
|
|
}
|
|
|
|
// Something seriously wrong with this file
|
|
if numberOfFrames == 0 || !isValidFloat64(framerate) {
|
|
logger.Errorf(
|
|
"number of frames or framerate is 0. nb_frames <%s> framerate <%f> duration <%f>",
|
|
videoStream.NbFrames,
|
|
framerate,
|
|
g.VideoFile.Duration,
|
|
)
|
|
}
|
|
|
|
g.FrameRate = framerate
|
|
g.NumberOfFrames = numberOfFrames
|
|
|
|
return nil
|
|
}
|
|
|
|
// isValidFloat64 ensures the given value is a valid number (not NaN) which is not equal to 0
|
|
func isValidFloat64(value float64) bool {
|
|
return !math.IsNaN(value) && value != 0
|
|
}
|
|
|
|
func (g *generatorInfo) configure() error {
|
|
videoStream := g.VideoFile.VideoStream
|
|
if videoStream == nil {
|
|
return fmt.Errorf("missing video stream")
|
|
}
|
|
|
|
if err := g.calculateFrameRate(videoStream); err != nil {
|
|
return err
|
|
}
|
|
|
|
// #2250 - ensure ChunkCount is valid
|
|
if g.ChunkCount < 1 {
|
|
logger.Warnf("[generator] Segment count (%d) must be > 0. Using 1 instead.", g.ChunkCount)
|
|
g.ChunkCount = 1
|
|
}
|
|
|
|
g.NthFrame = g.NumberOfFrames / g.ChunkCount
|
|
|
|
return nil
|
|
}
|