feat(local): add thumbnail for video with ffmpeg (#3556)
* feat(local): add ffmpeg * fix: missed `+` --------- Co-authored-by: Andy Hsu <i@nn.ci>
This commit is contained in:
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@ -20,7 +21,6 @@ import (
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/internal/sign"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/alist-org/alist/v3/server/common"
|
||||
"github.com/disintegration/imaging"
|
||||
_ "golang.org/x/image/webp"
|
||||
)
|
||||
@ -71,10 +71,13 @@ func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
||||
continue
|
||||
}
|
||||
thumb := ""
|
||||
if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
|
||||
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
|
||||
thumb = utils.EncodePath(thumb, true)
|
||||
thumb += "?type=thumb&sign=" + sign.Sign(stdpath.Join(args.ReqPath, f.Name()))
|
||||
if d.Thumbnail {
|
||||
typeName := utils.GetFileType(f.Name())
|
||||
if typeName == conf.IMAGE || typeName == conf.VIDEO {
|
||||
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
|
||||
thumb = utils.EncodePath(thumb, true)
|
||||
thumb += "?type=thumb&sign=" + sign.Sign(stdpath.Join(args.ReqPath, f.Name()))
|
||||
}
|
||||
}
|
||||
isFolder := f.IsDir() || isSymlinkDir(f, fullPath)
|
||||
var size int64
|
||||
@ -126,11 +129,22 @@ func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (
|
||||
fullPath := file.GetPath()
|
||||
var link model.Link
|
||||
if args.Type == "thumb" && utils.Ext(file.GetName()) != "svg" {
|
||||
imgData, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var srcBuf *bytes.Buffer
|
||||
if utils.GetFileType(file.GetName()) == conf.VIDEO {
|
||||
videoBuf, err := GetSnapshot(fullPath, 10)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
srcBuf = videoBuf
|
||||
} else {
|
||||
imgData, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imgBuf := bytes.NewBuffer(imgData)
|
||||
srcBuf = imgBuf
|
||||
}
|
||||
srcBuf := bytes.NewBuffer(imgData)
|
||||
|
||||
image, err := imaging.Decode(srcBuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1,6 +1,9 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
ffmpeg "github.com/u2takey/ffmpeg-go"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -23,3 +26,16 @@ func isSymlinkDir(f fs.FileInfo, path string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetSnapshot(videoPath string, frameNum int) (imgData *bytes.Buffer, err error) {
|
||||
srcBuf := bytes.NewBuffer(nil)
|
||||
err = ffmpeg.Input(videoPath).Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
|
||||
Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
|
||||
WithOutput(srcBuf, os.Stdout).
|
||||
Run()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return srcBuf, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user