如何使用 golang id3-go 库获取和打印 mp3 Popularmeter 框架

Posted

技术标签:

【中文标题】如何使用 golang id3-go 库获取和打印 mp3 Popularmeter 框架【英文标题】:How to get and print mp3 Popularimeter frame with golang id3-go library 【发布时间】:2018-10-21 09:58:42 【问题描述】:

我想从带有id3-go 的文件中读取Popularimeter 框架。

这是使用mutagen-inspect 打印时框架的外观:

$ mutagen-inspect samples/with_popm.mp3 | grep POPM
POPM=traktor@native-instruments.de=0 255/255

我想从文件中读取值 (255/255)。由于找不到任何文档,我的幼稚做法是:

popFrame := mp3File.Frame("POPM")
log.Println(popFrame.String())

但是当我运行它时(在带有和不带有流行量表标签的文件上),我得到了分段错误:

$ ./id3-go-popm-example samples/with_popm.mp3 
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x4ac302]

goroutine 1 [running]:
main.main()
    /home/ifischer/src/rivamp/rivamp-dist/id3-go-popm-example/main.go:21 +0xd2
$ ./id3-go-popm-example samples/without_popm.mp3 
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x4ac302]

goroutine 1 [running]:
main.main()
    /home/ifischer/src/rivamp/rivamp-dist/id3-go-popm-example/main.go:21 +0xd2

我在此处设置了一个示例存储库,其中包含两个示例文件(一个带有,一个没有流行的框架):https://github.com/ifischer/id3-go-popm-example

如何使用 id3-go 库获取 Popularmeter 值 (255/255)?

【问题讨论】:

实际的段错误/回溯也可能会有所帮助。 @ShiDoiSi 用段错误更新了问题 我刚刚完成了对 id3-go 库的检查,这绝对是第 3 方的问题。可能的解决方案是: 1. 修复 id3-go 上的问题; 2.或者只是使用另一个库,比如@ssemilla's answer 如果你真的需要使用id3-go,我已经添加了修复,这是一个单行修复,因为它只是缺少TDRC 字段。 我还添加了代码 sn-p 来解析流行度计,因为它似乎不包含在 id3-go 中。我希望这已经回答了这个问题。 【参考方案1】:

您遇到了分段错误,因为 mp3File.Frame("POPM") 实际上返回了 nil 值。我已将其缩小到id3-go 中的V23FrameTypeMap,它缺少TRDC 框架。我真的不熟悉 ID3 的内部结构,但也许您需要检查 TRDC 是否真的在 V2.3 中,如果是,请将缺少的 id 添加到 id3-go 中的 V23FrameTypeMap 中。

由于学习 ID3 太麻烦,我已经设法使用另一个库 https://github.com/dhowden/tag 获得了 POPM 标记

f, _ := os.Open("with_popm.mp3")
m, _ := tag.ReadFrom(f)
fmt.Printf("%s\n", m.Raw()["POPM"])

哪个输出:

traktor@native-instruments.de

编辑:我把TDRC 误认为TRDC,我的错。无论如何,这是使用 id3-go 获取 POPM 字段所需的操作

V23FrameTypeMap中添加以下github.com/mikkyang/id3-go/v2/idv23.go

V23FrameTypeMap = map[string]FrameType
    //...
    "TDRC": FrameTypeid: "TDRC", description: "Recording Date", constructor: ParseTextFrame,

然后您可以轻松获取 POPM 字段,例如

package main

import (
    "fmt"
    id3 "github.com/mikkyang/id3-go"
)

func main() 

    f, _ := id3.Open("with_popm.mp3")
    p := f.Frame("POPM")
    fmt.Printf("%s\n", p.Bytes())


编辑 2:我添加了一种方法,以便您可以解析 POPM 字段。然后您可以从Popularimeter.Rating 访问评级 255/255:

import (
    "bytes"
    "encoding/binary"
    "errors"
    "fmt"

    id3 "github.com/mikkyang/id3-go"
)

func main() 

    f, _ := id3.Open("with_popm.mp3")
    popm := f.Frame("POPM")
    popularimeter, _ := FromData(popm.Bytes())
    fmt.Println(popularimeter)


type Rating uint8

func (r Rating) String() string 
    if r == 0 
        return "unknown"
    
    return fmt.Sprintf("%d/255", r)


type Popularimeter struct 
    Email   string
    Rating  Rating
    Counter uint32


func FromData(data []byte) (*Popularimeter, error) 

    tokens := bytes.SplitN(data, []byte0x0, 2)
    // Pupolarimeter: <string>, null, 1byte rating, 4bytes counter
    if len(tokens) != 2 || len(tokens[1]) != 5 
        return nil, errors.New("invalid Popularimeter")
    

    return &Popularimeter
        Email:   string(tokens[0]),
        Rating:  Rating(tokens[1][0]),
        Counter: binary.BigEndian.Uint32(tokens[1][1:]),
    , nil

【讨论】:

答案值得赏金,尤其是解释!但是最好使用 id3-go,因为它也可以修改 ID3 标签 昨晚我很困,把TDRC误认为是TRDC。无论如何,答案已被编辑,因此您可以使用 id3-go 解析 POPM

以上是关于如何使用 golang id3-go 库获取和打印 mp3 Popularmeter 框架的主要内容,如果未能解决你的问题,请参考以下文章

Golang 日志接口应用实战

Golang使用pkg-config自动获取头文件和链接库的方法

golang获取命令行参数

如何使用 golang 实现自定义裁剪

如何使用 golang 在网络打印机上打印文件或格式化文本

golang 获取statuscode