PaddleSpeech?是基于飛槳?PaddlePaddle?的語音方向的開源模型庫,用于語音和音頻中的各種關(guān)鍵任務的開發(fā),包含大量基于深度學習前沿和有影響力的模型,一些典型的應用示例如下:語音識別、語音翻譯 (英譯中)、語音合成、標點恢復等。
我只用到了語音識別(語音轉(zhuǎn)文字)、語音合成(文字轉(zhuǎn)語音)。
安裝
我只在CentOS上用了(虛擬機CentOS Linux release 7.9.2009和云服務器CentOS Linux release 8.5.2111),因截止到寫這篇文章(2022年11月18日),官方README中說
我們強烈建議用戶在?Linux?環(huán)境下,3.7?以上版本的?python?上安裝 PaddleSpeech。
linux
- yum install gcc gcc-c++ # from https://github.com/PaddlePaddle/PaddleSpeech/blob/develop/docs/source/install_cn.md#linux
- pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple? # GPU版去官網(wǎng)看命令
- pip install pytest-runner
- pip install setuptools_scm # 安裝paddlespeech需要,否則報錯ERROR: Could not find a version that satisfies the requirement setuptools_scm (from versions: none)和ERROR: No matching distribution found for setuptools_scm,且這兩句報錯沒有高亮,而是在高亮的報錯'error: subprocess-exited-with-error'的下面。from https://github.com/PaddlePaddle/PaddleSpeech/issues/2150
- pip install paddlespeech -i https://pypi.tuna.tsinghua.edu.cn/simple
- 從安裝文檔中下載nltk_data并解壓到家目錄,文字轉(zhuǎn)語音需要它?# from https://github.com/PaddlePaddle/PaddleSpeech/issues/2456
- yum install libsndfile # 運行若報錯OSError: sndfile library not found和OSError: cannot load library 'libsndfile.so': libsndfile.so: cannot open shared object file: No such file or directory再裝。from https://github.com/PaddlePaddle/PaddleSpeech/issues/2198和https://github.com/PaddlePaddle/PaddleSpeech/issues/440,但這兩個鏈接中的命令不對
指定源是因為安裝文檔中建議的
- 提示: 我們建議在安裝?
paddlepaddle
?的時候使用百度源?https://mirror.baidu.com/pypi/simple?,而在安裝?paddlespeech
?的時候使用清華源?https://pypi.tuna.tsinghua.edu.cn/simple?。
不過README中沒說要指定源。?

