用speech_recognition库获得实时电脑音频输入,用requests和json库将生成的语音文件上传至百度的云语音识别服务器进行识别,返回结果用wx库显示为字幕,同时写为txt文件作为记录。用threading库调用两个thread,一个识别和处理音频,另一个从txt文件读取生成字幕。
该项目为个人参赛作品。原名TRAS(Toolkit for Recognition and Automatic Summarization),语音识别与自动总结工具。具体使用说明请看我的Github。该项目可用来为网课或语音生成字幕,也可帮助聋哑人“听”到电脑音频。代码写的不规范,请各位见谅!
以下代码在我的Github上也有。这里为学习与分享的目的加了注释。
import requests
import json
import base64
import os
import logging
import speech_recognition as sr
import wx
import threading
#调用库
def get_token(): # 调用百度云语音识别API,具体看百度的技术文档
logging.info('Retrieving token...') #和print差不多
baidu_server = "https://openapi.baidu.com/oauth/2.0/token?"
grant_type = "client_credentials"
client_id = "EUON57v2pcpk5CDQnet6AN6s" #你的ID
client_secret = "oHb0INPt5MGSC4LfoQ9hd7W2oSR6GLmV" #密钥
url = f"{baidu_server}grant_type={grant_type}&client_id={client_id}&client_secret={client_secret}"
res = requests.post(url)
token = json.loads(res.text)["access_token"] #用json处理返回数据
return token
def audio_baidu(filename): # 上传音频至百度云语音识别,返回结果存储为文本
if not os.path.exists('record'):
os.makedirs('record') #创建目录
filename = 'record/' + filename
logging.info('Analysing audio file...')
with open(filename, "rb") as f:
speech = base64.b64encode(f.read()).decode('utf-8')
size = os.path.getsize(filename)
token = get_token()
headers = {'Content-Type': 'application/json'}
url = "https://vop.baidu.com/server_api"
data = {
"format": "wav",
"rate": "16000",
"dev_pid": 1737, #识别类型。1737=english, 17372=enhanced english, 15372=enhanced chinese, 具体参考百度技术文档
"speech": speech,
"cuid": "3.141592653589793238462643383279502884197169399375105820", #独特的符号串
"len": size,
"channel": 1,
"token": token,
}
req = requests.post(url, json.dumps(data), headers)
result = json.loads(req.text)
if result["err_msg"] == "success.":
message = ''.join(result['result'])
print('RETURNED: ' + message)
return result['result']
else:
print("RETURNED: Recognition failure")
return -1
def main(): # 线程2: 语音识别
logging.basicConfig(level=logging.INFO)
wav_num = 0
while True:
r = sr.Recognizer() #创建识别类
mic = sr.Microphone() #创建麦克风对象
logging.info('Recording...')
with mic as source:
r.adjust_for_ambient_noise(source) #减少环境噪音
audio = r.listen(source, timeout=1000) #录音,1000ms超时
with open('record/' + f"00{wav_num}.wav", "wb") as f:
f.write(audio.get_wav_data(convert_rate=16000)) #写文件
message = ''.join(audio_baidu(f"00{wav_num}.wav"))
history = open('record/' + f"history.txt", "a")
history.write(message + '\n')
history.close()
wav_num += 1
def update_content(win, height=200, width=800): #用来更新字幕窗口内容
f = open('record/' + f"history.txt", "r") #读取文件
try:
last_line = f.readlines()[-1] #读文件最后一行
except IndexError:
last_line = ''
if last_line.strip('\n') in ['key point']: #有特殊词汇的话字幕加粗显示
logging.info('Emphasized')
ft = wx.Font(80, wx.MODERN, wx.NORMAL, wx.BOLD, False, '') #设置字体
else:
ft = wx.Font(50, wx.MODERN, wx.NORMAL, wx.NORMAL, False, '')
richText = wx.TextCtrl(win, value='', pos=(0, 0), size=(width, height))
richText.SetInsertionPoint(0) #从头插入文字,把原来的内容顶掉
richText.SetFont(ft)
richText.SetValue(last_line)
f.close()
return last_line
def show_win(x=320, y=550, height=200, width=800): #创建字幕窗口
win = wx.Frame(None, title="TRAS v1.0.0", pos=(x, y), size=(width, height), style=wx.STAY_ON_TOP) #创建Frame对象
win.SetTransparent(1000) #透明度
win.Show()
return win
#主程序
if __name__ == "__main__":
history = open('record/' + f"history.txt", "w+")
history.close()
thread = threading.Thread(target=main) #创建另一个thread跑语音识别
thread.start()
global app #这里有报错,要设置全局变量
app = wx.App() #创建对象
while True:
win = show_win() #创建字幕窗口
v = update_content(win) #更新窗口内容
wx.CallLater(2000, win.Destroy) #两秒没操作的话隐藏窗口
app.MainLoop()
(整个项目的运行方法请看Github)
程序开始运行后,对着电脑麦克风说话,就能顺利显示实时字幕啦!
该程序目前支持MacOS,WinOS未测试。选用ws库也是因为它支持Mac更好。其它的辅助功能请见github。这里的版本是英文识别,目前的id与密钥调用的是博主的免费额度,到达上限后可能会报错。有兴趣的同学可以了解百度云的其它功能,自行注册账号获得调用额度。有任何问题欢迎私信讨论或评论区留言!