音頻識別可以識別出一段未知的音頻屬於哪個音樂的,從第幾秒開始。目前音頻識別主要使用音頻指紋技術,音頻指紋技術通過特定的算法將一段音頻中獨一無二的數字特徵以標識符的形式提取出來,用於識別海量的聲音樣本或跟蹤定位樣本在數據庫中的位置。其中dejavu是一個非常好的音頻指紋的開源項目:
項目地址:https://github.com/worldveil/dejavu
dejavu將音頻通過FFT(快速傅里葉變換)轉換到頻域,然後獲取信號在頻域的峯值,將這些峯值通過哈希函數生成指紋。由於需要識別的音頻通常都只是一首歌的部分片段,所以這個生成指紋的過程會將一首歌一小段一小段的加窗進行。具體原理可以參考:
算法原理:https://willdrevo.com/fingerprinting-and-audio-recognition-with-python/
下面以一個demo介紹dejavu的使用:
1、dejavu是基於python2的,這點需要注意;
2、克隆代碼,並根據requirements.txt的內容安裝對應的庫,同時,操作系統需要安裝VCForPython27.msi(根據對應的版本下載);
3、dejavu的數據庫目前只支撐mysql數據庫,所以需要安裝mysql,並且在dejavu.cnf.SAMPLE配置文件中配置mysql連接參數(博主使用的是mysql5.7)。
4、測試demo代碼
# -*- coding: UTF-8 -*-
import warnings
import json
from dejavu import Dejavu
from dejavu.recognize import FileRecognizer, MicrophoneRecognizer
class Index:
def __init__(self):
warnings.filterwarnings("ignore")
with open("dejavu.cnf.SAMPLE") as f:
config = json.load(f)
self.djv = Dejavu(config)
#保存指紋到數據庫
def sava_fingerprint(self):
self.djv.fingerprint_directory("mp3", [".mp3"])
#識別音樂
def dis_fingerprint(self):
song = self.djv.recognize(FileRecognizer, "mp3test/testm1.mp3")
print "result: %s\n" % song
if __name__ == "__main__":
ind = Index()
ind.dis_fingerprint()
首先在構造函數中,讀取配置文件,通過配置初始化Dejavu對象。fingerprint_directory函數對音頻文件進行指紋提取,並將提取的指紋存儲進數據庫,函數第一個參數是文件位置,第二個參數是需要提取的音頻文件格式。recognize函數進行音頻的識別,第二個參數是需要識別的音頻文件,識別結果如下:
result: {'song_id': 2, 'song_name': 'test2', 'file_sha1': 'A19AC6B8BA1DC564C6C079B714861D68A505E010', 'confidence': 2097, 'offset_seconds': 100.12444, 'match_time': 4.577000141143799, 'offset': 2156}
song_id是數據庫中歌曲的id,song_name是歌曲的名稱,offset_seconds是被識別音頻位於歌曲的第幾秒。
音頻指紋技術比較消耗存儲和性能,一首幾M的歌曲,數據庫中生成的指紋可以達到20萬條。所以在實際應用的過程中,需要就指紋的檢索進行優化,數據庫也應該基於大數據庫架構。