在不考虑标题的情况下计算音频文件的校验和

时间:2008-12-08 23:14:07

标签: file audio checksum

我想以编程方式创建音频文件的SHA1校验和(MP3,Ogg Vorbis,Flac)。 要求是校验和应该稳定,即使标题(例如ID3)改变
注意:音频文件没有CRC

这是我现在尝试的:

1)使用Perl和MPEG::Audio::Frame

读取+散列所有MPEG帧
my $sha1 = Digest::SHA1->new;
while (my $frame = MPEG::Audio::Frame->read(\*FH)) {
    $sha1->add($frame->content());
}

2)使用Python和libmad (pymad)

解码+散列所有MPEG帧
mf = mad.MadFile(path)
sha1 = hashlib.sha1()

while 1:
    buf = mf.read()
    if (buf is None):
        break
    sha1.update(buf)

3)使用mp3cat

> mp3cat - - < file.mp3 | sha1sum

但是,这些方法都没有提供稳定校验和。也就是说,在某些案例中,在使用picard重新标记文件后,校验和发生了更改。

是否有任何图书馆已经提供了我想要的内容? 我不关心编程语言......

更新的 我进一步调试了这个案例。 libmad校验和不一致似乎发生在libmad遇到一些解码错误的情况下,例如“Huffman data overrun(0x0238)”。 因为在许多mp3文件中确实发生了这种情况,我不确定它是否真的表明文件损坏了......

5 个答案:

答案 0 :(得分:3)

如果您正在为实际音乐寻找稳定的哈希值,您可能需要查看libOFA。您当前的方法会给您不同的结果,因为格式可以嵌入标签。此外,如果你想让两首不同的同一首歌的文件返回相同的哈希值,你需要考虑比特率和采样频率等事项。

另一方面,libOFA可以为您提供可在格式和不同编码之间使用的稳定哈希。可能是你想要的吗?

答案 1 :(得分:2)

我需要工具来快速检查我的MP3 / OGG库是否仍然有效。 对于MP3,我发现mp3md5.py(http://snipplr.com/view/4025/mp3-checksum-in-id3-tag/)可以完成这项工作,但是没有简单的OGG Vorbis工具,但我编写了一个小的bash脚本来为我做这个。 这两个工具都应该容忍修改注释/ ID3Tag。

#!/bin/bash

# This bash script appends an MD5SUM to the vorbiscomment and/or verifies it if it exists
# Later modification of the vorbis comment does not alter the MD5SUM
# Julian M.K.

FILE="$1"

if [[ ! -f "$FILE" || ! -r "$FILE" || ! -w "$FILE" ]] ; then
  echo "File $FILE" does not exist or is not readable or writable
  exit 1
fi

OLDCRC=`vorbiscomment "$FILE" | grep ^CRC=|cut -d "=" -f 2`
NEWCRC=`ogginfo "$FILE" |grep "Total data length:" |cut -d ":" -f 2 | md5sum |cut -d " " -f 1`

if [[ "$OLDCRC" == "" ]] ; then
  echo "ADDED $FILE  $NEWCRC"
  vorbiscomment -a -t "CRC=$NEWCRC" "$FILE" 
  # rewrite CRC to get proper data length, I dont know why this is necessary
  NEWCRC=`ogginfo "$FILE" |grep "Total data length:" |cut -d ":" -f 2 | md5sum |cut -d " " -f 1`
  vorbiscomment -w -t "CRC=$NEWCRC" "$FILE" 
elif [[ "$OLDCRC" == "$NEWCRC" ]]  ; then
  echo "VERIFIED $FILE"
else
  echo "FAILURE $FILE -- $OLDCRC - $NEWCRC"
fi

答案 2 :(得分:0)

Bene,如果我是你,(而且我正在处理与你想做的事情非常相似的事情),我会哈希mp3数据块。 (首先将其提取到原始数据,然后将其写入磁盘,这样您就知道自己在处理什么了)。然后,修改ID3标签。再次哈希您的数据。现在,如果它发生变化,请比较两组原始数据并找出它发生了哪些变化。机会是,你可能在某个地方过度踩到边界。如果我记得,MP3文件以FF F8开头。好吧,至少框架确实如此。

我对你的发现很感兴趣,因为我还在写我的所有代码来处理指纹等,还没有得到实际的散列。

答案 3 :(得分:0)

我正在尝试做同样的事情。我使用MD5而不是SHA1。我开始使用mp3tag(www.mp3tag.de/en/)导出音频校验和;然后制作了一个类似于你的Perl脚本来做同样的事情。然后我从测试文件中删除了所有标签,音频校验和保持不变。

这是剧本:

use MPEG::Audio::Frame;
use Digest::MD5 qw(md5_hex);
use strict;

my $file = 'E:\Music\MP3\Russensoul\01 - 5nizza , Soldat (Russensoul - Russensoul).mp3';
my $mp3tag_audio_md5 = lc '2EDFBD62995A46A45CEEC08C1F303486';

my $md5 = Digest::MD5->new;

open(FILE, $file) or die "Cannot open $file : $!\n";
binmode FILE;

while(my $frame = MPEG::Audio::Frame->read(\*FILE)){
    $md5->add($frame->asbin);
}

print '$md5->hexdigest  : ', $md5->hexdigest, "\n",
      'mp3tag_audio_md5 : ', $mp3tag_audio_md5,  "\n",
      ;

用于修改标签的任何内容有时也会修改mp3标题吗?

答案 4 :(得分:0)

有一种简单而稳定的方法可以做到这一点。只需复制文件并从其中删除所有标签(例如使用mutagen.id3),然后获取生成文件的哈希值即可。

此方法的唯一缺点是它的性能。