Use concurrent map for subtitles

This commit is contained in:
Zoe Roux 2024-02-18 22:23:39 +01:00
parent b687d8ea95
commit 2afed432f7
4 changed files with 47 additions and 46 deletions

View File

@ -176,12 +176,16 @@ func (h *Handler) GetInfo(c echo.Context) error {
return err
}
sha, err := src.GetHash(path)
if err != nil {
return err
}
ret, err := src.GetInfo(path)
if err != nil {
return err
}
// Run extractors to have them in cache
h.extractor.RunExtractor(ret.Path, ret.Sha, &ret.Subtitles)
src.Extract(ret.Path, sha)
go h.thumbnails.ExtractThumbnail(
ret.Path,
fmt.Sprintf("%s/thumbnails.png", c.Request().Header.Get("X-Route")),
@ -195,46 +199,56 @@ func (h *Handler) GetInfo(c echo.Context) error {
//
// Path: /attachment/:name
func (h *Handler) GetAttachment(c echo.Context) error {
path, err := GetPath(c)
if err != nil {
return err
}
name := c.Param("name")
if err := SanitizePath(name); err != nil {
return err
}
wait, ok := h.extractor.Extract(sha)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "Not extracted yet. Call /info to extract.")
sha, err := src.GetHash(path)
if err != nil {
return err
}
wait, err := src.Extract(path, sha)
if err != nil {
return err
}
<-wait
path := fmt.Sprintf("%s/%s/att/%s", src.Settings.Metadata, sha, name)
return c.File(path)
ret := fmt.Sprintf("%s/%s/att/%s", src.Settings.Metadata, sha, name)
return c.File(ret)
}
// Get subtitle
//
// Get a specific subtitle.
//
// Path: /:sha/subtitle/:name
// Path: /subtitle/:name
func (h *Handler) GetSubtitle(c echo.Context) error {
sha := c.Param("sha")
name := c.Param("name")
if err := SanitizePath(sha); err != nil {
path, err := GetPath(c)
if err != nil {
return err
}
name := c.Param("name")
if err := SanitizePath(name); err != nil {
return err
}
wait, ok := h.extractor.Extract(sha)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "Not extracted yet. Call /info to extract.")
sha, err := src.GetHash(path)
if err != nil {
return err
}
wait, err := src.Extract(path, sha)
if err != nil {
return err
}
<-wait
path := fmt.Sprintf("%s/%s/sub/%s", src.Settings.Metadata, sha, name)
return c.File(path)
ret := fmt.Sprintf("%s/%s/sub/%s", src.Settings.Metadata, sha, name)
return c.File(ret)
}
// Get thumbnail sprite
@ -284,7 +298,6 @@ func (h *Handler) GetThumbnailsVtt(c echo.Context) error {
type Handler struct {
transcoder *src.Transcoder
extractor *src.Extractor
thumbnails *src.ThumbnailsCreator
}
@ -300,7 +313,6 @@ func main() {
}
h := Handler{
transcoder: transcoder,
extractor: src.NewExtractor(),
thumbnails: src.NewThumbnailsCreator(),
}

View File

@ -4,36 +4,24 @@ import (
"fmt"
"os"
"os/exec"
"sync"
)
type Extractor struct {
extracted map[string]<-chan struct{}
lock sync.RWMutex
}
var extracted = NewCMap[string, <-chan struct{}]()
func NewExtractor() *Extractor {
return &Extractor{
extracted: make(map[string]<-chan struct{}),
}
}
func (e *Extractor) Extract(path string, subs *[]Subtitle) (<-chan struct{}, error) {
sha, err := getHash(path)
if err != nil {
return nil, err
}
e.lock.Lock()
existing, ok := e.extracted[sha]
if ok {
func Extract(path string, sha string) (<-chan struct{}, error) {
ret := make(chan struct{})
existing, created := extracted.GetOrSet(sha, ret)
if !created {
return existing, nil
}
ret := make(chan struct{})
e.extracted[sha] = ret
e.lock.Unlock()
go func() {
info, err := GetInfo(path)
if err != nil {
extracted.Remove(sha)
close(ret)
return
}
attachment_path := fmt.Sprintf("%s/%s/att", Settings.Metadata, sha)
subs_path := fmt.Sprintf("%s/%s/sub", Settings.Metadata, sha)
os.MkdirAll(attachment_path, 0o644)
@ -49,7 +37,7 @@ func (e *Extractor) Extract(path string, subs *[]Subtitle) (<-chan struct{}, err
)
cmd.Dir = attachment_path
for _, sub := range *subs {
for _, sub := range info.Subtitles {
if ext := sub.Extension; ext != nil {
cmd.Args = append(
cmd.Args,
@ -61,8 +49,9 @@ func (e *Extractor) Extract(path string, subs *[]Subtitle) (<-chan struct{}, err
}
fmt.Printf("Starting extraction with the command: %s", cmd)
cmd.Stdout = nil
err := cmd.Run()
err = cmd.Run()
if err != nil {
extracted.Remove(sha)
fmt.Println("Error starting ffmpeg extract:", err)
}
close(ret)

View File

@ -68,7 +68,7 @@ func (t *ThumbnailsCreator) ExtractThumbnail(path string, name string) (string,
func extractThumbnail(path string, name string) (string, error) {
defer printExecTime("extracting thumbnails for %s", path)()
sha, err := getHash(path)
sha, err := GetHash(path)
if err != nil {
return "", err
}

View File

@ -19,7 +19,7 @@ func printExecTime(message string, args ...any) func() {
}
}
func getHash(path string) (string, error) {
func GetHash(path string) (string, error) {
info, err := os.Stat(path)
if err != nil {
return "", err