mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Feature: AVIF support (#6288)
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"image"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
_ "image/gif"
|
||||
_ "image/jpeg"
|
||||
@@ -28,6 +30,11 @@ func (d *Decorator) Decorate(ctx context.Context, fs models.FS, f models.File) (
|
||||
// ignore clips in non-OsFS filesystems as ffprobe cannot read them
|
||||
// TODO - copy to temp file if not an OsFS
|
||||
if _, isOs := fs.(*file.OsFS); !isOs {
|
||||
// AVIF images inside zip files are not supported
|
||||
if strings.ToLower(filepath.Ext(base.Path)) == ".avif" {
|
||||
logger.Warnf("Skipping AVIF image in zip file: %s", base.Path)
|
||||
return f, nil
|
||||
}
|
||||
logger.Debugf("assuming ImageFile for non-OsFS file %q", base.Path)
|
||||
return decorateFallback(fs, f)
|
||||
}
|
||||
|
||||
@@ -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