人工智能语音识别系统开发

时间:2024-03-02 17:02:59

 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,否则会出现缓存现象,得不到我们的效果