顯卡驅(qū)動的安裝可以看我另一篇文章。
使用
如果你的機器CPU或內(nèi)存不夠,可能運行不起來代碼,終端中能看到進程會被自動結(jié)束掉。
測試語音轉(zhuǎn)文字時,我用手機的錄音機錄了wav音頻,用PaddleSpeech轉(zhuǎn)文字時提示
The sample rate of the input file is not 16000.The program will resample the wav file to 16000.If the result does not meet your expectations,Please input the 16k 16 bit 1 channel wav file.?
它要求音頻文件的采樣率是16000Hz,如果輸入的文件不符合要求,根據(jù)提示按y后,程序會自動將音頻文件調(diào)整成它能識別的樣子,然后給出識別結(jié)果。此時我用的官方的示例代碼,只不過音頻文件是我自己錄的。
from paddlespeech.cli.asr.infer import ASRExecutor
asr = ASRExecutor()
result = asr(audio_file="luyin.wav")
print(result)
我需要把這個功能寫成接口,接口中程序運行時,若輸入的音頻文件不符合要求,用戶是無法用鍵盤進行交互的,導致輸入的音頻無法被轉(zhuǎn)成文字。這就需要提前將音頻文件轉(zhuǎn)成16k 16 bit 1 channel wav,然后將轉(zhuǎn)換后的音頻文件傳給PaddleSpeech。我不知道源碼中有沒有提供可供調(diào)用的轉(zhuǎn)換函數(shù)(因為服務器上只有vim,找代碼看代碼不方便),我直接用ffmpeg轉(zhuǎn)換了(python執(zhí)行shell命令),ffmpeg的安裝可以參考這兩個鏈接:CentOS安裝使用ffmpeg - 開普勒醒醒吧 - 博客園 (cnblogs.com)、centos 安裝ffmpeg_qq_duhai的博客-CSDN博客。
也可以直接在這里下載靜態(tài)編譯好的,不用自己解決依賴問題。
ffmpeg -y -i input.wav -ac 1 -ar 16000 -b:a 16k output.wav # from https://blog.csdn.net/Ezerbel/article/details/124393431
這個命令輸出的文件的格式,和PaddleSpeech給的示例zh.wav的格式一樣,可以用PotPlayer查看。
接口形式的語音轉(zhuǎn)文字、文字轉(zhuǎn)語音的完整代碼
import os
import random
import time
import json
import base64
import shutil
from paddlespeech.cli.asr.infer import ASRExecutor
from paddlespeech.cli.tts.infer import TTSExecutor
from flask import Flask, request
app=Flask(__name__)
asr = ASRExecutor() # 初始化成全局變量,防止多次初始化導致顯存不夠 from https://github.com/PaddlePaddle/PaddleSpeech/issues/2881和https://github.com/PaddlePaddle/PaddleSpeech/issues/2908
tts = TTSExecutor()
# 公共函數(shù),所有接口都能用
def random_string(length=32): # 生成32位隨機字符串,為了生成隨機文件名
string='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
return ''.join(random.choice(string) for i in range(length))
# 公共函數(shù),所有接口都能用
def base64_to_audio(audio_base64, folder_name=None): # 服務器上用folder_name參數(shù),用于在audio_file_path中拼接路徑,如f'/home/www/card/{folder_name}/',不同的folder_name對應不同的識別任務(如身份證識別、營業(yè)執(zhí)照識別),本地測試不用
audio_base64 = audio_base64.split(',')[-1]
audio = base64.b64decode(audio_base64)
audio_file_name = random_string() + '_' + (str(time.time()).split('.')[0]) # 不帶擴展名,因為不知道收到的音頻文件的原始擴展名,手機錄的不一定是什么格式
audio_file_path = f'/home/python/speech/{folder_name}/' + audio_file_name
with open(audio_file_path, 'wb') as f:
f.write(audio)
return audio_file_path
# 將收到的音頻文件轉(zhuǎn)為16k 16 bit 1 channel的wav文件,16k表示16000Hz的采樣率,16bit不知道是什么
# 若給paddlespeech傳的文件不對,會提示The sample rate of the input file is not 16000.The program will resample the wav file to 16000.If the result does not meet your expectations,Please input the 16k 16 bit 1 channel wav file.所以要提前轉(zhuǎn)換。
def resample_rate(audio_path_input):
audio_path_output = audio_path_input + '_output' + '.wav' # 傳入的audio_path_input不帶擴展名,所以后面直接拼接字符串
command = f'ffmpeg -y -i {audio_path_input} -ac 1 -ar 16000 -b:a 16k {audio_path_output}' # 這個命令輸出的wav文件,格式上和PaddleSpeech在README中給的示例zh.wav(https://paddlespeech.bj.bcebos.com/PaddleAudio/zh.wav,內(nèi)容是'我認為跑步最重要的就是給我?guī)砹松眢w健康')一樣。from https://blog.csdn.net/Ezerbel/article/details/124393431
command_result = os.system(command) # from https://blog.csdn.net/liulanba/article/details/115466783
assert command_result == 0
if os.path.exists(audio_path_output):
return audio_path_output
elif not os.path.exists(audio_path_output): # ffmpeg輸出的文件不存在,可能是ffmpeg命令沒執(zhí)行完,等1秒(因在虛擬機測試轉(zhuǎn)一個8.46M的MP3需0.48秒),1秒后若還沒有輸出文件,說明報錯了
time.sleep(1)
if os.path.exists(audio_path_output):
return audio_path_output
else:
return None
# 語音轉(zhuǎn)文字
# 只接受POST方法訪問
@app.route("/speechtotext",methods=["POST"])
def speech_to_text():
audio_file_base64 = request.get_json().get('audio_file_base64') # 要轉(zhuǎn)為文字的語音文件的base64編碼,開頭含不含'data:audio/wav;base64,'都行
audio_file_path = base64_to_audio(audio_file_base64, folder_name='speech_to_text/audio_file') # 存放收到的原始音頻文件
audio_path_output = resample_rate(audio_path_input=audio_file_path)
if audio_path_output:
# asr = ASRExecutor()
result = asr(audio_file=audio_path_output) # 會在當前代碼所在文件夾中產(chǎn)生exp/log文件夾,里面是paddlespeech的日志文件,每一次調(diào)用都會生成一個日志文件。記錄這點時的版本號是paddlepaddle==2.3.2,paddlespeech==1.2.0。 from https://github.com/PaddlePaddle/PaddleSpeech/issues/1211
os.remove(audio_file_path) # 識別成功時刪除收到的原始音頻文件和轉(zhuǎn)換后的音頻文件
os.remove(audio_path_output)
# try:
# shutil.rmtree('') # 刪除文件夾,若文件夾不存在會報錯。若需刪除日志文件夾,用這個。from https://blog.csdn.net/a1579990149wqh/article/details/124953746
# except Exception as e:
# pass
return json.dumps({'code':200, 'msg':'識別成功', 'data':result}, ensure_ascii=False)
else:
return json.dumps({'code':400, 'msg':'識別失敗'}, ensure_ascii=False)
# 文字轉(zhuǎn)語音
# 只接受POST方法訪問
@app.route("/texttospeech",methods=["POST"])
def text_to_speech():
text_str = request.get_json().get('text') # 要轉(zhuǎn)為語音的文字
# tts = TTSExecutor()
audio_file_name = random_string() + '_' + (str(time.time()).split('.')[0]) + '.wav'
audio_file_path = '/home/python/speech/text_to_speech/audio_file' + audio_file_name
tts(text=text_str, output=audio_file_path) # 輸出24k采樣率wav格式音頻。同speech_to_text()中一樣,會在當前代碼所在文件夾中產(chǎn)生exp/log文件夾,里面是paddlespeech的日志文件,每一次調(diào)用都會生成一個日志文件。
if os.path.exists(audio_file_path):
with open(audio_file_path, 'rb') as f:
base64_str = base64.b64encode(f.read()).decode('utf-8') # 開頭不含'data:audio/wav;base64,'
os.remove(audio_file_path) # 識別成功時刪除轉(zhuǎn)換后的音頻文件
# try:
# shutil.rmtree('') # 刪除文件夾,若文件夾不存在會報錯。若需刪除日志文件夾,用這個。from https://blog.csdn.net/a1579990149wqh/article/details/124953746
# except Exception as e:
# pass
return json.dumps({'code':200, 'msg':'識別成功', 'data':base64_str}, ensure_ascii=False)
elif not os.path.exists(audio_file_path):
return json.dumps({'code':400, 'msg':'識別失敗'}, ensure_ascii=False)
if __name__=='__main__':
app.run(host='127.0.0.1', port=9723)
最后
如果你想調(diào)整語速,可以看請問自己 finetune 的 tts 模型能夠改變語速嗎? · Issue #2383 · PaddlePaddle/PaddleSpeech · GitHub
如果你用的是GPU版,查看是否調(diào)用了GPU,請問語音合成可以使用GPU進行推理嗎,如果可以應該怎么操作呢? · Issue #2467 · PaddlePaddle/PaddleSpeech · GitHub,也可以用nvidia-smi命令查看GPU占用情況
如果在使用過程中遇到顯存未釋放,導致顯存不夠,可以看音頻轉(zhuǎn)文字過程中顯存不斷增加,最終 out of memory · Issue #2881 · PaddlePaddle/PaddleSpeech · GitHub文章來源:http://www.zghlxwxcb.cn/news/detail-779211.html
?[TTS]使用gpu合成后顯存未釋放 · Issue #2908 · PaddlePaddle/PaddleSpeech · GitHub文章來源地址http://www.zghlxwxcb.cn/news/detail-779211.html
到了這里,關(guān)于百度飛槳PaddleSpeech的簡單使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!