Fingerprinting audio

This commit is contained in:
Dan Jones 2023-09-08 18:48:21 -05:00
commit d8cae5b9c4
3 changed files with 105 additions and 0 deletions

View file

@ -24,7 +24,22 @@ func quit() {
os.Exit(0) 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) { func Run(step AppStep) {
testFp()
for step < Quit { for step < Quit {
switch step { switch step {
case Pick: case Pick:

View file

@ -19,6 +19,8 @@ type Config struct {
FfEncoder string `toml:"ff_encoder"` FfEncoder string `toml:"ff_encoder"`
AllowedCodecs []string `toml:"allowed_codec"` AllowedCodecs []string `toml:"allowed_codec"`
CodecExt map[string]string `toml:"codec_ext"` CodecExt map[string]string `toml:"codec_ext"`
AcousticIdKey string `toml:"acoustic_id_key"`
AcousticUserKey string `toml:"acoustic_user_key"`
} }
var config Config var config Config

88
media/fingerprint.go Normal file
View 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
}