mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
Add extraction cache and wait for extraction to end to return subtitles/attachments
This commit is contained in:
parent
30cb171612
commit
425de0b315
@ -190,10 +190,10 @@ func (h *Handler) GetAudioSegment(c echo.Context) error {
|
|||||||
|
|
||||||
// Identify
|
// Identify
|
||||||
//
|
//
|
||||||
// # Identify metadata about a file
|
// Identify metadata about a file
|
||||||
//
|
//
|
||||||
// Path: /:resource/:slug/info
|
// Path: /:resource/:slug/info
|
||||||
func GetInfo(c echo.Context) error {
|
func (h *Handler) GetInfo(c echo.Context) error {
|
||||||
resource := c.Param("resource")
|
resource := c.Param("resource")
|
||||||
slug := c.Param("slug")
|
slug := c.Param("slug")
|
||||||
|
|
||||||
@ -206,6 +206,7 @@ func GetInfo(c echo.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
h.extractor.RunExtractor(ret.Path, ret.Sha, &ret.Subtitles)
|
||||||
return c.JSON(http.StatusOK, ret)
|
return c.JSON(http.StatusOK, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +215,7 @@ func GetInfo(c echo.Context) error {
|
|||||||
// Get a specific attachment
|
// Get a specific attachment
|
||||||
//
|
//
|
||||||
// Path: /:sha/attachment/:name
|
// Path: /:sha/attachment/:name
|
||||||
func GetAttachment(c echo.Context) error {
|
func (h *Handler) GetAttachment(c echo.Context) error {
|
||||||
sha := c.Param("sha")
|
sha := c.Param("sha")
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
|
|
||||||
@ -225,6 +226,12 @@ func GetAttachment(c echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait, ok := h.extractor.Extract(sha)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Not extracted yet. Call /info to extract.")
|
||||||
|
}
|
||||||
|
<-wait
|
||||||
|
|
||||||
path := fmt.Sprintf("%s/%s/att/%s", src.GetMetadataPath(), sha, name)
|
path := fmt.Sprintf("%s/%s/att/%s", src.GetMetadataPath(), sha, name)
|
||||||
return c.File(path)
|
return c.File(path)
|
||||||
}
|
}
|
||||||
@ -233,8 +240,8 @@ func GetAttachment(c echo.Context) error {
|
|||||||
//
|
//
|
||||||
// Get a specific subtitle
|
// Get a specific subtitle
|
||||||
//
|
//
|
||||||
// Path: /:sha/sub/:name
|
// Path: /:sha/subtitle/:name
|
||||||
func GetSubtitle(c echo.Context) error {
|
func (h *Handler) GetSubtitle(c echo.Context) error {
|
||||||
sha := c.Param("sha")
|
sha := c.Param("sha")
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
|
|
||||||
@ -245,12 +252,19 @@ func GetSubtitle(c echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait, ok := h.extractor.Extract(sha)
|
||||||
|
if !ok {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, "Not extracted yet. Call /info to extract.")
|
||||||
|
}
|
||||||
|
<-wait
|
||||||
|
|
||||||
path := fmt.Sprintf("%s/%s/sub/%s", src.GetMetadataPath(), sha, name)
|
path := fmt.Sprintf("%s/%s/sub/%s", src.GetMetadataPath(), sha, name)
|
||||||
return c.File(path)
|
return c.File(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
transcoder *src.Transcoder
|
transcoder *src.Transcoder
|
||||||
|
extractor *src.Extractor
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -263,7 +277,7 @@ func main() {
|
|||||||
e.Logger.Fatal(err)
|
e.Logger.Fatal(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h := Handler{transcoder: transcoder}
|
h := Handler{transcoder: transcoder, extractor: src.NewExtractor()}
|
||||||
|
|
||||||
e.GET("/:resource/:slug/direct", DirectStream)
|
e.GET("/:resource/:slug/direct", DirectStream)
|
||||||
e.GET("/:resource/:slug/master.m3u8", h.GetMaster)
|
e.GET("/:resource/:slug/master.m3u8", h.GetMaster)
|
||||||
@ -271,9 +285,9 @@ func main() {
|
|||||||
e.GET("/:resource/:slug/audio/:audio/index.m3u8", h.GetAudioIndex)
|
e.GET("/:resource/:slug/audio/:audio/index.m3u8", h.GetAudioIndex)
|
||||||
e.GET("/:resource/:slug/:quality/:chunk", h.GetVideoSegment)
|
e.GET("/:resource/:slug/:quality/:chunk", h.GetVideoSegment)
|
||||||
e.GET("/:resource/:slug/audio/:audio/:chunk", h.GetAudioSegment)
|
e.GET("/:resource/:slug/audio/:audio/:chunk", h.GetAudioSegment)
|
||||||
e.GET("/:resource/:slug/info", GetInfo)
|
e.GET("/:resource/:slug/info", h.GetInfo)
|
||||||
e.GET("/:sha/attachment/:name", GetAttachment)
|
e.GET("/:sha/attachment/:name", h.GetAttachment)
|
||||||
e.GET("/:sha/sub/:name", GetSubtitle)
|
e.GET("/:sha/subtitle/:name", h.GetSubtitle)
|
||||||
|
|
||||||
e.Logger.Fatal(e.Start(":7666"))
|
e.Logger.Fatal(e.Start(":7666"))
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Extractor struct {
|
||||||
|
extracted map[string]<-chan struct{}
|
||||||
|
lock sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
func GetMetadataPath() string {
|
func GetMetadataPath() string {
|
||||||
out := os.Getenv("GOCODER_METADATA_ROOT")
|
out := os.Getenv("GOCODER_METADATA_ROOT")
|
||||||
if out == "" {
|
if out == "" {
|
||||||
@ -14,29 +20,66 @@ func GetMetadataPath() string {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func extract(path string, sha string, subs *[]Subtitle) {
|
func NewExtractor() *Extractor {
|
||||||
fmt.Printf("Extract subs and fonts for %s", path)
|
return &Extractor{
|
||||||
cmd := exec.Command(
|
extracted: make(map[string]<-chan struct{}),
|
||||||
"ffmpeg",
|
|
||||||
"-dump_attachment:t", "",
|
|
||||||
"-i", path,
|
|
||||||
)
|
|
||||||
cmd.Dir = fmt.Sprintf("/%s/%s/att/", GetMetadataPath(), sha)
|
|
||||||
|
|
||||||
for _, sub := range *subs {
|
|
||||||
if ext := sub.Extension; ext != nil {
|
|
||||||
cmd.Args = append(
|
|
||||||
cmd.Args,
|
|
||||||
"-map", fmt.Sprintf("0:s:%d", sub.Index),
|
|
||||||
"-c:s", "copy",
|
|
||||||
fmt.Sprintf("/%s/%s/sub/%d.%s", GetMetadataPath(), sha, sub.Index, *ext),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("Starting extraction with the command: %s", cmd)
|
|
||||||
cmd.Stdout = nil
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error starting ffmpeg extract:", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Extractor) Extract(sha string) (<-chan struct{}, bool) {
|
||||||
|
e.lock.RLock()
|
||||||
|
existing, ok := e.extracted[sha]
|
||||||
|
e.lock.RUnlock()
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return existing, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Extractor) RunExtractor(path string, sha string, subs *[]Subtitle) <-chan struct{} {
|
||||||
|
existing, ok := e.Extract(sha)
|
||||||
|
if ok {
|
||||||
|
return existing
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := make(chan struct{})
|
||||||
|
e.lock.Lock()
|
||||||
|
e.extracted[sha] = ret
|
||||||
|
e.lock.Unlock()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
attachment_path := fmt.Sprintf("%s/%s/att/", GetMetadataPath(), sha)
|
||||||
|
subs_path := fmt.Sprintf("%s/%s/sub/", GetMetadataPath(), sha)
|
||||||
|
os.MkdirAll(attachment_path, 0o644)
|
||||||
|
os.MkdirAll(subs_path, 0o644)
|
||||||
|
|
||||||
|
fmt.Printf("Extract subs and fonts for %s", path)
|
||||||
|
cmd := exec.Command(
|
||||||
|
"ffmpeg",
|
||||||
|
"-dump_attachment:t", "",
|
||||||
|
"-i", path,
|
||||||
|
)
|
||||||
|
cmd.Dir = attachment_path
|
||||||
|
|
||||||
|
for _, sub := range *subs {
|
||||||
|
if ext := sub.Extension; ext != nil {
|
||||||
|
cmd.Args = append(
|
||||||
|
cmd.Args,
|
||||||
|
"-map", fmt.Sprintf("0:s:%d", sub.Index),
|
||||||
|
"-c:s", "copy",
|
||||||
|
fmt.Sprintf("%s/%d.%s", subs_path, sub.Index, *ext),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf("Starting extraction with the command: %s", cmd)
|
||||||
|
cmd.Stdout = nil
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error starting ffmpeg extract:", err)
|
||||||
|
}
|
||||||
|
close(ret)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
@ -169,8 +169,6 @@ func GetInfo(path string) (*MediaInfo, error) {
|
|||||||
}
|
}
|
||||||
defer mi.Close()
|
defer mi.Close()
|
||||||
|
|
||||||
// TODO: extract
|
|
||||||
|
|
||||||
sha := mi.Parameter(mediainfo.StreamGeneral, 0, "UniqueID")
|
sha := mi.Parameter(mediainfo.StreamGeneral, 0, "UniqueID")
|
||||||
// Remove dummy values that some tools use.
|
// Remove dummy values that some tools use.
|
||||||
if len(sha) <= 5 {
|
if len(sha) <= 5 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user