Rework thumbnail cache to use db

This commit is contained in:
Zoe Roux 2024-07-29 23:25:26 +02:00
parent 3ea2004267
commit a75bd48ccf
3 changed files with 83 additions and 35 deletions

View File

@ -176,13 +176,10 @@ func (h *Handler) GetInfo(c echo.Context) error {
return err
}
ret, err := src.GetInfo(path, sha)
ret, err := h.metadata.GetMetadata(path, sha)
if err != nil {
return err
}
// Run extractors to have them in cache
src.Extract(ret.Path, sha)
go src.ExtractThumbnail(ret.Path, sha)
return c.JSON(http.StatusOK, ret)
}
@ -246,13 +243,12 @@ func (h *Handler) GetThumbnails(c echo.Context) error {
if err != nil {
return err
}
out, err := src.ExtractThumbnail(path, sha)
sprite, _, err := h.metadata.GetThumb(path, sha)
if err != nil {
return err
}
return c.File(fmt.Sprintf("%s/sprite.png", out))
return c.File(sprite)
}
// Get thumbnail vtt
@ -266,17 +262,17 @@ func (h *Handler) GetThumbnailsVtt(c echo.Context) error {
if err != nil {
return err
}
out, err := src.ExtractThumbnail(path, sha)
_, vtt, err := h.metadata.GetThumb(path, sha)
if err != nil {
return err
}
return c.File(fmt.Sprintf("%s/sprite.vtt", out))
return c.File(vtt)
}
type Handler struct {
transcoder *src.Transcoder
metadata src.MetadataService
}
func main() {

View File

@ -5,11 +5,25 @@ import (
)
type MetadataService struct {
database *sqlx.DB
lock *RunLock[string, *MediaInfo]
database *sqlx.DB
lock *RunLock[string, *MediaInfo]
thumbLock *RunLock[string, interface{}]
}
func (s MetadataService) GetMetadata(path string, sha string) (*MediaInfo, error) {
ret, err := s.getMetadata(path, sha)
if err != nil {
return nil, err
}
if ret.Versions.Thumbs < ThumbsVersion {
go s.ExtractThumbs(path, sha)
}
return ret, nil
}
func (s MetadataService) getMetadata(path string, sha string) (*MediaInfo, error) {
var ret MediaInfo
rows, err := s.database.Queryx(`
select * from info as i where i.sha=$1;

View File

@ -8,6 +8,7 @@ import (
"log"
"math"
"os"
"path/filepath"
"sync"
"github.com/disintegration/imaging"
@ -28,32 +29,60 @@ type Thumbnail struct {
var thumbnails = NewCMap[string, *Thumbnail]()
func ExtractThumbnail(path string, sha string) (string, error) {
ret, _ := thumbnails.GetOrCreate(sha, func() *Thumbnail {
ret := &Thumbnail{
path: fmt.Sprintf("%s/%s", Settings.Metadata, sha),
}
ret.ready.Add(1)
go func() {
extractThumbnail(path, ret.path)
ret.ready.Done()
}()
return ret
})
ret.ready.Wait()
return ret.path, nil
const ThumbsVersion = 1
func getThumbGlob(sha string) string {
return fmt.Sprintf("%s/%s/thumbs-v*.*", Settings.Metadata, sha)
}
func extractThumbnail(path string, out string) error {
defer printExecTime("extracting thumbnails for %s", path)()
os.MkdirAll(out, 0o755)
sprite_path := fmt.Sprintf("%s/sprite.png", out)
vtt_path := fmt.Sprintf("%s/sprite.vtt", out)
func getThumbPath(sha string) string {
return fmt.Sprintf("%s/%s/thumbs-v%d.png", Settings.Metadata, sha, ThumbsVersion)
}
func getThumbVttPath(sha string) string {
return fmt.Sprintf("%s/%s/thumbs-v%d.vtt", Settings.Metadata, sha, ThumbsVersion)
}
func (s MetadataService) GetThumb(path string, sha string) (string, string, error) {
sprite_path := getThumbPath(sha)
vtt_path := getThumbVttPath(sha)
if _, err := os.Stat(sprite_path); err == nil {
return nil
return sprite_path, vtt_path, nil
}
_, err := s.ExtractThumbs(path, sha)
if err != nil {
return "", "", err
}
return sprite_path, vtt_path, nil
}
func (s MetadataService) ExtractThumbs(path string, sha string) (interface{}, error) {
get_running, set := s.thumbLock.Start(sha)
if get_running != nil {
return get_running()
}
err := extractThumbnail(path, sha)
if err != nil {
return set(nil, err)
}
_, err = s.database.NamedExec(
`update info set ver_thumbs = :version where sha = :sha`,
map[string]interface{}{
"sha": sha,
"version": ThumbsVersion,
},
)
return set(nil, err)
}
func extractThumbnail(path string, sha string) error {
defer printExecTime("extracting thumbnails for %s", path)()
os.MkdirAll(fmt.Sprintf("%s/%s", Settings.Metadata), 0o755)
gen, err := screengen.NewGenerator(path)
if err != nil {
log.Printf("Error reading video file: %v", err)
@ -102,7 +131,7 @@ func extractThumbnail(path string, out string) error {
tsToVttTime(timestamps),
tsToVttTime(ts),
Settings.RoutePrefix,
base64.StdEncoding.EncodeToString([]byte(path)),
base64.RawURLEncoding.EncodeToString([]byte(path)),
x,
y,
width,
@ -110,11 +139,20 @@ func extractThumbnail(path string, out string) error {
)
}
err = os.WriteFile(vtt_path, []byte(vtt), 0o644)
// Cleanup old versions of thumbnails
files, err := filepath.Glob(getThumbGlob(sha))
if err == nil {
for _, f := range files {
// ignore errors
os.Remove(f)
}
}
err = os.WriteFile(getThumbVttPath(sha), []byte(vtt), 0o644)
if err != nil {
return err
}
err = imaging.Save(sprite, sprite_path)
err = imaging.Save(sprite, getThumbPath(sha))
if err != nil {
return err
}