专辑整理

Navidrome 为什么把一张专辑拆成好几张

有时候又反过来,把两张专辑并成一张。到底是什么在决定,我们在真实的 Navidrome 上核对过;每一种原因,用手头现有的工具怎么修。

规则

Navidrome 给每首歌算一个专辑 ID,ID 相同的歌就是同一张专辑。这个 ID 你看不到,但看得到它的结果:同一张专辑在曲库里出现两次,每一份里只有一部分歌;或者一张专辑缺了几首,缺的那几首待在另一张同名专辑里。

默认设置下,专辑 ID 取下面两条里第一条能用的:

  1. 歌曲带有 MusicBrainz 专辑编号(MUSICBRAINZ_ALBUMID),并且是合法的 UUID。有它就只看它,别的都不算。
  2. 没有的话,就把这四样合在一起:专辑艺人、专辑名、专辑版本、发行日期。

规则就这么多。文件放在哪个文件夹不算在内,碟号也不算。所以,只要各首歌在这四样里有一样对不上,或者只有一部分歌带了 MusicBrainz 编号,专辑就会被拆开;反过来,两张专辑只要这四样都一样,不管放在硬盘的哪里,都会被并成一张。

为了核对,我们用 ffmpeg 做了 22 张测试专辑,每张两首歌,每对之间只差一样东西,然后让一个全新的、默认设置的 Navidrome 0.63.2 去扫描。下面的表格列出了它对每一张的处理结果。另有三种情况是按规则推出来的,没有实际扫描,表里单独标了出来。

如果你在 Navidrome 的配置里改过 PID.Album,专辑 ID 就按你自己的写法来算,这一页的结论不能直接套用。

发行日期:最容易忽略的拆分原因

大多数标签编辑器只显示一个“年份”或“日期”。Navidrome 却把两个日期分开看:发行日期算在专辑 ID 里,日期(录音日期)不算。哪个标签算哪个,要看文件格式:

  • FLAC:RELEASEDATE 是发行日期,没有的话看 YEAR。DATE 不是。
  • MP3:TDRL 帧是发行日期。平常写年份的那个字段(TDRC,旧版标签里是 TYER)不是。
  • M4A:只有一个日期 ©day,Navidrome 把它当发行日期读。所以 M4A 文件里,普通的日期字段一不一致,专辑就会拆开。
编号两首歌差在哪里Navidrome 认成
T01 M4A:日期(©day)一首是 2020-01-01,另一首是 2021-02-02 2 张专辑
T16 M4A:日期(©day)一首只写了 2020,另一首写的是 2020-05-01 2 张专辑
T02 M4A:两首的日期(©day)相同 1 张专辑
T19 FLAC:RELEASEDATE 不同 2 张专辑
T04 FLAC:YEAR 不同 2 张专辑
R01 MP3:TDRL(ID3 的发行日期)不同 2 张专辑按规则推出,没有实测
T03 FLAC:DATE 不同 1 张专辑专辑的日期显示为空
T05 MP3:日期(TDRC)不同 1 张专辑专辑的日期显示为空

有两点值得注意。M4A 文件里,一首写 2020、另一首写 2020-05-01,是两个不同的发行日期,也就是两张专辑;一首一首下载的专辑,或者后来补进了加曲的专辑,常常就是这样。一张专辑里 FLAC 和 M4A 混放,标签看着一样也可能被拆开,也是同一个原因:M4A 那几首有发行日期,只有 DATE 的 FLAC 没有(按规则推出,没有实测)。另外,如果各首歌只是录音日期不同,专辑不会拆开,但专辑的日期会显示为空。

怎么修

给每首歌写上同一个发行日期,写在这种格式对应的标签里。用标签编辑器(Mp3tag、foobar2000、kid3、MusicBrainz Picard)的话,把这张专辑的歌全选上,日期只填一次。FLAC 也可以用命令行:

metaflac --remove-tag=RELEASEDATE --set-tag=RELEASEDATE=2020-05-01 *.flac

专辑显示不出年份的话,再把每首歌的 DATE 也改成一样。

合辑,和按艺人拆开的专辑

Navidrome 从 ALBUMARTIST 读专辑艺人。歌里没有这个标签,就看 ALBUMARTISTS;再没有,如果设了合辑标记,就是“Various Artists”;最后才轮到这首歌自己的第一个艺人。问题就出在最后这一步:没写专辑艺人的歌,会归到唱这首歌的人名下。

