人工智能語音識別系統開發

 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目錄,配置我們的環境變量

配置後,在終端測試效果:

使用

技術文檔SDK鏈接

我們用命令行對這個 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   # 英文
View Code

 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,否則會出現緩存現象,得不到我們的效果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章