85 lines
1.7 KiB
Go
85 lines
1.7 KiB
Go
|
|
package media
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"net/http"
|
||
|
|
u "net/url"
|
||
|
|
"os/exec"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"codeberg.org/danjones000/strip-beats/config"
|
||
|
|
)
|
||
|
|
|
||
|
|
type FPrint struct {
|
||
|
|
Duration float64
|
||
|
|
Fingerprint string
|
||
|
|
}
|
||
|
|
|
||
|
|
func Fingerprint(path string) (FPrint, error) {
|
||
|
|
pr := FPrint{}
|
||
|
|
_, err := exec.LookPath("fpcalc")
|
||
|
|
if err != nil {
|
||
|
|
return pr, errors.Join(errors.New("Unable to find fpcalc in PATH"), err)
|
||
|
|
}
|
||
|
|
cmd := exec.Command("fpcalc", "-json", path)
|
||
|
|
out, err := cmd.Output()
|
||
|
|
if err != nil {
|
||
|
|
return pr, errors.Join(errors.New(fmt.Sprintf("Failed to run %s", strings.Join(cmd.Args, " "))), err)
|
||
|
|
}
|
||
|
|
err = json.Unmarshal(out, &pr)
|
||
|
|
if err != nil {
|
||
|
|
return pr, errors.Join(errors.New("Couldn't parse output from fpcalc"), err)
|
||
|
|
}
|
||
|
|
|
||
|
|
return pr, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type IdResults struct {
|
||
|
|
Status string
|
||
|
|
Results []IdResult
|
||
|
|
Error IdError
|
||
|
|
}
|
||
|
|
|
||
|
|
type IdResult struct {
|
||
|
|
Id string
|
||
|
|
Score float64
|
||
|
|
Recordings []MbRecording
|
||
|
|
}
|
||
|
|
|
||
|
|
type IdError struct {
|
||
|
|
Code int
|
||
|
|
Message string
|
||
|
|
}
|
||
|
|
|
||
|
|
func LookupFingerprint(print FPrint) (IdResults, error) {
|
||
|
|
res := IdResults{}
|
||
|
|
key := config.GetConfig().AcousticIdKey
|
||
|
|
if key == "" {
|
||
|
|
return res, errors.New("Missing acoustic_id_key from config")
|
||
|
|
}
|
||
|
|
url := "https://api.acoustid.org/v2/lookup"
|
||
|
|
form := u.Values{
|
||
|
|
"format": {"json"},
|
||
|
|
"client": {key},
|
||
|
|
"duration": {fmt.Sprintf("%.0f", print.Duration)},
|
||
|
|
"fingerprint": {print.Fingerprint},
|
||
|
|
"meta": {"recordingids"}}
|
||
|
|
resp, err := http.PostForm(url, form)
|
||
|
|
if err != nil {
|
||
|
|
return res, err
|
||
|
|
}
|
||
|
|
defer resp.Body.Close()
|
||
|
|
body, err := io.ReadAll(resp.Body)
|
||
|
|
if err != nil {
|
||
|
|
return res, err
|
||
|
|
}
|
||
|
|
json.Unmarshal(body, &res)
|
||
|
|
if res.Status == "error" {
|
||
|
|
err = errors.New(res.Error.Message)
|
||
|
|
}
|
||
|
|
return res, err
|
||
|
|
}
|