package src import ( "fmt" "os" "os/exec" "sync" ) type Extractor struct { extracted map[string]<-chan struct{} lock sync.RWMutex } func NewExtractor() *Extractor { return &Extractor{ extracted: make(map[string]<-chan struct{}), } } 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", Settings.Metadata, sha) subs_path := fmt.Sprintf("%s/%s/sub", Settings.Metadata, sha) os.MkdirAll(attachment_path, 0o644) os.MkdirAll(subs_path, 0o755) 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 }