241205_使用本地vosk模型实现流式语音识别

241205_使用本地vosk模型实现流式语音识别

上一篇我们使用了vosk模型实现了本地的语音识别,但是存在一个严重的问题,因为我们采用的是整段音频录制结束之后再进行转文字并进行关键字检索,就会导致识别不实时,在环境噪音较为复杂(或者正在播放音乐时),我们说完了话他还在持续录音状态,识别太慢了,并且有时候他把音乐声音也录进去,导致识别错误。要解决这样的问题,只能采用流式语音识别。

流式语音识别就是,你这边一直说话,电脑这边边录入边识别,就不是整段音频录入再识别了,大大提高了识别效率。

和上一篇的代码相比,我们这里主要修改了weekup函数以及添加了stream_decode函数,并且把相关的逻辑处理方法单独拿出来写了一个函数process_command。采用的还是本地vosk模型。

前面的载入模型,初始化参数,打开音频流都是不变的

model = Model("vosk-model-cn-0.15")
SetLogLevel(-1)
FORMAT = pyaudio.paInt16  # 音频流的格式
RATE = 16000              # 采样率,单位Hz
CHUNK = 4000              # 单位帧
audio = pyaudio.PyAudio()
stream = audio.open(format=FORMAT,
                   channels=1,
                   rate=RATE,
                   input=True,
                   frames_per_buffer=CHUNK)
   

主要实现方法在这里:

在weekup方法中

创建一个队列 data_queue 来存储音频数据块,并启动一个线程 t 来运行 stream_decode 函数,将模型、队列和 mw 对象作为参数传递给该函数。

data_queue = queue.Queue()
t = threading.Thread(target=stream_decode, args=(model, data_queue, mw))
t.daemon = True
t.start()

不断从音频流中读取数据块,并将其放入队列 data_queue 中。

print("开始录音...")
while True:
   data = stream.read(CHUNK, exception_on_overflow=False)
   data_queue.put(data)

到这里实现了把我们的语音分块装入队列中,我们还要实现去读取出这个数据块进行语音识别。

编写解码方法stream_decode

初始化一个 Kaldi 识别器,并设置为输出单词级别的识别结果。

rec = KaldiRecognizer(model, 16000)
rec.SetWords(True)

不断从队列 data_queue 中获取音频数据块,并将其传递给识别器进行处理。如果识别器接受到完整的语音数据并生成识别结果,则解析 JSON 格式的识别结果,并调用 process_command 函数处理识别出的文本。

while True:
   data = data_queue.get()
   if rec.AcceptWaveform(data):
       result = json.loads(rec.Result())
       if 'text' in result and result['text']:
           process_command(result['text'], mw)

因为我们转换出来的结果是单词级别的,所以可能会产生识别的每一个单独的词之间都有空格,我们在process_command方法中需要去除掉这些空格,重新把他拼接成一个句子,实现我们的关键词检索。

image-20241205222117346

完整代码:

import json
import time
import pyaudio
import numpy as np
from vosk import Model, KaldiRecognizer, SetLogLevel
from baidu_tts import baidu_tts_test
from pypinyin import lazy_pinyin
import queue
import threading
dir_path = {
    '浏览器': "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
    '记事本': "C:\\Windows\\System32\\notepad.exe",
    '计算器': "C:\\Windows\\System32\\calc.exe"
}

def stream_decode(model, data_queue,mw):
    rec = KaldiRecognizer(model, 16000)
    rec.SetWords(True)
    while True:
        data = data_queue.get()
        if rec.AcceptWaveform(data):
            result = json.loads(rec.Result())
            if 'text' in result and result['text']:
                process_command(result['text'],mw)

def process_command(text,mw):
    # print(text)
    text=text.replace(" ","")
    print(text)
    if "小爱同学" in text:
        answer = "我在"
        answermethod(answer)

    if "聊天" in text:
        answer = "好的,请开始"
        answermethod(answer)
        from stt import run as stt_run
        result = stt_run()

    if "打开" in text:
        app_name = text.replace("打开", '').strip()
        if app_name in dir_path:
            app_path = dir_path[app_name]
            import subprocess
            subprocess.Popen(app_path)
            answer = "好的,已经为您打开了"
            answermethod(answer)

    if "歌" in text:
        from testyuncloud import yuncloudMW
        mw.playMusic()
        # print("播放歌曲")

    if "暂停" in text:
        mw.playMusic()

    if "播放" in text:
        mw.playMusic()

    if "上一首" in text:
        mw.prevMusic()

    if "下一首" in text:
        mw.nextMusic()

    if "音量" in text:
        volumn = text.split('百分之')[1]
        volumn = hanzi_to_number_pinyin(volumn)
        print(volumn)
        mw.volumeSet(volumn)

