✨ Fingerprinting audio
This commit is contained in:
parent
4057d00c46
commit
d8cae5b9c4
3 changed files with 105 additions and 0 deletions
15
app/run.go
15
app/run.go
|
|
@ -24,7 +24,22 @@ func quit() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
func testFp() {
|
||||
fp, err := media.Fingerprint("/home/drj/MyFiles/Videos/WebShows/YouTube/Dolly_Parton_-_Topic/Just_Because_I_m_a_Woman.Dolly_Parton_-_Topic.Fmv-XQerVkM.webm")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// fmt.Printf("%+v\n", fp)
|
||||
ids, err := media.LookupFingerprint(fp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%+v\n", ids)
|
||||
quit()
|
||||
}
|
||||
|
||||
func Run(step AppStep) {
|
||||
testFp()
|
||||
for step < Quit {
|
||||
switch step {
|
||||
case Pick:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ type Config struct {
|
|||
FfEncoder string `toml:"ff_encoder"`
|
||||
AllowedCodecs []string `toml:"allowed_codec"`
|
||||
CodecExt map[string]string `toml:"codec_ext"`
|
||||
AcousticIdKey string `toml:"acoustic_id_key"`
|
||||
AcousticUserKey string `toml:"acoustic_user_key"`
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
|
|
|||
88
media/fingerprint.go
Normal file
88
media/fingerprint.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
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
|
||||
}
|
||||
|
||||
type MbRecording struct {
|
||||
Id 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue