语音识别就是将语音转换为文字的过程。鉴于所识别的语言种类不同,其具体处理过程也有所差异。但是语言识别的大致过程都一样,包括将帧识别为状态、将状态组合成音素以及将音素组合成单词几个过程。
在语言识别过程中,首先需要对音频文件进行切割掉首位部分的静音部分。这个静音切除的操作一般称为VAD,需要用到信号处理的一些技术。
其次,使用移动窗口进行分帧。
分帧后,语音就变成了很多小段。但波形在时域上几乎没有描述能力,因此必须将波形作变换。常见的一种变换方法是提取MFCC特征(根据人耳的生理特性,把每一帧波形变成一个多维向量,可以简单地理解为这个向量包含了这帧语音的内容信息)。
然后就需要使用一个声学模型来分析每个状特征所对应的可能发音。
最后就会将发音放入语音模型进行概率计算,得到这段发音所对应的最可能的一段文字路径(如是:ni hao所对应的是你好还是李好或者是倪浩)。
"""
实时流式识别
需要安装websocket-client库
使用方式 python realtime_asr.py 16k-0.pcm
"""
import websocket
import threading
import time
import uuid
import json
import logging
import sys
import pyaudio
import wave
import win32com.client
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
import re
import sys
import urllib.parse, urllib.request
import hashlib
import urllib
import random
import json
import time
from sklearn import preprocessing
from translate import Translator
# 下面2个是鉴权信息
APPID = xxxxx
APPKEY = "xxxxxxxxxxxx"
# 语言模型 , 可以修改为其它语言模型测试,如远场普通话19362
DEV_PID = 15372
# 可以改为wss://
URI = "ws://vop.baidu.com/realtime_asr"
url_google = 'http://translate.google.cn'
reg_text = re.compile(r'(?<=TRANSLATED_TEXT=).*?;')
user_agent = r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' \
r'Chrome/44.0.2403.157 Safari/537.36'
if len(sys.argv) < 2:
path=r'D:\myvoice.wav'
pcm_file = path
else:
pcm_file = sys.argv[1]
logger = logging.getLogger()
"""
1. 连接 ws_app.run_forever()
2. 连接成功后发送数据 on_open()
2.1 发送开始参数帧 send_start_params()
2.2 发送音频数据帧 send_audio()
2.3 库接收识别结果 on_message()
2.4 发送结束帧 send_finish()
3. 关闭连接 on_close()
库的报错 on_error()
"""
def send_start_params(ws):
"""
开始参数帧
:param websocket.WebSocket ws:
:return:
"""
req = {
"type": "START",
"data": {
"appid":APPID, # 网页上的appid
"appkey": APPKEY, # 网页上的appid对应的appkey
"dev_pid": DEV_PID, # 识别模型
"cuid": "yourself_defined_user_id", # 随便填不影响使用。机器的mac或者其它唯一id,百度计算UV用。
"sample": 16000, # 固定参数
"format": "pcm" # 固定参数
}
}
body = json.dumps(req)
ws.send(body, websocket.ABNF.OPCODE_TEXT)
logger.info("send START frame with params:" + body)
def send_audio(ws):
"""
发送二进制音频数据,注意每个帧之间需要有间隔时间
:param websocket.WebSocket ws:
:return:
"""
chunk_ms = 160 # 160ms的录音
chunk_len = int(16000 * 2 / 1000 * chunk_ms)
with open(pcm_file, 'rb') as f:
pcm = f.read()
index = 0
total = len(pcm)
logger.info("send_audio total={}".format(total))
while index < total:
end = index + chunk_len
if end >= total:
# 最后一个音频数据帧
end = total
body = pcm[index:end]
logger.debug("try to send audio length {}, from bytes [{},{})".format(len(body), index, end))
ws.send(body, websocket.ABNF.OPCODE_BINARY)
index = end
time.sleep(chunk_ms / 1000.0) # ws.send 也有点耗时,这里没有计算
def send_finish(ws):
"""
发送结束帧
:param websocket.WebSocket ws:
:return:
"""
req = {
"type": "FINISH"
}
body = json.dumps(req)
ws.send(body, websocket.ABNF.OPCODE_TEXT)
logger.info("send FINISH frame")
def send_cancel(ws):
"""
发送取消帧
:param websocket.WebSocket ws:
:return:
"""
req = {
"type": "CANCEL"
}
body = json.dumps(req)
ws.send(body, websocket.ABNF.OPCODE_TEXT)
logger.info("send Cancel frame")
def on_open(ws):
"""
连接后发送数据帧
:param websocket.WebSocket ws:
:return:
"""
def run(*args):
"""
发送数据帧
:param args:
:return:
"""
send_start_params(ws)
send_audio(ws)
send_finish(ws)
logger.debug("thread terminating")
threading.Thread(target=run).start()
def on_message(ws, message):
"""
接收服务端返回的消息
:param ws:
:param message: json格式,自行解析
:return:
"""
logger.info("Response: " + message)
resultResponse.append(message)
def on_error(ws, error):
"""
库的报错,比如连接超时
:param ws:
:param error: json格式,自行解析
:return:
"""
logger.error("error: " + str(error))
def on_close(ws):
"""
Websocket关闭
:param websocket.WebSocket ws:
:return:
"""
logger.info("ws close ...")
# ws.close()
def record():
framerate = 16000 # 采样频率 8000 or 16000
channels = 1 # 声道数
sampwidth = 2 # 采样字节 1 or 2
# 实时录音的参数
CHUNK = 1024 # 录音的块大小
RATE = 16000 # 采样频率 8000 or 16000
RECORD_SECONDS = 6 # 录音时长 单位 秒(s)
pa = pyaudio.PyAudio()
stream = pa.open(format=pyaudio.paInt16, channels=channels, rate=framerate, input=True, frames_per_buffer=CHUNK)
# print('开始录音,请说话:')
frames = []
for i in range(0, int(RATE/CHUNK*RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
# print('录音结束!')
path = r'D:\myvoice.wav'
wf = wave.open(path, 'wb')
wf.setnchannels(channels)
wf.setsampwidth(sampwidth)
wf.setframerate(framerate)
wf.writeframes(b"".join(frames))
wf.close()
if __name__ == "__main__":
resultResponse=[]
#1.语音转文字
#1.1录音
record()
#1.2识别
logging.basicConfig(format='[%(asctime)-15s] [%(funcName)s()][%(levelname)s] %(message)s')
logger.setLevel(logging.INFO) # 调整为logging.INFO,日志会少一点 (DEBUG)
logger.info("begin")
# websocket.enableTrace(True)
uri = URI + "?sn=" + str(uuid.uuid1())
logger.info("uri is "+ uri)
ws_app = websocket.WebSocketApp(uri,
on_open=on_open, # 连接建立后的回调
on_message=on_message, # 接收消息的回调
on_error=on_error, # 库遇见错误的回调
on_close=on_close) # 关闭后的回调
ws_app.run_forever()
# print("语音转文字结束!")
语音合成技术的本质是将文本信息转化成语音信息。概 括 起 来 说, 语 音 合 成 的 主 要 功 能 是: 根 据 韵 律 建 模 的 结 果, 从 原 始 语 音 库 中 取 出 相 应 的 语 音 基 元, 利 用 特 定 的 语 音 合 成 技 术 对 语 音 基 元 进 行 韵 律 特 性 的 调 整 和 修 改, 最 终 合 成 出 符 合 要 求 的 语 音。
常用的技术有单元挑选波形拼接技术、基于HMM的参数语音合成技术和基于深度学习的语音合成技术。单元挑选波形拼接技术主要是从原始语音库中挑选需要合成的语音文字,然后进行拼接成完整的一句话。基于HMM的参数语音合成技术主要包括高质量语音声码器和基于上下文的决策树模型。高质量语音声码器首先将语音库的语音转换一系列声学特征信号,其次采用基于上下文的决策树模型去预测文本与声学参数之间的对应关系,进而将文本转换成语音。
import win32com.client
'''
微软所提供的SAPI (全称The Microsoft Speech API),正是在应用程序和语音引擎之间提供一个高级别的接口,它实现了所有必需的对各种语音引擎的实时的控制和管理等低级别的细节。语音引擎通过DDI层(设备驱动接口)和SAPI进行交互,应用程序通过API层和SAPI通信。
'''
'''
SAPI包括以下组件对象(接口):
(1)Voice Commands API。对应用程序进行控制,一般用于语音识别系统中。识别某个命令后,会调用相关接口是应用程序完成对应的功能。如果程序想实现语音控制,必须使用此组对象。
(2)Voice Dictation API。听写输入,即语音识别接口。
(3)Voice Text API。完成从文字到语音的转换,即语音合成。
(4)Voice Telephone API。语音识别和语音合成综合运用到电话系统之上,利用此接口可以建立一个电话应答系统,甚至可以通过电话控制计算机。
(5)Audio Objects API。封装了计算机发音系统。
'''
if __name__ == '__main__':
question=input("语音合成的文字内容:")
speaker = win32com.client.Dispatch("SAPI.SpVoice")
speaker.Speak(question)
[1] https://www.cnblogs.com/tuyile006/p/8471622.html
[2] http://www.360doc.com/content/17/0705/16/44422250_669096916.shtml
[3] https://www.bilibili.com/video/BV1A54y167w8?from=search&seid=4667329003657407722
[4] http://www.jizhuomi.com/software/614.html