mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Feature: AVIF support (#6288)
This commit is contained in:
@@ -22,12 +22,8 @@ const ffmpegImageQuality = 5
|
||||
var vipsPath string
|
||||
var once sync.Once
|
||||
|
||||
var (
|
||||
ErrUnsupportedImageFormat = errors.New("unsupported image format")
|
||||
|
||||
// ErrNotSupportedForThumbnail is returned if the image format is not supported for thumbnail generation
|
||||
ErrNotSupportedForThumbnail = errors.New("unsupported image format for thumbnail")
|
||||
)
|
||||
// ErrNotSupportedForThumbnail is returned if the image format is not supported for thumbnail generation
|
||||
var ErrNotSupportedForThumbnail = errors.New("unsupported image format for thumbnail")
|
||||
|
||||
type ThumbnailEncoder struct {
|
||||
FFMpeg *ffmpeg.FFMpeg
|
||||
@@ -83,8 +79,9 @@ func (e *ThumbnailEncoder) GetThumbnail(f models.File, maxSize int) ([]byte, err
|
||||
|
||||
data := buf.Bytes()
|
||||
|
||||
format := ""
|
||||
if imageFile, ok := f.(*models.ImageFile); ok {
|
||||
format := imageFile.Format
|
||||
format = imageFile.Format
|
||||
animated := imageFile.Format == formatGif
|
||||
|
||||
// #2266 - if image is webp, then determine if it is animated
|
||||
@@ -96,6 +93,15 @@ func (e *ThumbnailEncoder) GetThumbnail(f models.File, maxSize int) ([]byte, err
|
||||
if animated {
|
||||
return nil, fmt.Errorf("%w: %s", ErrNotSupportedForThumbnail, format)
|
||||
}
|
||||
|
||||
// AVIF cannot be read from stdin, must use file path
|
||||
// AVIF in zip files is not supported
|
||||
if format == "avif" {
|
||||
if f.Base().ZipFileID != nil {
|
||||
return nil, fmt.Errorf("%w: AVIF in zip file", ErrNotSupportedForThumbnail)
|
||||
}
|
||||
return e.ffmpegImageThumbnailPath(f.Base().Path, maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
// Videofiles can only be thumbnailed with ffmpeg
|
||||
@@ -130,16 +136,32 @@ func (e *ThumbnailEncoder) GetPreview(inPath string, outPath string, maxSize int
|
||||
}
|
||||
|
||||
func (e *ThumbnailEncoder) ffmpegImageThumbnail(image *bytes.Buffer, maxSize int) ([]byte, error) {
|
||||
args := transcoder.ImageThumbnail("-", transcoder.ImageThumbnailOptions{
|
||||
options := transcoder.ImageThumbnailOptions{
|
||||
OutputFormat: ffmpeg.ImageFormatJpeg,
|
||||
OutputPath: "-",
|
||||
MaxDimensions: maxSize,
|
||||
Quality: ffmpegImageQuality,
|
||||
})
|
||||
}
|
||||
|
||||
args := transcoder.ImageThumbnail("-", options)
|
||||
|
||||
return e.FFMpeg.GenerateOutput(context.TODO(), args, image)
|
||||
}
|
||||
|
||||
// ffmpegImageThumbnailPath generates a thumbnail from a file path (used for AVIF which can't be piped)
|
||||
func (e *ThumbnailEncoder) ffmpegImageThumbnailPath(inputPath string, maxSize int) ([]byte, error) {
|
||||
options := transcoder.ImageThumbnailOptions{
|
||||
OutputFormat: ffmpeg.ImageFormatJpeg,
|
||||
OutputPath: "-",
|
||||
MaxDimensions: maxSize,
|
||||
Quality: ffmpegImageQuality,
|
||||
}
|
||||
|
||||
args := transcoder.ImageThumbnail(inputPath, options)
|
||||
|
||||
return e.FFMpeg.GenerateOutput(context.TODO(), args, nil)
|
||||
}
|
||||
|
||||
func (e *ThumbnailEncoder) getClipPreview(inPath string, outPath string, maxSize int, clipDuration float64, frameRate float64) error {
|
||||
var thumbFilter ffmpeg.VideoFilter
|
||||
thumbFilter = thumbFilter.ScaleMaxSize(maxSize)
|
||||
|
||||
Reference in New Issue
Block a user