1.初始教程
1.登錄百度雲管理中心,點擊管理控制檯
2.進入後,下拉在已開通服務中選擇百度語音
3.點擊創建應用,得到以下應用
4.這裏也可以查看它的相關技術文檔
2.文字合成語音
1.安裝使用Python SDK,終端下:
pip install baidu-aip
使用
from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID = '11793737' API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH' SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR' client = AipSpeech(APP_ID,API_KEY,SECRET_KEY) result = client.synthesis("第一次把下列文字轉成MP3語音","zh",1,{ "spd":4, "vol":7, "pit":8, "per":4 }) if not isinstance(result,dict): # 創建一個auido.mp3文件 with open("auido.mp3","wb") as f: f.write(result) print(result) # 打印bytes字節
此時文件中會多出一個mp3結尾的文件,我們把改文字已經轉換成語音寫入在了該文件中
3.語音轉義成文字
參考技術文檔說明,這裏支持的語音格式文件有:pcm(不壓縮)、wav(不壓縮,pcm編碼)、amr(壓縮格式)
我們需要藉助第三方工具ffmpeg把任意格式的語音轉移成pcm格式
3.1 ffmpeg說明:
FFmpeg 是一個自由軟件,可以運行音頻和視頻多種格式的錄影、轉換、流功能包含了libavcodec——這是一個用於多個項目中音頻和視頻的解碼器庫,
以及libavformat——一個音頻與視頻格式轉換庫。說簡單點,這個工具可以將wav wma mp3 等音頻文件轉換爲 pcm 無壓縮音頻文件
下載鏈接:猛戳此處
或者此處鏈接:鏈接: https://pan.baidu.com/s/1-TEQZP9QbJSlGSYedyAUFw 密碼: 2z8l
下載後解壓縮(我把它放在了D盤下),注意可執行的exe文件是在文件的bin目錄,配置我們的環境變量
配置後,在終端測試效果:
使用
我們用命令行對這個 auido.mp3 進行pcm格式的轉換然後得到 audio.pcm
命令是 : ffmpeg -y -i audio.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 audio.pcm
from aip import AipSpeech import os """ 你的 APPID AK SK """ APP_ID = '11793737' API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH' SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR' client = AipSpeech(APP_ID,API_KEY,SECRET_KEY) # 讀取文件 filePath = "auido.mp3" def get_file_content(filePath): # 用於將任何形式的語音文件格式轉化成pcm格式,這裏使用的是py3.6的模板語法,其他版本可以使用字符串的格式化語法 os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm") with open(f"{filePath}.pcm",'rb') as fp: return fp.read() # 識別本地文件 liu = get_file_content(filePath) res = client.asr(liu,'pcm',16000,{ 'dev_pid':1536 }) print(res) # 查看格式 # {'corpus_no': '6599876657908188502', 'err_msg': 'success.', 'err_no': 0, # 'result': ['第一次把下列文字轉MP3語音'], 'sn': '465883505901536653530'} if res.get("result"): print(res.get('result')[0]) else: print(res)
# 注意這裏轉化後文件中會搓出一個auido.mp3.pcm格式的文件
相關參數說明:
asr函數需要四個參數 第一個參數: speech 音頻文件流 建立包含語音內容的Buffer對象, 語音文件的格式,pcm 或者 wav 或者 amr 第二個參數: format 文件的格式,包括pcm(不壓縮)、wav、am 第三個參數: rate 音頻文件採樣率 如果使用剛剛的FFmpeg的命令轉換的,你的pcm文件就是16000 第四個參數: dev_pid 音頻文件語言id 默認1537(普通話 輸入法模型) 1636 # 普通話,支持簡單英文識別 1737 # 英文
4.輸入語音實現自動交互
這裏需要我們的圖靈機器人技術,創建一個機器人
對我們的機器人進行相關設置
4.1 api接口使用
api接口文檔說明地址:猛戳此處
接口地址:http://openapi.tuling123.com/openapi/api/v2
請求方式:只有兩種,HTTP POST
測試:
import requests import json apiKey = "d76b3e9669404fe7b5a1949466fd6376" userId = "taylor" # 機器人名稱 data = { # 請求的類型 0 文本 1 圖片 2 音頻 "reqType": 0, "perception": { "inputText": { "text": "你是誰" } }, "userInfo": { "apiKey": apiKey, "userId": userId } } tuling_url = "http://openapi.tuling123.com/openapi/api/v2" res = requests.post(tuling_url,json=data) # 請求url # 將返回信息解碼 res_dic = json.loads(res.content.decode("utf-8")) # type:dict # 得到返回信息中的文本信息 res_type = res_dic.get("results")[0].get("values").get("text") print(res_type)
效果:
現在有文本信息了,我們可以調用上面的文本信息轉換成語音,讓它實現語音播放
third.py
import os from aip import AipSpeech from aip import AipNlp """ 你的 APPID AK SK """ APP_ID = '11793737' API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH' SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR' client = AipSpeech(APP_ID,API_KEY,SECRET_KEY) # 用於將任何形式的語音文件格式轉化成pcm格式 # 這裏使用的是py3.6的模板語法,其他語言可以使用字符串的格式化語法 def get_file_content(filePath): os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm") with open(f"{filePath}.pcm",'rb') as fp: return fp.read() def text2audio(text): result = client.synthesis(text, 'zh', 1, { "spd": 4, 'vol': 7, "pit": 8, "per": 4 }) if not isinstance(result, dict): # 創建一個auido.mp3文件 with open('auido.mp3', 'wb') as f: f.write(result)
return get_file_content('auido.mp3')
test.py
import requests import json import third apiKey = "d76b3e9669404fe7b5a1949466fd6376" userId = "taylor" # 機器人名稱 data = { # 請求的類型 0 文本 1 圖片 2 音頻 "reqType": 0, "perception": { "inputText": { "text": "你是誰" } }, "userInfo": { "apiKey": apiKey, "userId": userId } } tuling_url = "http://openapi.tuling123.com/openapi/api/v2" res = requests.post(tuling_url,json=data) # 請求url # 將返回信息解碼 res_dic = json.loads(res.content.decode("utf-8")) # type:dict # 得到返回信息中的文本信息 res_type = res_dic.get("results")[0].get("values").get("text") # 調用text2audio函數 third.text2audio(res_type)
執行後,此時文件中會多出一個auido.mp3和一個auido.mp3.pcm文件,文件內容就是機器人對我們的文本回復的內容
5.web錄音實現互動問答
5.1 websocket監聽
ai.py
from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket app = Flask(__name__,template_folder="../templates") @app.route("/index") def index(): # 獲取請求的WebSocket對象 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket print(user_socket) # <geventwebsocket.websocket.WebSocket object at 0x000002718C07F798> print(request.remote_addr) # 遠程ip地址127.0.0.1 while True: # 接收消息 msg = user_socket.receive() print(msg) @app.route("/") def home(): return render_template("index.html") if __name__ == "__main__": http_serv = WSGIServer(("0.0.0.0",9520),app,handler_class=WebSocketHandler) http_serv.serve_forever()
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> <script type="application/javascript"> //創建 WebSocket 對象 var ws = new WebSocket("ws://127.0.0.1:9520/index"); </script> </html>
這裏我們啓動我們的程序,在瀏覽器輸入http://127.0.0.1:9520/,此時在pycharm上就會傳回我們的websocket對象以及遠程IP地址
我們利用websocket已經實現了前端與後端的交互嗎,現在我們需要通過websocket把我們網頁上錄的語音換到後端去
5.2 recorder.js錄音插件
recorder.js是HTML5錄音插件,它可以實現在線錄音。
部分瀏覽器還存在兼容性(如ie,Safari)
Chrome47以上以及QQ瀏覽器需要HTTPS支持
github下載地址爲:https://github.com/mattdiamond/Recorderjs
html5 Audio常用屬性和函數事件參考鏈接:https://blog.csdn.net/bright2017/article/details/80041448
項目構架
./
├── ai.py
├── static
│ └── recorder.js
└── templates
└── index.html
在index.html中導入我們的recorder.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#audio是HTML5的標籤,autoplay表示自動播放,controls表示展示組件#} <audio src="" autoplay controls id="player"></audio> <br> <button onclick="start_reco()">開始廢話</button> <br> <button onclick="stop_reco()">發送語音</button> </body> <script src="/static/recorder.js"></script> <script type="application/javascript"> // 創建WebSocket對象 var ws = new WebSocket("ws://127.0.0.1:5300/index"); var reco = null; //錄音對象 // 創建AudioContext對象 // AudioContext() 構造方法創建了一個新的 AudioContext 對象 它代表了一個由音頻模塊鏈接而成的音頻處理圖, 每一個模塊由 AudioNode 表示 var audio_context = new AudioContext(); //要獲取音頻和視頻,需要用到getUserMedia。桌面平臺支持的瀏覽器包括Chrome, Firefox, Opera和Edge。 // 這裏的|| 表示或者的關係,也就是能支持的瀏覽器 navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); // 拿到媒體對象,允許音頻對象 navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err) }); //創建媒體流容器 function create_stream(user_media) { //AudioContext接口的createMediaStreamSource()方法用於創建一個新的MediaStreamAudioSourceNode 對象, // 需要傳入一個媒體流對象(MediaStream對象)(可以從 navigator.getUserMedia 獲得MediaStream對象實例), // 然後來自MediaStream的音頻就可以被播放和操作。 // MediaStreamAudioSourceNode 接口代表一個音頻接口,是WebRTC MediaStream (比如一個攝像頭或者麥克風)的一部分。 // 是個表現爲音頻源的AudioNode。 var stream_input = audio_context.createMediaStreamSource(user_media); // 給Recoder 創建一個空間,麥克風說的話,都可以錄入。是一個流 reco = new Recorder(stream_input); } function start_reco() { //開始錄音 reco.record(); //往裏面寫流 } function stop_reco() { //停止錄音 reco.stop(); //停止寫入流 get_audio(); //調用自定義方法 reco.clear(); //清空容器 } // 獲取音頻 function get_audio() { reco.exportWAV(function (wav_file) { // 發送數據給後端 ws.send(wav_file); }) } </script> </html>
啓動程序後,點擊開始按鈕,後臺會接收到一個bytearray類型的字符,這就是我們的聲音字節,現在需要我們把它寫入文件
修改我們的後臺程序
from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket app = Flask(__name__,template_folder="../templates") @app.route("/index") def index(): # 獲取請求的WebSocket對象 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket print(user_socket) # <geventwebsocket.websocket.WebSocket object at 0x000002718C07F798> print(request.remote_addr) # 遠程ip地址127.0.0.1 while True: # 接收消息 msg = user_socket.receive() if type(msg) == bytearray: # 寫入文件123.wav with open("123.wav", "wb") as f: f.write(msg) @app.route("/") def home(): return render_template("index.html") if __name__ == "__main__": http_serv = WSGIServer(("0.0.0.0",5300),app,handler_class=WebSocketHandler) http_serv.serve_forever()
此時重啓文件,我們就能把我們的聲音錄製成一個123.wav格式的文件,這個就是我們錄製的聲音
5.3 整合以上內容
現在我們需要完成在瀏覽器輸入語音,在線實時和圖靈機器人交互的效果,我們把以上代碼進行整合
流程:通過瀏覽器發送語音給後端-->後端將音頻文件轉成文字發個圖靈機器人-->後端再講圖靈回執的文字轉成音頻文件-->回執的音頻文件發送給前端
test.py
import requests import json import third apiKey = "d76b3e9669404fe7b5a1949466fd6376" userId = "taylor" # 機器人名稱 data = { # 請求的類型 0 文本 1 圖片 2 音頻 "reqType": 0, "perception": { "inputText": { "text": "你是誰" } }, "userInfo": { "apiKey": apiKey, "userId": userId } } tuling_url = "http://openapi.tuling123.com/openapi/api/v2" def to_tuling(question,user_id): # 修改請求參數中的inputText,也就是問題 data["perception"]["inputText"]["text"] = question # # 修改userInfo data["userInfo"]["userId"] = user_id res = requests.post(tuling_url,json=data) # 請求url # 將返回信息解碼 res_dic = json.loads(res.content.decode("utf-8")) # type:dict # 得到返回信息中的文本信息 result = res_dic.get("results")[0].get("values").get("text") # print(res_type) return result
third.py
import os from aip import AipSpeech from aip import AipNlp import test """ 你的 APPID AK SK """ APP_ID = '11793737' API_KEY = 'Mx8wLzbFk2VNVcjybf8lDzFH' SECRET_KEY = 'DEc7I5q18z7aazW22LKDgwGocZ8h9VdR' client = AipSpeech(APP_ID,API_KEY,SECRET_KEY) nlp_client = AipNlp(APP_ID, API_KEY, SECRET_KEY) # 用於將任何形式的語音文件格式轉化成pcm格式 # 這裏使用的是py3.6的模板語法,其他語言可以使用字符串的格式化語法 def get_file_content(filePath): os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm") with open(f"{filePath}.pcm",'rb') as fp: return fp.read() def text2audio(text): result = client.synthesis(text, 'zh', 1, { "spd": 4, 'vol': 7, "pit": 8, "per": 4 }) if not isinstance(result, dict): # 創建一個auido.mp3文件 with open('audio.mp3', 'wb') as f: f.write(result) return 'audio.mp3' # 識別本地文件,轉義成文本信息 def audio2text(file_path): a = client.asr(get_file_content(file_path), 'pcm', 16000, { 'dev_pid': 1536, }) if a.get("result") : return a.get("result")[0] def my_nlp(q,uid): a = test.to_tuling(q,uid) return a
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#audio是HTML5的標籤,autoplay表示自動播放,controls表示展示組件#} <audio src="" autoplay controls id="player"></audio> <br> <button onclick="start_reco()">開始廢話</button> <br> <button onclick="stop_reco()">發送語音</button> </body> <script src="/static/recorder.js"></script> <script type="application/javascript"> // 創建WebSocket對象,index後面的是userid,是圖靈機器人需要的 var ws = new WebSocket("ws://127.0.0.1:5300/index/taylor"); var reco = null; //錄音對象 // 創建AudioContext對象 // AudioContext() 構造方法創建了一個新的 AudioContext 對象 它代表了一個由音頻模塊鏈接而成的音頻處理圖, 每一個模塊由 AudioNode 表示 var audio_context = new AudioContext(); //要獲取音頻和視頻,需要用到getUserMedia。桌面平臺支持的瀏覽器包括Chrome, Firefox, Opera和Edge。 // 這裏的|| 表示或者的關係,也就是能支持的瀏覽器 navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); // 拿到媒體對象,允許音頻對象 navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err) }); //創建媒體流容器 function create_stream(user_media) { //AudioContext接口的createMediaStreamSource()方法用於創建一個新的MediaStreamAudioSourceNode 對象, // 需要傳入一個媒體流對象(MediaStream對象)(可以從 navigator.getUserMedia 獲得MediaStream對象實例), // 然後來自MediaStream的音頻就可以被播放和操作。 // MediaStreamAudioSourceNode 接口代表一個音頻接口,是WebRTC MediaStream (比如一個攝像頭或者麥克風)的一部分。 // 是個表現爲音頻源的AudioNode。 var stream_input = audio_context.createMediaStreamSource(user_media); // 給Recoder 創建一個空間,麥克風說的話,都可以錄入。是一個流 reco = new Recorder(stream_input); } function start_reco() { //開始錄音 reco.record(); //往裏面寫流 } function stop_reco() { //停止錄音 reco.stop(); //停止寫入流 get_audio(); //調用自定義方法 reco.clear(); //清空容器 } // 獲取音頻 function get_audio() { reco.exportWAV(function (wav_file) { // 發送數據給後端 ws.send(wav_file); }) } // 接收到服務端數據時觸發 ws.onmessage = function (data) { console.log(data.data); //打印文件名 } </script> </html>
ai.py -->執行文件
from flask import Flask,request,render_template,send_file from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket import third app = Flask(__name__,template_folder="../templates",static_folder="../static") @app.route("/index/<uid>") def index(uid): # 接收uid # 獲取請求的WebSocket對象 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket print(user_socket) # print(request.remote_addr) # 遠程ip地址 while True: # 接收消息 msg = user_socket.receive() if type(msg) == bytearray: # 寫入文件123.wav with open("123.wav", "wb") as f: f.write(msg) # 將音頻文件轉換爲文字 res_q = third.audio2text("123.wav") # 調用my_nlp函數,內部調用圖靈機器人 res_a = third.my_nlp(res_q,uid) # 將文字轉換爲音頻文件 file_name = third.text2audio(res_a) # 發送文件名給前端 user_socket.send(file_name) @app.route("/") def home_page(): return render_template("index.html") @app.route("/get_file/<file_name>") # 獲取音頻文件 def get_file(file_name): # 此方法用於前端調取後端的音頻文件,用於自動播放 return send_file(file_name) if __name__ == "__main__": http_serv = WSGIServer(("0.0.0.0",5300),app,handler_class=WebSocketHandler) http_serv.serve_forever()
相關說明:這裏瀏覽器很關鍵,很容易失敗,多試幾個瀏覽器,我調試的是谷歌瀏覽器,需要我們把油猴插件關掉,還需要把靜態文件路徑加上
執行完後,頁面打印臺會輸出一個audio.mp3文件
5.4 實現自動播放
實現頁面自動播放生成的audio.mp3文件
index.html -->直接替換上面html的即可
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#audio是HTML5的標籤,autoplay表示自動播放,controls表示展示組件#} <audio src="" autoplay controls id="player"></audio> <br> <button onclick="start_reco()">開始廢話</button> <br> <button onclick="stop_reco()">發送語音</button> </body> <script src="/static/recorder.js"></script> <script type="application/javascript"> // 訪問後端的get_file,得到一個文件名 var get_file = "http://127.0.0.1:5300/get_file/"; // 創建WebSocket對象,index後面的是userid,是圖靈機器人需要的 var ws = new WebSocket("ws://127.0.0.1:5300/index/taylor"); var reco = null; //錄音對象 // 創建AudioContext對象 // AudioContext() 構造方法創建了一個新的 AudioContext 對象 它代表了一個由音頻模塊鏈接而成的音頻處理圖, 每一個模塊由 AudioNode 表示 var audio_context = new AudioContext(); //要獲取音頻和視頻,需要用到getUserMedia。桌面平臺支持的瀏覽器包括Chrome, Firefox, Opera和Edge。 // 這裏的|| 表示或者的關係,也就是能支持的瀏覽器 navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); // 拿到媒體對象,允許音頻對象 navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err) }); //創建媒體流容器 function create_stream(user_media) { //AudioContext接口的createMediaStreamSource()方法用於創建一個新的MediaStreamAudioSourceNode 對象, // 需要傳入一個媒體流對象(MediaStream對象)(可以從 navigator.getUserMedia 獲得MediaStream對象實例), // 然後來自MediaStream的音頻就可以被播放和操作。 // MediaStreamAudioSourceNode 接口代表一個音頻接口,是WebRTC MediaStream (比如一個攝像頭或者麥克風)的一部分。 // 是個表現爲音頻源的AudioNode。 var stream_input = audio_context.createMediaStreamSource(user_media); // 給Recoder 創建一個空間,麥克風說的話,都可以錄入。是一個流 reco = new Recorder(stream_input); } function start_reco() { //開始錄音 reco.record(); //往裏面寫流 } function stop_reco() { //停止錄音 reco.stop(); //停止寫入流 get_audio(); //調用自定義方法 reco.clear(); //清空容器 } // 獲取音頻 function get_audio() { reco.exportWAV(function (wav_file) { // 發送數據給後端 ws.send(wav_file); }) } // 接收到服務端數據時觸發 ws.onmessage = function (data) { // console.log(data.data); console.log(get_file + data.data); //打印文件名 // 修改id爲player的src屬性, document.getElementById("player").src = get_file + data.data; } </script> </html>
ok,下來就可以聽到聲音了
# 補充說明:這裏生成的文件名我們給寫死了,最好生成動態文件名,可以引入uuid,否則會出現緩存現象,得不到我們的效果