Python实时音频识别与处理——让上网课不再单调

Python实时语音识别转字幕

实现原理

用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与密钥调用的是博主的免费额度,到达上限后可能会报错。有兴趣的同学可以了解百度云的其它功能,自行注册账号获得调用额度。有任何问题欢迎私信讨论或评论区留言!

你可能感兴趣的:(奇怪的工具增加了!,python,语音识别,github,百度)