项目实现语音转换文字的功能。
项目前后端分离,前端(移动端/Web端)按特定参数要求录音,将录音传给后端,后端将录音上传百度服务处理,对百度返回的结果进行预处理,以JSON格式返回给前端。
一级文件 | 二级文件 | 三级文件 | 四级文件 |
---|---|---|---|
baiduASR(Directory) | |||
/ | app.py | ||
/ | requirements.txt | ||
/ | apps(Python_package) | ||
/ | apps | baidu_ai((Python_package) | |
/ | apps | baidu_ai | _init_.py |
/ | apps | baidu_ai | baiduToken.py |
/ | apps | baidu_ai | keySpace.py |
/ | apps | baidu_ai | views.py |
说明:app.py为入口文件;baiduToken是写获取百度令牌的文件;keySpace是用于存放百度语音识别密钥的地方;views是视图层,用于写路由。
从app.py入口文件开始依次介绍。
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author VieneLau
@desc 服务入口文件
@date 2020/12/2
说明:
创建(增加)新应用需要在本文件中,注册新应用的蓝图
"""
from flask import Flask
from apps.baidu_ai import bp as baiduai_bp#导入各个模块应用
from flask_wtf import CSRFProtect
from flask_wtf import CSRFProtect as WTF # 利用表单类去渲染模板时需要用到
from flask_cors import *
def create_app():
app = Flask(__name__)
app.config.from_object(Config) # 从配置对象来加载配置
CORS(app, resources=r'/*') # 跨域设置
#注册蓝图
app.register_blueprint(baiduai_bp)
return app
if __name__ == '__main__':
app = create_app()
app.run(host='127.0.0.1', debug=True)
#!usr/bin/env python
# -*- coding:utf-8 -*-
from .views import bp # 引入蓝图
需要按申请的密钥修改代码API_KEY、SECRET_KEY这两个值。
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author VieneLau
@desc 百度语音识别参数
@date 2020/12/2
说明:
base_url 获取百度语音识别token地址,HOST进行地址拼接;
API_KEY、SECRET_KEY为自行申请的百度服务的密钥
"""
base_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s"
API_KEY = '申请的密钥'
SECRET_KEY = '申请的密钥'
HOST = base_url % (API_KEY, SECRET_KEY)
获取百度语音识别Token(如不想获取Token进行语音识别,可参考B版本)
# -*- coding:utf-8 -*-
"""
@author VieneLau
@desc 获取百度token并识别的具体逻辑
@date 2020/12/2
说明:
具体情况请看 【百度语音识别官方文档】
采用百度语音识别官方文档提供的方式,base64编码Json方式上传百度服务器,并进行处理,返回结果。
其中在speech2text函数中,FORMAT为音频文件的格式,
百度服务支持:pcm(不压缩)、wav(不压缩,pcm编码)、amr(压缩格式)、m4a(AAC编码);固定16k 采样率;
cuid为用户唯一标识,用来区分用户,计算UV值。建议填写能区分用户的机器 MAC 地址或 IMEI 码,长度为60字符以内。
"""
import base64
import json
import requests
def getToken(host):
res = requests.post(host)
return res.json()['access_token']
# 传入语音二进制数据,token
# dev_pid为百度语音识别提供的几种语言选择
def speech2text(speech_data, token, dev_pid):
# 音频格式要求
FORMAT = 'pcm'
RATE = '16000'
CHANNEL = 1
CUID = 'asrbaidu_test'
SPEECH = base64.b64encode(speech_data).decode('utf-8')
data = {
"format": FORMAT,
"rate": RATE,
"dev_pid": dev_pid,
"channel": CHANNEL,
"token": token,
"cuid": CUID,
"len": len(speech_data),
"speech": SPEECH,
}
url = 'https://vop.baidu.com/server_api'
headers = {
'Content-Type': 'application/json'}
res = requests.post(url, json=data, headers=headers)
Result = res.json()
# 对百度服务回传回的结果进行预处理。
# 此处未对语音识别不成功的情况特殊定义,如有需要可进行定义。
if 'result' in Result:
return Result['result'][0]
else:
return Result
B版本:
'''
将下面的代码直接替换views.py文件中的33与35行代码
(Token = apps.baidu_ai.baiduToken.getToken(HOST)
result = apps.baidu_ai.baiduToken.speech2text(file, Token, dev_pid=1537))
'''
APP_ID = '申请的'
API_KEY = '申请的'
SECRET_KEY = '申请的'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
# 音频文件的格式在下面的语句中改,eg:可把‘pcm’改为‘wav’
result = client.asr(read_file(str(file_address)), 'pcm', 16000, {
'dev_pid': 1537,
})
return result
#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author VieneLau
@desc 处理前端post音频
@date 2020/12/2
说明:
将录音转换为文字并以json格式返回给前端
"""
from flask import Blueprint, request, jsonify, json, render_template
from flask_cors import cross_origin
import apps
from apps.baidu_ai.baiduToken import speech2text
from apps.baidu_ai.keySpace import HOST
bp = Blueprint("baiduAi", __name__, url_prefix='/')
@bp.route('/baiduai', methods=['GET', 'POST'])
@cross_origin()
def baidu_ai():
if request.method == "GET":
return jsonify({
'status': 200,
'message': '这是get方法!'
})
else:
# 对应前端传的参数名——pcm_audio
file = request.files['pcm_audio'].read()
Token = apps.baidu_ai.baiduToken.getToken(HOST)
# 音频文件格式要求,具体见百度官方文档;本项目中为PCM,可在baiduToken.py中修改。
result = apps.baidu_ai.baiduToken.speech2text(file, Token, dev_pid=1537)
return jsonify({
'status': 200,
'message': result
})
1、直接选择右上角 run app.py
2、在Terminal 中输入命令【flask run】
项目一开始用Django框架写的,后面各种原因,改成Flask重写。
看网上好多解决方案都会将语音文件存在本地,再进行语音识别,我第一版的也是这样,但是就很占地很闹心,最后用【.read】解决的(具体见views.py)。
项目还有很多需要完善的地方,本文仅供参考。欢迎讨论、批评、指正。