def answermethod(answer):
    baidu_tts_test(answer)
    time.sleep(1)

def weekup(mw):
    model = Model("vosk-model-cn-0.15")
    SetLogLevel(-1)

    FORMAT = pyaudio.paInt16  # 音频流的格式
    RATE = 16000              # 采样率,单位Hz
    CHUNK = 4000              # 单位帧

    audio = pyaudio.PyAudio()
    stream = audio.open(format=FORMAT,
                        channels=1,
                        rate=RATE,
                        input=True,
                        frames_per_buffer=CHUNK)

    data_queue = queue.Queue()
    t = threading.Thread(target=stream_decode, args=(model, data_queue,mw))
    t.daemon = True
    t.start()

    print("开始录音...")
    while True:
        data = stream.read(CHUNK, exception_on_overflow=False)
        data_queue.put(data)

def hanzi_to_number_pinyin(hanzi_str):
    hnd = {
        'ling': 0, 'yi': 1, 'er': 2, 'san': 3, 'si': 4, 'wu': 5, 'liu': 6, 'qi': 7, 'ba': 8, 'jiu': 9,
        'shi': 10, 'bai': 100, 'qian': 1000, 'wan': 10000, 'yi': 100000000
    }
    pinyin_list = lazy_pinyin(hanzi_str)
    result = 0
    temp = 0
    for pinyin in pinyin_list:
        if pinyin in hnd:
            digit = hnd[pinyin]
            if digit >= 10:
                if temp == 0:
                    temp = 1
                result += temp * digit
                temp = 0
            else:
                temp = temp * 10 + digit
    result += temp
    return result


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CMake笔记之在CMakeLists.txt文件中开启Debug模式

CMake笔记之在CMakeLists.txt文件中开启Debug模式 code review! 文章目录 CMake笔记之在CMakeLists.txt文件中开启Debug模式1.设置 CMake 的构建类型2.添加编译器的调试选项3.使用 CMAKE_CXX_STANDARD (可选)4.编译和构建5.针对多配置生成器6.最终示例 CMakeLists.txt 1.设置 …

VINS_MONO视觉导航算法【一】基础知识介绍

文章目录 VINS-Mono其他文章说明简介单目相机存在的尺度不确定问题缺乏深度信息尺度等价性对极几何和三角化平移和深度的关系解决尺度不确定问题的方法视觉惯性里程计(VIO)初始尺度估计持续尺度校正 摄像头数据处理直接法(Direct Method&…

【CC2530开发基础篇】光敏和热敏传感器

一、前言 1.1 开发背景 本实验通过CC2530单片机接入光敏传感器和热敏传感器,进行数据采集与检测,并将检测结果通过串口终端输出。光敏传感器和热敏传感器是常见的环境感知设备,分别用于测量光强和温度。在实际应用中,这些传感器…

计算机网络-GRE基础实验二

前面我们学习了GRE隧道的建立以及通过静态路由指向的方式使得双方能够网络互联,但是通过静态路由可能比较麻烦,GRE支持组播、单播、广播因此可以在GRE隧道中运行动态路由协议使得网络配置更加灵活。 通过前面的动态路由协议的学习我们知道动态路由协议都…

中建海龙:科技创新引领建筑业革新,铸就行业影响力

在建筑业这个古老而又充满活力的行业中,中建海龙科技有限公司(以下简称“中建海龙”)凭借其卓越的科技实力和一系列荣誉奖项,正逐步确立其在建筑工业化领域的领导地位,并对整个行业产生了深远影响。 中建海龙自成立以来…

Y20030028 JAVA+SSM+MYSQL+LW+基于JAVA的考研监督互助系统的设计与实现 源代码 配置 文档

基于JAVA的考研监督互助系统 1.项目描述2. 课题开发背景及意义3.项目功能4.界面展示5.源码获取 1.项目描述 随着高等教育的普及和就业竞争的加剧,越来越多的学生选择继续深造,参加研究生入学考试。考研人数的不断增加,使得考研过程中的学习监…

HarmonyOS NEXT开发进阶(一):初识 HarmonyOS NEXT开发

文章目录 一、前言二、HarmonyOS NEXT 开发框架三、HarmonyOS NEXT开发指导3.1 Windows环境准备 四、项目拆解4.1 工程目录4.2 全局配置4.2.1 APP全局配置: AppScope层(AppScope/app.json5)4.2.3 签名全局配置 4.3 APP代码初始化4.4 APP签名文件配置4.5 …

【机器学习算法】——逻辑回归

目录 逻辑回归理解损失函数代码练习1. 房屋价格与面积的关系2.基于学生特征的录取概率预测 逻辑回归理解 逻辑回归是用来二分类的! 是在线性回归模型之后加了一个激活函数(Sigmoid)将预测值归一化到【0~1】之间,变成概率值。 一般计算其中一…

mongo开启慢日志及常用命令行操作、数据备份

mongo开启慢日志及常用命令行操作、数据备份 1.常用命令行操作2.mongo备份3.通过命令临时开启慢日志记录4.通过修改配置开启慢日志记录 1.常用命令行操作 连接命令行 格式:mongo -u用户名 -p密码 --host 主机地址 --port 端口号 库名; 如:连…

排序的事

排序的事 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 输入n个不相同的正整数,每个数都不超过n。现在需要你把这些整数进行升序排序,每次可以交换两个数的位置,最少需…

.NET Framework修复工具

某些精简Windows系统或者第三方下载的改版Windows系统在安装.NET Framework的时候会出现类似下面的错误信息: 可以使用微软官方出的.NET Framework修复工具解决, 下载地址: 【免费】.NETFramework修复工具资源-CSDN文库 下载后运行即可修复系统里的.NET Framework

PyTorch 本地安装指南:全面支持 macOS 、 Linux 和 Windows 系统

PyTorch 本地安装指南:全面支持 macOS 、 Linux 和 Windows 系统 PyTorch 是一个功能强大的深度学习框架,支持高效的计算图和 GPU 加速,广泛应用于人工智能和机器学习项目中。本文从安装前的准备工作开始,详细介绍了如何使用 con…

【单片机基础知识】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]