“第一个艺人”是指:歌里有 ARTISTS 标签的话,取它的第一个值;没有的话取 ARTIST,如果它只有一个值,就在  / 、 feat. 、 ft. 、;  这些地方切开取第一段。所以有嘉宾参与的歌不会把专辑拆开,而没写专辑艺人的合辑,会按艺人拆成一人一张,每首歌都是不同歌手的话,曲库里就是一排封面一样的专辑。

编号两首歌差在哪里Navidrome 认成
T07 两首都没有专辑艺人;艺人一首是 Alpha,另一首是 Beta 2 张专辑
T08 同样的两首歌,都加上合辑标记(COMPILATION=1) 1 张专辑归在“Various Artists”名下
T06 两首都没有专辑艺人;艺人一首是 Solo,另一首是 Solo feat. Guest 1 张专辑归在 Solo 名下
T14 只有一首写了专辑艺人,而且和另一首的艺人同名 1 张专辑
T15 只有一首写了专辑艺人,而且和另一首的艺人不同名 2 张专辑

怎么修

每首歌写上同一个专辑艺人。合辑一般写“Various Artists”;也可以给每首歌都设上合辑标记(FLAC 里是 COMPILATION=1,MP3 里是 TCMP,M4A 里是 cpil;编辑器里一般叫“合辑”或“Part of a compilation”)。

metaflac --remove-tag=ALBUMARTIST --set-tag="ALBUMARTIST=Various Artists" *.flac

看起来一样的专辑名

曲库里出现两张名字一模一样的专辑时,名字往往并不真的一样。Navidrome 不区分字母大小写,也把弯引号和直引号、各种破折号当成一样,除此之外的差别都算数。

