FLAC 和 MP3 的色谱指纹
chromaprint fingerprint of FLAC and MP3
我想使用 Go 中的 chromaprint 库创建 FLAC 或 MP3 文件的声学指纹。我一直在研究以下两个 Go 库:
- gochroma,去绑定 chromaprint
- fingerprint
使用以下代码,可以创建“原始音频数据流”的指纹(其中 reader
属于 io.Reader
类型):
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: reader,
Channels: 2,
Rate: 44100,
MaxSeconds: 120,
}
)
不幸的是,我无法弄清楚“原始音频数据流”的确切含义(我的猜测:WAVE LPCM 流),但我知道我不能简单地使用以下命令打开 FLAC 或 MP3 文件os.Open
并将流传递给 fingerprint.RawInfo.Src
。有一些 examples,但这些适用于以 .raw
.
结尾的文件
如何在 Go 中将 FLAC(或辅助 MP3)file/stream 转换为原始音频数据流?我的猜测是使用像 go-flac 这样的 Go FLAC 库,但我不确定从哪里开始。欢迎任何提示!
编辑
通过 go-flac 的 GetStreamInfo
应该可以访问 FLAC 文件的原始音频数据,然后可以使用 reader (我真的不喜欢 go-flac 的 GetStreamInfo
不是 return 和 io.Reader
;而是 return 和 []byte
,所以整个在进一步处理实际发生之前,流被加载到内存中。
使用以下代码,可以计算 FLAC 文件的指纹(基本上是 fpcalc
所做的):
package main
import (
"bytes"
"fmt"
"os"
"github.com/go-fingerprint/fingerprint"
"github.com/go-fingerprint/gochroma"
"github.com/go-flac/go-flac"
)
func main() {
f, err := flac.ParseFile(os.Args[1])
if err != nil {
panic(err)
}
si, err := f.GetStreamInfo()
if err != nil {
panic(err)
}
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: bytes.NewReader(f.Frames),
Channels: uint(si.ChannelCount),
Rate: uint(si.SampleRate),
MaxSeconds: 120,
},
)
fmt.Println(fprint)
}
不幸的是,上面的代码没有 return 与 fpcalc
相同的指纹。我做错了什么?
我最终得到了以下代码,它使用 github.com/eaburns/flac (as Steven Penny pointed out) and then passes the data over to fingerprint/gochroma 将 FLAC 文件解码为原始音频数据。
对于同一个 FLAC 文件,生成的指纹似乎与 fpcalc
报告的指纹不一样,但是当使用生成的指纹查询 AcoustID 数据库时,结果是正确的。
package main
import (
"bytes"
"fmt"
"log"
"os"
"github.com/eaburns/flac"
"github.com/go-fingerprint/fingerprint"
"github.com/go-fingerprint/gochroma"
)
func main() {
if len(os.Args) != 2 {
log.Fatalf("usage: go run fpcalc.go FILE")
}
f, err := os.Open(os.Args[1])
if err != nil {
log.Fatalf("os.Open(%s): %s", os.Args[1], err)
}
defer f.Close()
d, metadata, err := flac.Decode(f)
if err != nil {
log.Fatalf("flac.Decode: %s", err)
}
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: bytes.NewBuffer(d),
Channels: uint(metadata.NChannels),
Rate: uint(metadata.SampleRate),
MaxSeconds: 120,
},
)
if err != nil {
log.Fatalf("fpcalc.Fingerprint: %s", err)
}
fmt.Println(fprint)
}
我想使用 Go 中的 chromaprint 库创建 FLAC 或 MP3 文件的声学指纹。我一直在研究以下两个 Go 库:
- gochroma,去绑定 chromaprint
- fingerprint
使用以下代码,可以创建“原始音频数据流”的指纹(其中 reader
属于 io.Reader
类型):
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: reader,
Channels: 2,
Rate: 44100,
MaxSeconds: 120,
}
)
不幸的是,我无法弄清楚“原始音频数据流”的确切含义(我的猜测:WAVE LPCM 流),但我知道我不能简单地使用以下命令打开 FLAC 或 MP3 文件os.Open
并将流传递给 fingerprint.RawInfo.Src
。有一些 examples,但这些适用于以 .raw
.
如何在 Go 中将 FLAC(或辅助 MP3)file/stream 转换为原始音频数据流?我的猜测是使用像 go-flac 这样的 Go FLAC 库,但我不确定从哪里开始。欢迎任何提示!
编辑
通过 go-flac 的 GetStreamInfo
应该可以访问 FLAC 文件的原始音频数据,然后可以使用 reader (我真的不喜欢 go-flac 的 GetStreamInfo
不是 return 和 io.Reader
;而是 return 和 []byte
,所以整个在进一步处理实际发生之前,流被加载到内存中。
使用以下代码,可以计算 FLAC 文件的指纹(基本上是 fpcalc
所做的):
package main
import (
"bytes"
"fmt"
"os"
"github.com/go-fingerprint/fingerprint"
"github.com/go-fingerprint/gochroma"
"github.com/go-flac/go-flac"
)
func main() {
f, err := flac.ParseFile(os.Args[1])
if err != nil {
panic(err)
}
si, err := f.GetStreamInfo()
if err != nil {
panic(err)
}
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: bytes.NewReader(f.Frames),
Channels: uint(si.ChannelCount),
Rate: uint(si.SampleRate),
MaxSeconds: 120,
},
)
fmt.Println(fprint)
}
不幸的是,上面的代码没有 return 与 fpcalc
相同的指纹。我做错了什么?
我最终得到了以下代码,它使用 github.com/eaburns/flac (as Steven Penny pointed out) and then passes the data over to fingerprint/gochroma 将 FLAC 文件解码为原始音频数据。
对于同一个 FLAC 文件,生成的指纹似乎与 fpcalc
报告的指纹不一样,但是当使用生成的指纹查询 AcoustID 数据库时,结果是正确的。
package main
import (
"bytes"
"fmt"
"log"
"os"
"github.com/eaburns/flac"
"github.com/go-fingerprint/fingerprint"
"github.com/go-fingerprint/gochroma"
)
func main() {
if len(os.Args) != 2 {
log.Fatalf("usage: go run fpcalc.go FILE")
}
f, err := os.Open(os.Args[1])
if err != nil {
log.Fatalf("os.Open(%s): %s", os.Args[1], err)
}
defer f.Close()
d, metadata, err := flac.Decode(f)
if err != nil {
log.Fatalf("flac.Decode: %s", err)
}
fpcalc := gochroma.New(gochroma.AlgorithmDefault)
defer fpcalc.Close()
fprint, err := fpcalc.Fingerprint(
fingerprint.RawInfo{
Src: bytes.NewBuffer(d),
Channels: uint(metadata.NChannels),
Rate: uint(metadata.SampleRate),
MaxSeconds: 120,
},
)
if err != nil {
log.Fatalf("fpcalc.Fingerprint: %s", err)
}
fmt.Println(fprint)
}