识别 MP3 文件之间的差异

识别 MP3 文件之间的差异

我有 2 个类似的旧目录树,其中包含 MP3 文件。我很高兴使用 diff 和 Rsync 等工具来识别和合并只存在于一侧或相同的文件,剩下一堆按位不同的文件。

在对两个实际上不同的文件运行 diff 时(使用 -a 标签强制进行文本分析),它会产生难以理解的乱码。我听了两边的文件,它们似乎都播放得很好(但每首歌要花将近 10 分钟,每首歌听两遍,我没听多少)

我怀疑这些差异是由于过去某些玩家通过修改 ID3 标签来“增强”我的收藏而造成的,但我不能确定。即使我发现 ID3 标签存在差异,我也想确认没有宇宙射线或文件复制错误问题损坏了任何文件。

想到的一种方法是找到差异的字节位置,并忽略每个文件前~10kb 中的所有更改,但我不知道如何做到这一点。

我有大约一百个左右在目录树中不同的文件。

我发现如何比较文件中的 mp3、flac 音频数据,忽略标题数据(ID3 标签)等?——但由于仅限于 Linux,我无法运行 alldup,而且从声音来看,它只能部分解决我的问题。

答案1

无可比拟根据主题

Beyond Compare 3 不能在 Linux 上作为控制台应用程序运行。它需要 X-Windows。

支持的 Linux 发行版

红帽企业 Linux 4-6

Fedora 4-14

Novell Suse Linux 企业桌面 10

openSUSE 10.3-11.2

Ubuntu 6.06-10.10

Debian 5.04

曼德里瓦 2010

答案2

Beyond Compare(上面提到)看起来是个不错的解决方案。我从未使用过它。关于 Xwindows 的部分只是意味着它希望在 GUI 中运行,而不是直接在命令行中运行。如果您安装了 GUI,那么 Xwindows 很可能已经正确安装在您的系统上。

关于如何进行的一些想法:

cmp -i 10kB 文件1 文件2

将在 Linux 上按字节比较两个任意文件,首先在每个文件上跳过 10kb。它甚至有一个选项可以跳过每个文件的不同字节数。-b 参数将打印出不同的字节,但这可能是一个很长的输出,因此如果您使用它,请将输出导入文件或 less。您必须决定跳过多少字节。我不知道答案。要有效地将其用于多个文件,您必须用 bash 或其他语言编写脚本。也许将它作为 find 命令的一部分与 exec 选项一起运行会有效。

将来,如果要查找重复文件,请查看 fdupes。这是一个专为此目的而设计的实用程序。当我还在想办法管理计算机上的照片时,我用过它,结果得到了一堆包含大量重复文件的目录。

https://code.google.com/p/fdupes/

另外,如果你在维基百科上查找 fdupes,你会发现条目中列出了大量 Linux 文件比较程序。

只是为了好玩,我看了一下:

http://www.id3.org/id3v2.4.0-structure

它指定了 id3 标签的结构。它“建议”将标签放在文件的开头,但也提供了在文件末尾添加其他标签的功能,因此除非没有人使用该选项,否则文件中的其他地方可能存在元信息,而不仅仅是开头。粗略查看规范会发现 id3 标签信息的长度是可变的,因此没有确切的字节数可以保证跳过它,但最初建议的 10k 应该足以跳过初始标签。

答案3

作为可能的解决方案,您可以使用任何工具将文件转换为不包含元数据信息的未压缩流(pcmwav),然后进行比较。对于转换,您可以使用任何软件,例如ffmpegsoxavidemux

例如我如何使用 ffmpeg

假设我有 2 个具有不同元数据的文件: $ diff Original.mp3 Possible-dup.mp3 ; echo $? Binary files Original.mp3 and Possible-dup.mp3 differ 强力比较会抱怨它们不同。

然后我们只需转换和区分主体: $ diff <( ffmpeg -loglevel 8 -i Original.mp3 -map_metadata -1 -f wav - ) <( ffmpeg -loglevel 8 -i Possible-dup.mp3 -map_metadata -1 -f wav - ) ; echo $? 0

当然,这 ; echo $?部分只是为了演示目的,以查看返回代码。

处理多个文件(遍历目录)

如果您想尝试集合中的重复项,则值得计算数据的校验和(任何如,,,crc),然后只需找到其中的冲突。md5sha2sha256

  1. 首先计算每个文件中数据的哈希值(并放入文件中进行下一步处理): for file in *.mp3; do printf "%s:%s\n" "$( ffmpeg -loglevel 8 -i "$file" -map_metadata -1 -f wav - | sha256sum | cut -d' ' -f1 )" "$file"; done > mp3data.hashes 对于您的情况,您可能只比较多个目录,例如: find -L orig-dir dir-with-duplicates -name '*.mp3' -print0 | while read -r -d $'\0' file; do printf "%s:%s\n" "$( ffmpeg -loglevel 8 -i \"$file\" -map_metadata -1 -f wav - | sha256sum | cut -d' ' -f1 )" "$file"; done > mp3data.hashes

文件将如下所示: $ cat mp3data.hashes ad48913a11de29ad4639253f2f06d8480b73d48a5f1d0aaa24271c0ba3998d02:file1.mp3 54320b708cea0771a8cf71fac24196a070836376dd83eedd619f247c2ece7480:file2.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Original.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Possible-dup.mp3 任何 RDBMS 都非常有用,可以汇总计数并选择此类数据。但继续使用纯命令行解决方案,您可能需要执行进一步的简单步骤。

查看重复的哈希值(如果有)(额外步骤来展示其工作原理,不需要查找重复项): $ count.by.regexp.awk '([0-9a-f]+):' mp3data.hashes [1:54320b708cea0771a8cf71fac24196a070836376dd83eedd619f247c2ece7480]=1 [1:1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f]=2 [1:ad48913a11de29ad4639253f2f06d8480b73d48a5f1d0aaa24271c0ba3998d02]=1

  1. 并一起列出按内容重复的文件 $ grep mp3data.hashes -f <( count.by.regexp.awk '([0-9a-f]+):' mp3data.hashes | grep -oP '(?<=\[1:).{64}(?!]=1$)' ) | sort 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Original.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Possible-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other.mp3

按正则表达式计数.awkawk一个用于计数正则表达式模式的简单脚本。

PS 稍微调整了https://superuser.com/a/1219353/435801

相关内容