编号两首歌差在哪里Navidrome 认成
T09 专辑名和专辑艺人只差在字母大小写上 1 张专辑
T17 专辑名里的撇号一首是直的(Don't),另一首是弯的(Don’t) 1 张专辑
T10 专辑名里一首是普通空格,另一首是不换行空格(NBSP) 2 张专辑
T21 其中一首的专辑名末尾多了一个空格 2 张专辑
T20 专辑名里的 é,一首存成一个字符(NFC),另一首存成 e 加重音符(NFD) 2 张专辑

不换行空格、末尾多出的空格、重音字母的另一种存法,在大多数标签编辑器里都看不出来,所以两张专辑看着完全一样。把所有歌全选上,专辑名重新输入一次,写进去的字符就一致了。

MusicBrainz 专辑编号

MusicBrainz 专辑编号比别的都优先,这一点两头都管用。

编号两首歌差在哪里Navidrome 认成
T12 只有一首带 MUSICBRAINZ_ALBUMID 2 张专辑
T13 专辑名和专辑艺人都不一样,MUSICBRAINZ_ALBUMID 相同 1 张专辑

从别处补来的歌,或者单独重新打过标签的歌,可能缺了其他歌都有的编号,于是自成一张专辑。把编号补到缺的那几首上,或者干脆从所有歌里删掉;用 MusicBrainz Picard 对整张专辑打标签,会给每一首都写上。不是合法 UUID 的编号会被忽略(按规则推出,没有实测)。

metaflac --remove-tag=MUSICBRAINZ_ALBUMID *.flac

专辑版本

ALBUMVERSION(没有的话看 MUSICBRAINZ_ALBUMCOMMENT)本来是用来把豪华版和原版分开的。只有一部分歌带着它,专辑就会被拆开。

编号两首歌差在哪里Navidrome 认成
T18 只有一首带 ALBUMVERSION 2 张专辑

每首歌写同一个版本,或者都不写。

多碟专辑被拆成几张

碟号不算在专辑 ID 里,所以光是分碟,不会把专辑拆开。一套双碟专辑显示成两张,一定是两张碟在上面说的这几样里有一样对不上。常见的是专辑名里带了碟号(Album (Disc 1) 和 Album (Disc 2) 是两个不同的名字),或者只有一张碟写了发行日期。两张碟用同一个专辑名,碟号写进 DISCNUMBER。(按规则推出,扫描里没有多碟的例子。)

两张专辑并成一张

文件夹不算在专辑 ID 里,所以标签相同的两张专辑,即使放在不同的文件夹,对 Navidrome 来说也是一张。完全没有专辑名的歌,不管在曲库的哪里,同一个艺人的都会被归进同一张“[Unknown Album]”。连艺人都没有的歌,会归到“[Unknown Artist]”下面。

编号两首歌差在哪里Navidrome 认成
T11 标签完全一样,两首歌放在两个不同的文件夹里 1 张专辑
T22 两个文件夹里两首不相干的歌,都没有专辑名,艺人相同 1 张专辑都进了“[Unknown Album]”

怎么修

每首歌都写上专辑名。同一张专辑的两个版本想分开放,就给它们写上不同的发行日期、专辑版本,或者各自的 MusicBrainz 编号。

封面不显示

Navidrome 找专辑封面有固定的顺序:先找专辑文件夹里叫 cover 的图片,然后是 folder、front,再然后才是嵌在歌里的图片。叫 scan.jpg 或者以专辑名命名的图片不在其中。这一条不在扫描范围内,依据的是 Navidrome 封面文档里 CoverArtPriority 设置的默认值:cover.*, folder.*, front.*, embedded, external。

最稳妥的办法是两样都做:专辑文件夹里放一个 cover.jpg,同一张图再嵌进每一首歌,照顾那些只显示单曲封面的客户端。

用分号连起来的艺人

Navidrome 把 ARTISTS 当成一个列表来读,一个值一位艺人,从不把一个值切开。如果写成一个值 Nujabes; Shing02,那就是一位名字里带分号的艺人:它会有自己的艺人页;在没写专辑艺人的歌上,它还会成为专辑艺人。

编号两首歌差在哪里Navidrome 认成
R02 都没有专辑艺人;ARTISTS 一首是单独一个值 Nujabes; Shing02,另一首是 Nujabes 2 张专辑按规则推出,没有实测
R03 都没有专辑艺人;ARTISTS 一首是单独一个值 A;B,另一首是 A 2 张专辑按规则推出,没有实测

正确的写法是每位艺人各写一次这个标签。FLAC 里:

metaflac --remove-tag=ARTISTS --set-tag=ARTISTS=Nujabes --set-tag=ARTISTS=Shing02 track.flac

写完用 metaflac --export-tags-to=- track.flac 检查,每个值单独一行。别用 ffprobe 看:它会把重复的值用“;”连起来显示,对的写法和错的写法在它眼里一模一样。

各个标签在文件里叫什么

同一个字段,在不同格式的文件里名字不一样。下面是本站读写时用的名字,经由 TagLib 读写;Navidrome 读标签用的也是 TagLib。

字段FLACMP3M4A
专辑名ALBUMTALB©alb
专辑艺人ALBUMARTISTTPE2aART
发行日期RELEASEDATE,没有则 YEARTDRL©day
日期(不算在专辑 ID 里)DATETDRC没有
专辑版本ALBUMVERSIONTXXX:ALBUMVERSION----:com.apple.iTunes:ALBUMVERSION
MusicBrainz 专辑编号MUSICBRAINZ_ALBUMIDTXXX:MusicBrainz Album Id----:com.apple.iTunes:MusicBrainz Album Id
合辑标记COMPILATIONTCMPcpil

测试条件

在 Docker 里新装的 Navidrome 0.63.2,默认配置,扫描。每张测试专辑是 ffmpeg 生成的两首短曲,各用一个独立的专辑名,保证不同的测试之间不会互相合并。所有文件、每个文件写了哪些标签、Navidrome 认成了几张专辑,都在仓库里的 navidrome.groundtruth.js,规则本身在 identity.js。

表里标着“按规则推出,没有实测”的几项,是从同一条规则推出来的,没有经过 Navidrome 扫描。Navidrome 之后又发了新版本(写这一页时最新是 0.64.2),以后的版本也可能改默认设置。你看到的情况和这一页对不上的话,这个扫描很容易重做一遍。

本站是个人项目,与 Navidrome 官方无关。Navidrome 自己对打标签的说明,见它的标签指南。

交给专辑整理来修

把专辑的文件夹或 zip 拖到专辑整理页面上。它会告诉你 Navidrome 会把它认成几张、是上面哪几种原因造成的,在浏览器里修好标签、不重新编码音频,再打包成 zip 还给你。不上传任何文件。