下载数据集,解压完成后可以看到这几个文件:WAV – 音频文件夹,README.txt – 数据集版权介绍文件,SPKINFO.txt – 每个音频的录音设备,性别,年龄,区域,录音频道的介绍文件,UTTRANSINFO.txt – 音频的文本内容,包含普通话和上海话。这里我们主要用到的是音频文本内容普通话部分。这里将 UTTRANSINFO.txt 文件转成了 CSV 的形式,有利于我们后续数据处理。
def loadDataSet(test_dir):f = open(test_dir,'r',encoding='utf-8')fname ='ts.csv'with open(fname,'w') as fine:for line in f.readlines():line1 =line.split()PROMPT=line1[3]linew = PROMPT+"n"fine.write(linew)
2. 音频检索
音频搜索项目中,首先,将音频文件用 Panns-Inference 模型转成特征向量存储到 Milvus 2.0,并返回对应的 ID;接着,在 MySQL 数据库中存储 ID 、音频文件的路径,以及文本内容对应关系;随后,在 Milvus 2.0 中检索得出与其相似的音频文件,并返回最相似的前 N 个结果;最后,根据返回的 ID 结果,在数据库中搜索到对应的音频文件和文本内容。
使用 Milvus 2.0 最新音频检索项目,只需要修改少量代码,就可以对上海话音频进行检索,返回上海话的音频和音频内容。
下面是音频检索项目中需要修改的代码,在 load.py 中读取 CSV 的数据
def do_load(table_name, audio_dir,text_dir, model, milvus_client, mysql_cli):if not table_name:table_name = DEFAULT_TABLEvectors, names = extract_features(audio_dir, model)ids = milvus_client.insert(table_name, vectors)loadDataSet(text_dir)data = pd.read_csv("ts.csv")text = data['PROMPT'].tolist()milvus_client.create_index(table_name)mysql_cli.create_mysql_table(table_name)mysql_cli.load_data_to_mysql(table_name, format_data(ids, names,text))return len(ids)
在 search.py 中需要修改以下的代码部分:
def do_search(host,table_name, audio_path, model, milvus_client, mysql_cli):try:if not table_name:table_name = DEFAULT_TABLEfeat = get_audio_embedding(audio_path)vectors = milvus_client.search_vectors(table_name, [feat], TOP_K)vids = [str(x.id) for x in vectors[0]]paths,text = mysql_cli.search_by_milvus_ids(vids, table_name)distances = [x.distance for x in vectors[0]]for i in range(len(paths)):tmp = "http://" + str(host) + "/data?audio_path=" + str(paths[i])paths[i] = tmpreturn vids, paths, distances,textexcept Exception as e:LOGGER.error(" Error with search : {}".format(e))sys.exit(1)
在 mysql_helpers.py 文件中修改以下代码:
def create_mysql_table(self, table_name):sql = "create table if not exists " + table_name + "(milvus_id TEXT, audio_path TEXT,text TEXT) ENGINE=InnoDB DEFAULT CHARSET=utf8;"try:self.cursor.execute(sql)LOGGER.debug("MYSQL create table: {} with sql: {}".format(table_name, sql))except Exception as e:LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))sys.exit(1)def load_data_to_mysql(self, table_name, data):sql = "insert into " + table_name + " (milvus_id,audio_path,text) values (%s,%s,%s);"try:self.cursor.executemany(sql, data)self.conn.commit()LOGGER.debug("MYSQL loads data to table: {} successfully".format(table_name))except Exception as e:LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))sys.exit(1)def search_by_milvus_ids(self, ids, table_name):str_ids = str(ids).replace('[', '').replace(']', '')sql = "select * from " + table_name + " where milvus_id in (" + str_ids + ") order by field (milvus_id," + str_ids + ");"try:self.cursor.execute(sql)results = self.cursor.fetchall()results_path=[res[1] for res in results]results_text=[res[2] for res in results]LOGGER.debug("MYSQL search by milvus id.")return results_path,results_textexcept Exception as e:LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))sys.exit(1)
以及修改相关的接口,在 main.py 中修改以下代码:
class Item(BaseModel):Table: Optional[str] = NoneFile:strText:str@app.post('/audio/load')async def load_audios(item: Item):# Insert all the audio files under the file path to Milvus/MySQLtry:total_num = do_load(item.Table, item.File,item.Text,MODEL, MILVUS_CLI, MYSQL_CLI)LOGGER.info("Successfully loaded data, total count: {}".format(total_num))return {'status': True, 'msg': "Successfully loaded data!"}except Exception as e:LOGGER.error(e)return {'status': False, 'msg': e}, 400@app.post('/audio/search')async def search_audio(request: Request,Table: str = None, audio: UploadFile = File(...)):# Search the uploaded audio in Milvus/MySQLtry:# Save the upload data to server.content = await audio.read()audio_path = os.path.join(UPLOAD_PATH, audio.filename)with open(audio_path, "wb+") as f:f.write(content)host = request.headers['host']ids, paths,text, distances= do_search(host,Table, audio_path, MODEL, MILVUS_CLI, MYSQL_CLI)names=[]names = textres = dict(zip(paths, zip(names, distances)))#res = sorted(res.items(), key=lambda item: item[1][1])LOGGER.info("Successfully searched similar audio!")return resexcept Exception as e:LOGGER.error(e)return {'status': False, 'msg': e}, 400
3. 测试运行
现在上海话语音翻译器,修改完上述代码以后,参考 Github 中 Audio_similar_search 的 Readme 文档(来源详见文末链接[2])启动 FastAPI ,从 FastAPI 中验证代码是否成功运行,在浏览器中输入 localhost:8002/docs 可以看到如图所示 FastAPI 的页面, 在 Load API 中分别输入 Table 的名称,音频文件的路径,音频对应的文本的路径,然后点击 Excute 的按钮,图中显示数据插入成功。
然后,在 Search API 中输入对应的 Table 名称和需要检索的音频路径,点击 Excute 按钮进行检索。如下图所示,就可以看到相应的音频和其对应的文本内容了。
最后,感谢爱数智慧 MagicHub 提供的开源数据集,让我们更好地结合模型与 Milvus 进行多个领域的向量检索。
在这个音频检索项目中,我们也可以使用其他的方言数据集上海话语音翻译器项目加盟,将数据集经过 AI 模型转成特征向量,结合 Milvus 进行相似检索,就可以把任何你听不懂的方言翻译成普通话啦!
●●●
动手玩一把?
源码链接就在下方!
●●●
[1] 爱数智慧 MagicHub 开源社区:
[2] 音频检索:
作者 |贾晶晶
Zilliz 数据工程师,毕业于西安交通大学计算机系。加入Zilliz后,主要工作内容为数据预处理、AI模型部署、Milvus 相关技术研究,以及帮助社区用户实现应用场景落地。资深动漫粉,对社区沟通超级有耐心,平时比较关注自然语言处理领域的研究。
Github@Milvus-io|CSDN@Zilliz Planet|Bilibili@Zilliz-Planet
Zilliz 以重新定义数据科学为愿景,致力于打造一家全球领先的开源技术创新公司,并通过开源和云原生解决方案为企业解锁非结构化数据的隐藏价值。
Zilliz 构建了 Milvus 向量数据库,以加快下一代数据平台的发展。Milvus 目前是 LF AI & Data 基金会的毕业项目,能够管理大量非结构化数据集。我们的技术在新药发现、计算机视觉、推荐引擎、聊天机器人等方面具有广泛的应用。