-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchromaprint.go
90 lines (76 loc) · 2.58 KB
/
chromaprint.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
package chromaprint
import (
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
"strings"
)
type Chromaprint struct {
options builder
}
type FingerprintData struct {
// timestamp in the input audio (starts from 0)
// useful in case the output consists of various
// chunks
TimestampInSeconds float64 `json:"timestamp"`
// duration of the fingerprint
DurationInSeconds float64 `json:"duration"`
// fingerprint of the input audio
Fingerprint []uint32 `json:"fingerprint"`
}
// Create a list of slice prints
// filepathToAudioFile is the file path to the audio file.
// In case an error is identified the fingerprint slice will
// be of length 0 and error will not be nil.
func (c *Chromaprint) CreateFingerprints(filepathToAudioFile string) ([]FingerprintData, error) {
result := make([]FingerprintData, 0)
if _, err := os.Stat(filepathToAudioFile); errors.Is(err, os.ErrNotExist) {
return result, os.ErrNotExist
}
parameters := []string{filepathToAudioFile, "-json", "-raw"}
parameters = append(parameters, c.getArgs()...)
out, err := exec.Command(c.options.filePath, parameters...).Output()
if err != nil {
return result, err
}
// even if json format is chosen result value is not json
// but a set of loose json elements
// convert output into real json array of json element
jsonString := strings.TrimSpace(string(out))
// add comma separation between individual elements
jsonString = strings.Replace(jsonString, "}", "},", -1)
// cut last unneeded comma
jsonString = jsonString[0 : len(jsonString)-1]
// add array braces to whole set
jsonString = fmt.Sprintf("[%s]", jsonString)
err = json.Unmarshal([]byte(jsonString), &result)
if err != nil {
return result, fmt.Errorf("invalid JSON output from fpcalc: %+v", err)
}
return result, nil
}
func (c *Chromaprint) getArgs() []string {
args := make([]string, 0)
addInt(&args, "rate", c.options.sampleRateInHz)
addInt(&args, "channels", c.options.channels)
addInt(&args, "length", c.options.maxFingerPrintLength)
addInt(&args, "chunk", c.options.chunkSizeInSeconds)
addInt(&args, "algorithm", c.options.algorithm)
if c.options.overlap {
args = append(args, "-overlap")
}
return args
}
func addInt(args *[]string, argName string, value int) {
if value != -1 {
*args = append(*args, fmt.Sprintf("-%s", argName), fmt.Sprint(value))
}
}
// Returns to used version of Chomaprint e.g.:
// 'fpcalc version 1.5.1 (FFmpeg Lavc58.134.100 Lavf58.76.100 SwR3.9.100)'
func (c *Chromaprint) GetVersion() (string, error) {
result, err := exec.Command(c.options.filePath, "-version").Output()
return strings.TrimSpace(string(result)), err
}