mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-04 13:07:36 +03:00
Add MBIDs to media_file, album and artist
This commit is contained in:
parent
64ccb4d188
commit
6663c079e0
9 changed files with 138 additions and 2 deletions
57
db/migration/20200827130401_add_more_tags.go
Normal file
57
db/migration/20200827130401_add_more_tags.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"github.com/pressly/goose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
goose.AddMigration(upAddMoreTags, downAddMoreTags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func upAddMoreTags(tx *sql.Tx) error {
|
||||||
|
_, err := tx.Exec(`
|
||||||
|
alter table media_file
|
||||||
|
add mbz_track_id varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add mbz_album_id varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add mbz_artist_id varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add mbz_album_artist_id varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add mbz_album_type varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add mbz_album_comment varchar(255);
|
||||||
|
alter table media_file
|
||||||
|
add catalog_num varchar(255);
|
||||||
|
|
||||||
|
alter table album
|
||||||
|
add mbz_album_id varchar(255);
|
||||||
|
alter table album
|
||||||
|
add mbz_album_artist_id varchar(255);
|
||||||
|
alter table album
|
||||||
|
add mbz_album_type varchar(255);
|
||||||
|
alter table album
|
||||||
|
add mbz_album_comment varchar(255);
|
||||||
|
alter table album
|
||||||
|
add catalog_num varchar(255);
|
||||||
|
|
||||||
|
create index if not exists album_mbz_album_type
|
||||||
|
on album (mbz_album_type);
|
||||||
|
|
||||||
|
alter table artist
|
||||||
|
add mbz_artist_id varchar(255);
|
||||||
|
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
notice(tx, "A full rescan needs to be performed to import more tags")
|
||||||
|
return forceFullRescan(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func downAddMoreTags(tx *sql.Tx) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -9,9 +9,9 @@ type Album struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CoverArtPath string `json:"coverArtPath"`
|
CoverArtPath string `json:"coverArtPath"`
|
||||||
CoverArtId string `json:"coverArtId"`
|
CoverArtId string `json:"coverArtId"`
|
||||||
ArtistID string `json:"artistId" orm:"pk;column(artist_id)"`
|
ArtistID string `json:"artistId" orm:"column(artist_id)"`
|
||||||
Artist string `json:"artist"`
|
Artist string `json:"artist"`
|
||||||
AlbumArtistID string `json:"albumArtistId" orm:"pk;column(album_artist_id)"`
|
AlbumArtistID string `json:"albumArtistId" orm:"column(album_artist_id)"`
|
||||||
AlbumArtist string `json:"albumArtist"`
|
AlbumArtist string `json:"albumArtist"`
|
||||||
MaxYear int `json:"maxYear"`
|
MaxYear int `json:"maxYear"`
|
||||||
MinYear int `json:"minYear"`
|
MinYear int `json:"minYear"`
|
||||||
|
@ -25,6 +25,11 @@ type Album struct {
|
||||||
SortAlbumArtistName string `json:"sortAlbumArtistName"`
|
SortAlbumArtistName string `json:"sortAlbumArtistName"`
|
||||||
OrderAlbumName string `json:"orderAlbumName"`
|
OrderAlbumName string `json:"orderAlbumName"`
|
||||||
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
||||||
|
CatalogNum string `json:"catalogNum"`
|
||||||
|
MbzAlbumID string `json:"mbzAlbumId" orm:"column(mbz_album_id)"`
|
||||||
|
MbzAlbumArtistID string `json:"mbzAlbumArtistId" orm:"column(mbz_album_artist_id)"`
|
||||||
|
MbzAlbumType string `json:"mbzAlbumType"`
|
||||||
|
MbzAlbumComment string `json:"mbzAlbumComment"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
|
|
|
@ -11,6 +11,7 @@ type Artist struct {
|
||||||
SortArtistName string `json:"sortArtistName"`
|
SortArtistName string `json:"sortArtistName"`
|
||||||
OrderArtistName string `json:"orderArtistName"`
|
OrderArtistName string `json:"orderArtistName"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
|
MbzArtistID string `json:"mbzArtistId" orm:"column(mbz_artist_id)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Artists []Artist
|
type Artists []Artist
|
||||||
|
|
|
@ -37,6 +37,13 @@ type MediaFile struct {
|
||||||
OrderArtistName string `json:"orderArtistName"`
|
OrderArtistName string `json:"orderArtistName"`
|
||||||
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
OrderAlbumArtistName string `json:"orderAlbumArtistName"`
|
||||||
Compilation bool `json:"compilation"`
|
Compilation bool `json:"compilation"`
|
||||||
|
CatalogNum string `json:"catalogNum"`
|
||||||
|
MbzTrackID string `json:"mbzTrackId" orm:"column(mbz_track_id)"`
|
||||||
|
MbzAlbumID string `json:"mbzAlbumId" orm:"column(mbz_album_id)"`
|
||||||
|
MbzArtistID string `json:"mbzArtistId" orm:"column(mbz_artist_id)"`
|
||||||
|
MbzAlbumArtistID string `json:"mbzAlbumArtistId" orm:"column(mbz_album_artist_id)"`
|
||||||
|
MbzAlbumType string `json:"mbzAlbumType"`
|
||||||
|
MbzAlbumComment string `json:"mbzAlbumComment"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ func (r *albumRepository) refresh(ids ...string) error {
|
||||||
sel := Select(`f.album_id as id, f.album as name, f.artist, f.album_artist, f.artist_id, f.album_artist_id,
|
sel := Select(`f.album_id as id, f.album as name, f.artist, f.album_artist, f.artist_id, f.album_artist_id,
|
||||||
f.sort_album_name, f.sort_artist_name, f.sort_album_artist_name,
|
f.sort_album_name, f.sort_artist_name, f.sort_album_artist_name,
|
||||||
f.order_album_name, f.order_album_artist_name, f.path,
|
f.order_album_name, f.order_album_artist_name, f.path,
|
||||||
|
f.mbz_album_id, f.mbz_album_artist_id, f.mbz_album_type, f.mbz_album_comment, f.catalog_num,
|
||||||
f.compilation, f.genre, max(f.year) as max_year, sum(f.duration) as duration,
|
f.compilation, f.genre, max(f.year) as max_year, sum(f.duration) as duration,
|
||||||
count(f.id) as song_count, a.id as current_id,
|
count(f.id) as song_count, a.id as current_id,
|
||||||
group_concat(f.disc_subtitle, ' ') as disc_subtitles,
|
group_concat(f.disc_subtitle, ' ') as disc_subtitles,
|
||||||
|
|
|
@ -144,6 +144,7 @@ func (r *artistRepository) refresh(ids ...string) error {
|
||||||
}
|
}
|
||||||
var artists []refreshArtist
|
var artists []refreshArtist
|
||||||
sel := Select("f.album_artist_id as id", "f.album_artist as name", "count(*) as album_count", "a.id as current_id",
|
sel := Select("f.album_artist_id as id", "f.album_artist as name", "count(*) as album_count", "a.id as current_id",
|
||||||
|
"f.mbz_album_artist_id as mbz_artist_id",
|
||||||
"f.sort_album_artist_name as sort_artist_name", "f.order_album_artist_name as order_artist_name",
|
"f.sort_album_artist_name as sort_artist_name", "f.order_album_artist_name as order_artist_name",
|
||||||
"sum(f.song_count) as song_count", "sum(f.size) as size").
|
"sum(f.song_count) as song_count", "sum(f.size) as size").
|
||||||
From("album f").
|
From("album f").
|
||||||
|
|
|
@ -52,6 +52,13 @@ func (s *mediaFileMapper) toMediaFile(md metadata.Metadata) model.MediaFile {
|
||||||
mf.OrderAlbumName = sanitizeFieldForSorting(mf.Album)
|
mf.OrderAlbumName = sanitizeFieldForSorting(mf.Album)
|
||||||
mf.OrderArtistName = sanitizeFieldForSorting(mf.Artist)
|
mf.OrderArtistName = sanitizeFieldForSorting(mf.Artist)
|
||||||
mf.OrderAlbumArtistName = sanitizeFieldForSorting(mf.AlbumArtist)
|
mf.OrderAlbumArtistName = sanitizeFieldForSorting(mf.AlbumArtist)
|
||||||
|
mf.CatalogNum = md.CatalogNum()
|
||||||
|
mf.MbzTrackID = md.MbzTrackID()
|
||||||
|
mf.MbzAlbumID = md.MbzAlbumID()
|
||||||
|
mf.MbzArtistID = md.MbzArtistID()
|
||||||
|
mf.MbzAlbumArtistID = md.MbzAlbumArtistID()
|
||||||
|
mf.MbzAlbumType = md.MbzAlbumType()
|
||||||
|
mf.MbzAlbumComment = md.MbzAlbumComment()
|
||||||
|
|
||||||
// TODO Get Creation time. https://github.com/djherbis/times ?
|
// TODO Get Creation time. https://github.com/djherbis/times ?
|
||||||
mf.CreatedAt = md.ModificationTime()
|
mf.CreatedAt = md.ModificationTime()
|
||||||
|
|
|
@ -52,6 +52,37 @@ var _ = Describe("ffmpegExtractor", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("extractMetadata", func() {
|
Context("extractMetadata", func() {
|
||||||
|
It("extracts MusicBrainz custom tags", func() {
|
||||||
|
const output = `
|
||||||
|
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Colt 45 - Underground Post-Punk, Tropical Tapes, Lo Fi Electronics And Others Sounds From Brazil (1983 - 1993) Selected By Tetine/01-06 X.m4a':
|
||||||
|
Metadata:
|
||||||
|
title : X
|
||||||
|
artist : Saara Saara
|
||||||
|
composer : Servio Tulio & Raul Rachid
|
||||||
|
album : Colt 45 - Underground Post-Punk, Tropical Tapes, Lo Fi Electronics And Others Sounds From Brazil (1983 - 1993) Selected By Tetine
|
||||||
|
genre : Alternative
|
||||||
|
MusicBrainz Release Group Id: 0
|
||||||
|
MusicBrainz Album Artist Id: 194
|
||||||
|
MusicBrainz Artist Id: 200455
|
||||||
|
MusicBrainz Album Release Country: Unknown
|
||||||
|
MusicBrainz Album Id: 11406732
|
||||||
|
MusicBrainz Track Id: 11406732-6
|
||||||
|
Label : Slum Dunk Music
|
||||||
|
publisher : Slum Dunk Music
|
||||||
|
MusicBrainz Album Type: Compilation
|
||||||
|
MusicBrainz Album Comment: MP3
|
||||||
|
CATALOGNUMBER : SLUM DUNK MUSIC 009
|
||||||
|
`
|
||||||
|
md, _ := extractMetadata("tests/fixtures/test.mp3", output)
|
||||||
|
Expect(md.CatalogNum()).To(Equal("SLUM DUNK MUSIC 009"))
|
||||||
|
Expect(md.MbzTrackID()).To(Equal("11406732-6"))
|
||||||
|
Expect(md.MbzAlbumID()).To(Equal("11406732"))
|
||||||
|
Expect(md.MbzArtistID()).To(Equal("200455"))
|
||||||
|
Expect(md.MbzAlbumArtistID()).To(Equal("194"))
|
||||||
|
Expect(md.MbzAlbumType()).To(Equal("Compilation"))
|
||||||
|
Expect(md.MbzAlbumComment()).To(Equal("MP3"))
|
||||||
|
})
|
||||||
|
|
||||||
It("detects embedded cover art correctly", func() {
|
It("detects embedded cover art correctly", func() {
|
||||||
const output = `
|
const output = `
|
||||||
Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3':
|
Input #0, mp3, from '/Users/deluan/Music/iTunes/iTunes Media/Music/Compilations/Putumayo Presents Blues Lounge/09 Pablo's Blues.mp3':
|
||||||
|
|
|
@ -51,6 +51,13 @@ type Metadata interface {
|
||||||
HasPicture() bool
|
HasPicture() bool
|
||||||
Comment() string
|
Comment() string
|
||||||
Compilation() bool
|
Compilation() bool
|
||||||
|
CatalogNum() string
|
||||||
|
MbzTrackID() string
|
||||||
|
MbzAlbumID() string
|
||||||
|
MbzArtistID() string
|
||||||
|
MbzAlbumArtistID() string
|
||||||
|
MbzAlbumType() string
|
||||||
|
MbzAlbumComment() string
|
||||||
Duration() float32
|
Duration() float32
|
||||||
BitRate() int
|
BitRate() int
|
||||||
ModificationTime() time.Time
|
ModificationTime() time.Time
|
||||||
|
@ -87,6 +94,25 @@ func (m *baseMetadata) DiscNumber() (int, int) { return m.parseTuple("disc", "d
|
||||||
func (m *baseMetadata) DiscSubtitle() string {
|
func (m *baseMetadata) DiscSubtitle() string {
|
||||||
return m.getTag("tsst", "discsubtitle", "setsubtitle")
|
return m.getTag("tsst", "discsubtitle", "setsubtitle")
|
||||||
}
|
}
|
||||||
|
func (m *baseMetadata) CatalogNum() string { return m.getTag("catalognumber") }
|
||||||
|
func (m *baseMetadata) MbzTrackID() string {
|
||||||
|
return m.getTag("musicbrainz_trackid", "musicbrainz track id")
|
||||||
|
}
|
||||||
|
func (m *baseMetadata) MbzAlbumID() string {
|
||||||
|
return m.getTag("musicbrainz_albumid", "musicbrainz album id")
|
||||||
|
}
|
||||||
|
func (m *baseMetadata) MbzArtistID() string {
|
||||||
|
return m.getTag("musicbrainz_artistid", "musicbrainz artist id")
|
||||||
|
}
|
||||||
|
func (m *baseMetadata) MbzAlbumArtistID() string {
|
||||||
|
return m.getTag("musicbrainz_albumartistid", "musicbrainz album artist id")
|
||||||
|
}
|
||||||
|
func (m *baseMetadata) MbzAlbumType() string {
|
||||||
|
return m.getTag("musicbrainz_albumtype", "musicbrainz album type")
|
||||||
|
}
|
||||||
|
func (m *baseMetadata) MbzAlbumComment() string {
|
||||||
|
return m.getTag("musicbrainz_albumcomment", "musicbrainz album comment")
|
||||||
|
}
|
||||||
|
|
||||||
func (m *baseMetadata) ModificationTime() time.Time { return m.fileInfo.ModTime() }
|
func (m *baseMetadata) ModificationTime() time.Time { return m.fileInfo.ModTime() }
|
||||||
func (m *baseMetadata) Size() int64 { return m.fileInfo.Size() }
|
func (m *baseMetadata) Size() int64 { return m.fileInfo.Size() }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue