/
transcriber.go
111 lines (97 loc) · 2.61 KB
/
transcriber.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package transcriber
import (
"bytes"
"fmt"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/airenas/go-app/pkg/goapp"
"github.com/airenas/music-transcription-service/internal/pkg/utils"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
//Worker wrapper for file conversion
type Worker struct {
cmdPath string
convertFunc func([]string) error
}
//NewWorker return new transcribe wrapper
func NewWorker(cmdPath string) (*Worker, error) {
res := Worker{}
if cmdPath == "" {
return nil, errors.New("no cmd path")
}
res.cmdPath = cmdPath
res.convertFunc = func(p []string) error { return runCmd(p, time.Minute*2) }
goapp.Log.Infof("Cmd: %s", cmdPath)
return &res, nil
}
//Convert returns name of new converted file
func (e *Worker) Convert(nameIn, instrument string) (string, error) {
resName := getNewFile(nameIn)
params := prepareParams(e.cmdPath, nameIn, resName, instrument)
err := e.convertFunc(params)
if err != nil {
return "", err
}
return resName, nil
}
func runCmd(cmdArr []string, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
goapp.Log.Infof("Cmd: %s", strings.Join(cmdArr, " "))
cmd := exec.CommandContext(ctx, cmdArr[0], cmdArr[1:]...)
var outBuffer bytes.Buffer
var errBuffer bytes.Buffer
cmd.Stdout = &outBuffer
cmd.Stderr = &errBuffer
resChan := make(chan error, 1)
go func() {
resChan <- cmd.Run()
}()
var err error
select {
case e := <-resChan:
err = e
case <-ctx.Done():
return errors.Wrap(ctx.Err(), fmt.Sprintf("Timeout. Out: %s\nErr: %s", outBuffer.String(), errBuffer.String()))
}
es := errBuffer.String()
if err != nil || es != "" {
goapp.Log.Errorf("Cmd err: %s\nout %s:", es, outBuffer.String())
return mapError(err, es)
}
return nil
}
func getNewFile(file string) string {
f := filepath.Base(file)
ext := filepath.Ext(f)
d := filepath.Dir(file)
return filepath.Join(d, fmt.Sprintf("%s.%s", f[:len(f)-len(ext)], "musicxml"))
}
func mapError(err error, es string) error {
if es != "" {
return utils.NewErrTranscribe(es)
}
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
c := exitErr.ExitCode()
if c == -1 {
if exitErr.ProcessState != nil {
s := exitErr.ProcessState.String()
goapp.Log.Error(s)
return errors.Wrapf(err, "Err: %s", s)
}
}
}
return err
}
func prepareParams(cmd, fIn, fOut, ins string) []string {
res := []string{}
iCmd := strings.ReplaceAll(cmd, "{{INPUT}}", fIn)
iCmd = strings.ReplaceAll(iCmd, "{{OUTPUT}}", fOut)
iCmd = strings.ReplaceAll(iCmd, "{{INSTRUMENT}}", ins)
res = append(res, strings.Split(iCmd, " ")...)
return res
}