我需要创建一个元数据无关的mp3文件哈希(即在重新标记后可以计算相同的哈希)。如何仅将音频数据提取到内存中,而不实际通过解压器运行它?
MAD似乎是一个很好的起点 - http://www.underbit.com/products/mad/,但似乎没有明显暴露用于此操作的函数。
任何指针都将不胜感激!
MAD似乎是一个很好的起点 - http://www.underbit.com/products/mad/,但似乎没有明显暴露用于此操作的函数。
任何指针都将不胜感激!
如何仅将音频数据提取到内存中,而不实际通过解压缩器运行它?
你无法在不解压缩的情况下提取音频数据 - 它已经被压缩了!但是,如果你只想要原始压缩流,请继续阅读!
典型的mp3音频文件将被分成几个部分:
[可能是元标签]
[可能是垃圾]
[可能是XING/LAME标签 [可能还有更多垃圾]]
[mp3音频帧]
[可能是元标签]
可能是元标签:大多数mp3音频文件的开头都会有id3标签。请注意,一些用户可能会使用不同的标记格式(例如APE),因此你需要考虑到这一点。
可能是垃圾信息:一些mp3音频文件经过多次标记、重新标记和转换,元标记头可能无法提供第一个音频帧的准确偏移量,因为之前标记的残留物可能会留下来。foobar2000有一个选项可以解决这个问题。
可能是XING/LAME标签:它们包含在mp3音频帧中,但不包含实际的音频。madplay有代码可以显示如何读取和解析这些帧。XING/LAME头可能有一个帧计数,因此值得解析这些头。同样,如果文件经历了许多不同的标记器和编辑器,则可能会在这里找到几个格式不正确、无效的音频帧。
MP3音频帧:实际的压缩流,分成“帧”。每个帧都以同步位模式0xFFE开头。
可能是元标记:在文件末尾发现更多的元标记并不罕见。id3v1、APE、歌词都可以在这里找到。
为了找到音频帧的偏移量,你需要解析任何元标头,然后开始寻找同步位模式。你不能从文件开头开始寻找同步模式,因为并不是所有标签支持unsynchronization,所以元标头本身可能包含0xFFE模式。ffmpeg可以单独计算音频文件的音频片段的MD5哈希值,即不包括元数据。
使用方法:
ffmpeg -v -i $file -acodec copy -f md5 -
#include <fcntl.h>
#define DUMPTAGS
int main(int argc, char **argv){
unsigned char buf[4096];
int len,fd = open(argv[1],O_RDONLY);
while (len=read(fd,buf,10)){ // handle ID3v2 tags (maybe multiple)
if (buf[0]=='I' && buf[1]=='D' && buf[2]=='3'){
len=read(fd,buf,buf[9]|(buf[8] << 7)|(buf[7] << 14)|(buf[6] << 21));
#ifdef DUMPTAGS
write(2,buf,len);
#endif
} else break;
}
while (write(1,buf,len)){
unsigned char tag[3] = {'T','A','G'}, *end;
len=read(fd,buf,4096);
end=(unsigned char *)memmem(buf,len,&tag,3);
if (end){ //handle ID3v1 tag (should only be 1)
write(1,buf,end-buf);
#ifdef DUMPTAGS
write(2,end,len-(end-buf));
#endif
break;
}
}
}