Как получить и распечатать mp3 рамку Popularimeter с библиотекой golang id3-go - PullRequest
0 голосов
/ 21 октября 2018

Я хотел бы прочитать кадр Popularimeter из файла с id3-go .

Так выглядит кадр при печати с 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

Как получить значение Popularimeter (255/255) с библиотекой id3-go

1 Ответ

0 голосов
/ 29 октября 2018

Вы получаете ошибку сегментации, потому что mp3File.Frame("POPM") фактически возвращает значение nil.Я сузил его до V23FrameTypeMap в id3-go, в котором отсутствует рамка TRDC.Я действительно не знаком с внутренностями ID3, но, возможно, вам нужно проверить, действительно ли TRDC присутствует в V2.3, и, если это так, добавить недостающие идентификаторы в V23FrameTypeMap в id3-go.

Поскольку изучать ID3 было бы слишком сложно, мне удалось получить тег POPM, используя другую библиотеку https://github.com/dhowden/tag

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

, которая выдает:

traktor@native-instruments.de

Редактировать: я принял TDRC за TRDC, моя ошибка.В любом случае, вот что вам нужно сделать, чтобы получить поле POPM, используя id3-go

Добавьте следующее в V23FrameTypeMap в github.com/mikkyang/id3-go/v2/idv23.go

V23FrameTypeMap = map[string]FrameType{
    //...
    "TDRC": FrameType{id: "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.Затем вы можете получить доступ к рейтингу 255/255 от 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
}
...