参考资料: MCU的三种启动方式 - EdgeAI Lab 立芯嵌入式的视频 在SRAM中运行代码 - EdgeAI Lab 利用 Boot 选择不同的启动方式: 根据不同的启动方式,将不同的地址(主 FLASH/系统存储器/嵌入式 SRAM)映射到 0x0000 0000(系统中断向量表) 上…

记录一个Flutter 3.24单元测试点击事件bug

哈喽,我是老刘 这两天发现一个Flutter 3.24版本的单元测试的一个小bug,提醒大家注意一下。 老刘自己写代码十多年了,写Flutter也6年多了,没想到前两天在一个小小的BottomNavigationBar 组件上翻了车。 给大家分享一下事件的经过。…

第四篇:k8s 理解Service工作原理

什么是service? Service是将运行在一组 Pods 上的应用程序公开为网络服务的抽象方法。 简单来说K8s提供了service对象来访问pod。我们在《k8s网络模型与集群通信》中也说过k8s集群中的每一个Pod(最小调度单位)都有自己的IP地址,都…

基于ResNet50和VGG16深度学习模型的阿尔茨海默病MRI图像分类与早期诊断研究

阿尔茨海默病(AD)是目前全球范围内最常见的神经退行性疾病之一,早期诊断对延缓疾病进程和改善患者生活质量至关重要。随着医学影像学的进步,基于MRI图像的阿尔茨海默病检测成为一种重要的研究方向。本文提出了一种基于深度学习的M…

【日常记录-Mybatis】PageHelper导致语句截断

1. 简介 PageHelper是Mybatis-Plus中的一个插件,主要用于实现数据库的分页查询功能。其核心原理是将传入的页码和条数赋值给一个Page对象,并保存到本地线程ThreadLocal中,接下来,PageHelper会进入Mybatis的拦截器环节,…

MFC实现全屏功能

之前全屏都是参考: MFC单文档(SDI)全屏程序的实现 主要思路就是将各种菜单工具栏隐藏恢复。 随着MFC的升级,MFC框架本身就具备了全屏的功能。 微软有一个全屏实现类: CFullScreenImpl Class managing full-screen mod…

nn.RNN解析

以下是RNN的计算公式,t时刻的隐藏状态H(t)等于前一时刻隐藏状态H(t-1)乘以参数矩阵,再加t时刻的输入x(t)乘以参数矩阵,最后再通过激活函数,等到t时刻隐藏状态。 下图是输出input和初始化的隐藏状态,当参数batch_first True时候&…

运算符重载(五)

目录 const成员函数const对象不可以调用非const成员函数非const对象可以调用const成员函数const成员函数内不可以调用其它的非const成员函数非const成员函数内可以调用其它的const成员函 取地址及const取地址操作符重载const补充场景1场景2场景3场景4 const成员函数 将const修…