duanniling0018 2018-10-21 09:58
浏览 249

如何使用golang id3-go库获取和打印mp3流行度表框架

I would like to read the Popularimeter frame from a file with id3-go.

This is how the frame looks like when printing with mutagen-inspect:

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

I would like to read the value (255/255) from the file. As I could not find any documentation, my naive approach is:

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

But when I run this (on a file with and also without a popularimeter tag), I get segmentation faults:

$ ./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

I setup a sample repository containing two sample files (one with, one without popularimeter frame) here: https://github.com/ifischer/id3-go-popm-example

How to I get the Popularimeter value (255/255) with id3-go library?

  • 写回答

1条回答 默认 最新

  • dqp10099 2018-10-29 14:19
    关注

    You're getting a segmentation fault because mp3File.Frame("POPM") is actually returning a nil value. I've narrowed it down to the V23FrameTypeMap in id3-go which lacks the TRDC frame. I'm really not familiar with the internals of ID3 but maybe you need to check if TRDC is really in V2.3 and if it is, add the missing ids in V23FrameTypeMap in id3-go.

    Since it would be too much of a hassle to learn ID3, I've managed to get the POPM tag using another library https://github.com/dhowden/tag

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

    which outputs:

    traktor@native-instruments.de
    

    Edit: I mistook TDRC as TRDC, my mistake. Anyway, here is what you need to do to get the POPM field using id3-go

    Add the following in V23FrameTypeMap in github.com/mikkyang/id3-go/v2/idv23.go

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

    Then you can easily get the POPM field e.g.

    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
    ", p.Bytes())
    
    }
    

    Edit 2: I've added a way so that you can parse the POPM field. You can then access the rating 255/255 from Popularimeter.Rating:

    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, []byte{0x0}, 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
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置