实时asr新服务串讲

1.背景及现状

         工程方面目前语音相关服务存在大量重复代码,逻辑复杂,文档缺失,并且某些细节设计不合理。基于目前现状,代码业务与功能耦合严重,迭代困难,将来增加新的能力也需要改动音频数据相关代码,开发周期较长。

         推理框架目前老服务使用的Kaldi推理框架,需要使用业界最新的推理框架去替代老的框架,以便在模型大小,识别准确率,识别速率,以及实时效果等多方面进行优化。相对于Kaldi来说Whisper是一个轻量级的语音处理工具库,专注于实时语音处理和嵌入式设备。它提供了一些基本的语音处理功能,如语音增强、语音识别、语音合成等。Whisper的设计目标是在资源受限的环境下实现高效的语音处理,因此它的代码量相对较小,适合在嵌入式设备或边缘计算平台上使用,所以可以有效的降低资源占用。

2.整体流程架构

新的架构流程

新的架构流程

可以看出,老服务有两个问题,首先是协议的选择,一次session需要进行多次http请求排序等分片组合逻辑会大大增加代码复杂度,另外很多业务能力(比如训练场,直播)处理放在了整个asr识别服务里面,属于功能与业务的耦合,需要进行拆解,方便代码维护与迭代。

3.新架构具体方案

1.协议相关

  • 协议方面参考阿里接口

如何自行开发代码访问阿里语音服务_智能语音交互(ISI)-阿里云帮助中心

  • 协议交互流程图

  • sdk相关

       对于用户端来说,接入asr可以通过两个方式接入,一种是直接根据协议文档进行接入,另一种是需要根据服务端提供的针对各个平台的sdk进行能力接入。

 调研是否可以复用阿里的sdk:

     相关链接

如何下载安装、使用实时语音识别PythonSDK及代码示例_智能语音交互(ISI)-阿里云帮助中心

 下载sdk查看依赖

可以看出来,阿里给的sdk需要安装他自身的核心库,这样会导致某些部分代码对我们来说是黑盒子,将来版本更替,能力升级,都可能会遇上兼容的问题。

  测试代码

import time
import threading
import sysimport nls
# from tests.test_utils import (TEST_ACCESS_TOKEN, TEST_ACCESS_APPKEY)class TestSr:def __init__(self, tid, test_file):
        self.__th = threading.Thread(target=self.__test_run)
        self.__id = tid
        self.__test_file = test_filedef loadfile(self, filename):with open(filename, 'rb') as f:
            self.__data = f.read()def start(self):
        self.loadfile(self.__test_file)
        self.__th.start()def test_on_start(self, message, *args):print('test_on_start:{}'.format(message))def test_on_error(self, message, *args):print('on_error args=>{}'.format(args))def test_on_close(self, *args):print('on_close: args=>{}'.format(args))def test_on_result_chg(self, message, *args):print('test_on_chg:{}'.format(message))def test_on_completed(self, message, *args):print('on_completed:args=>{} message=>{}'.format(args, message))def __test_run(self):print('thread:{} start..'.format(self.__id))#ws://127.0.0.1:8081/v1/asr/realtime
        sr = nls.NlsSpeechRecognizer(
                    url = 'ws://127.0.0.1:8081/v1/asr/realtime',
                    token='none',
                    appkey='none',
                    on_start=self.test_on_start,
                    on_result_changed=self.test_on_result_chg,
                    on_completed=self.test_on_completed,
                    on_error=self.test_on_error,
                    on_close=self.test_on_close,
                    callback_args=[self.__id])while True:print('{}: session start'.format(self.__id))
            r = sr.start(ex={'format':'pcm', 'hello':123})            self.__slices = zip(*(iter(self.__data),) * 640)for i in self.__slices:
                sr.send_audio(bytes(i))
                time.sleep(0.01)            r = sr.stop()print('{}: sr stopped:{}'.format(self.__id, r))
            time.sleep(5)def multiruntest(num=500):for i in range(0, num):
        name = 'thread' + str(i)
        t = TestSr(name, 'tests/test1.pcm')
        t.start()nls.enableTrace(True)
multiruntest(1)

结论

     使用官网sdk的话需要绕过相关验证机制,目前觉得应该不太合适.。

2.引擎框架

       目前依据不同的库实现了两套引擎,一套是基于transform,一套基于fast-whisper,两种开元框架使用了不同的窗口策略。总体思路都是切分的方式,控制模型每次运算接收到的上下文窗口大小,让模型可以有对序列局部建模能力,然后将局部计算的结果拼接起来。

基本流程图

音频数据分片传输

      上面是一段单通道 16khz  16bit 的pcm原始音频数据的波形图,录音设备获取原始数据后将数据按照时间分片存储在内存中,也就是数据采样的过程。将连续的模拟信号改为可存储量化的数字信号。

音频数据量化

       将采样获取的数据使用numpy库进行音频数据量化,根据位深将数据量化为相应的数组,数组中每一个数据绝对值都小于2的16次方,方便后续输入算法模块。

静音检测处理

音频数据量化的基础上,后续的滑动窗口策略需要使用到静音来进行断句,静音原理是根据量化后的数据值是否大于100来确定的,因为外界有你声音的话,声音数据波动在2000以上。但是对于以后得优化可以进一步通过模型识别人声和非人声将这块逻辑进行替换,这样对于一些噪音很大的场景会提升识别准确率。

滑动窗口策略

  • 基于transform实现流式的窗口策略

         使用该推理框架实现流式,由于窗口太小识别数据不准确,另外依据测试结果,对于稍微长的语音(小于30s),识别的rtf参数值小于1.0,可以满足流式的基本要求,所以滑动窗口采用音频buffer逐渐增加的方式最为窗口滑动策略。

具体流程图如下:

  • 基于fast-whisper实现流式窗口策略

对于fast-whisper,使用github上开源的流式推理工程:

GitHub - ufal/whisper_streaming: Whisper realtime streaming for long speech-to-text transcription and translation

分析源码,发现由于fast-whisper提供的音频识别api支持condition_on_previous_text

参数,可以将之前识别的文本输出输入模型,协助模型识别该段音频数据,所以该推理工程使用数据buffer窗口大小不变,文本buffer滚动的方式进行流式处理。

具体流程如下:

4.测试指标

测试指标目前主要是字准与数据返回速度:

changeUrl

结论:

1.阿里目前首字时间打开600毫秒到800毫秒左右,流式过程中平均延时300ms到600ms范围内波动。

2.目前transform引擎目前首字时间打开600毫秒到800毫秒左右,流式过程中平均延时300ms到600ms范围内波动。

5.后续优化思考

  • 工程方面

在调试过程中,不同的窗口大小,不同的数据流速,静音阈值的大小,对识别效果或多或少都有一定的影响,可能也是因为这个原因(当然也有别的原因,比如网络不稳定或者音频文件本身噪音就比较大等),会导致之前算法测试结果和实际使用中的结果有很大差异,所以如果遇上算法同学认为识别效果不错但是工程实现之后发现识别结果不尽人意,可以尝试调节不同的工程参数,尝试找到最契合算法测试环境的情况。

  •   推理框架

      对于推理框架不只需要熟悉相关api相关参数,还要尽可能熟悉具体的内部原理,这样在模型调参过程中就不是盲目取尝试,做到先预期结果然后再验证。

      另外比如想办法让模型可以识别人声,这样对于噪音场景的识别效果也会有所提升。

  •      接入方式

   后续需要提供各个平台的sdk接入接口(第一阶段可以先让试用方根据协议进行接入)。

1

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Allegro如何导入芯片的Pin Delay?

Allegro在做等长时,需要导入芯片的Pin Delay才能做真正的等长。因为有些芯片内部的引脚本身就是不等长的,例如海思的部分芯片。 那么如何导入芯片的Pin Delay呢? 1、打开约束管理器,点击Properties(属性)→Component(器件)→Pin Properties→General。 在右栏找到芯片U1,…

实时嵌入式Linux设备基准测试快速入门4测试和测量

本章将介绍主要测试方案及其具体配置和结果。在介绍实际测量结果之前,将尽可能总结被测设备的特性。最后,将对结果进行分析,并概述由于高速缓存一致性问题造成的延迟方面的主要瓶颈,提出减少延迟的解决方案,并解释用于…

Duplicate object key json(520)

亲爱的码友,当你看到这个错误 请查看一下你的json文件内容的关键词是不是重复了 举个栗子🌰 往下翻翻: 删一个就行!!! 被自己傻哭了吧🤣🤣🤣

js实现九九乘法表

效果图 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><script type"text/javascript">// 输出乘法口诀表// document.write () 空格 " " 换行…

Flowable 生成流程图

/*** 生成流程图** param processId 任务ID*/ RequestMapping("/diagram/{processId}") public void genProcessDiagram(HttpServletResponse response,PathVariable("processId") String processId) {InputStream inputStream flowTaskService.diagram(p…

HubSpot整合小红书,MessageBox助力多系统融合

在当今数字化潮流中&#xff0c;HubSpot与小红书的强大联盟成为了数字化市场的亮点。今天运营坛将深入解析它们的合作策略&#xff0c;聚焦于MessageBox在整合中的关键角色&#xff0c;以及它在推动HubSpot和小红书整合方面的关键作用。 HubSpot与小红书&#xff1a;数字化市场…

【Linux驱动】休眠与唤醒 | POLL机制 | 异步通知 | 阻塞与非阻塞 | 软件定时器

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《Linux驱动》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 目录 &#x1f3d3;休眠与唤醒&#x1f3f8;内核函数&#x1f3f8;驱动框架及编程 &#x1f3d3;…

代码随想录算法训练DAY25|回溯2

算法训练DAY25|回溯2 216.组合总和III 力扣题目链接 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数&#xff0c;并且每种组合中不存在重复的数字。 说明&#xff1a; 所有数字都是正整数。 解集不能包含重复的组合。 示例 1: 输入: k 3, n …

本地部署轻量级web开发框架Flask并实现无公网ip远程访问开发界面

文章目录 1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 本篇文章主要讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网进行远程访问。 Flask是目前十分流行的web框架&#xff0c;采用Python编程语…

Linux操作系统——理解软硬链接

1.引言 通过我们前面理解文件系统的基础上&#xff0c;我们来理解软硬链接&#xff0c;在我们学习文件的时候我们会见到各种链接文件&#xff0c;其中链接文件分为两种&#xff0c;一种叫软连接&#xff0c;一种叫硬链接。 下面我们新建一个log文件&#xff0c;要对log这个文…

【SpringCloud Alibaba】 介绍及微服务模块搭建

文章目录 SpringCloud Alibaba 介绍主要功能组件 微服务环境搭建案例准备技术选型模块设计微服务调用 创建父工程创建基础模块1、创建 shop-common 模块2、创建实体类 创建用户微服务1、创建pom.xml2、编写主类3、创建配置文件 创建商品微服务1、创建一个名为 shop-product 的模…

理解PCIE设备透传

PCIE设备透传解决的是使虚拟机直接访问PCIE设备的技术&#xff0c;通常情况下&#xff0c;为了使虚拟机能够访问Hypervisor上的资源&#xff0c;QEMU&#xff0c;KVMTOOL等虚拟机工具提供了"trap and emulate"&#xff0c; Virtio半虚拟化等机制实现。但是这些实现都…

websocket实现聊天室(vue2 + node)

通过websocket实现简单的聊天室功能 需求分析如图&#xff1a; 搭建的项目结构如图&#xff1a; 前端步骤&#xff1a; vue create socket_demo (创建项目)views下面建立Home , Login组件路由里面配置路径Home组件内部开启websocket连接 前端相关组件代码&#xff1a; Login…

【操作系统】实验二 Proc文件系统

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

使用Rancher管理Kubernetes集群

部署前规划 整个部署包括2个部分&#xff0c;一是管理集群部署&#xff0c;二是k8s集群部署。管理集群功能主要提供web界面方式管理k8s集群。正常情况&#xff0c;管理集群3个节点即可&#xff0c;k8s集群至少3个。本文以3节点管理集群&#xff0c;3节点k8s集群为例 说明部署过…

vivado JTAG链、连接、IP关联规则

JTAG链 这列出了定义板上可用的不同JTAG链。每个链都列在下面<jtag_chain>以及链的名称&#xff0c;以及定义名称和链中组件的位置&#xff1a; <jtag_chains> <jtag_chain name"chain1"> <position name"0" component"part0…

ELK 分离式日志(1)

目录 一.ELK组件 ElasticSearch&#xff1a; Kiabana&#xff1a; Logstash&#xff1a; 可以添加的其它组件&#xff1a; ELK 的工作原理&#xff1a; 二.部署ELK 节点都设置Java环境: 每台都可以部署 Elasticsearch 软件&#xff1a; 修改elasticsearch主配置文件&…

计算机视觉工程师就业前景如何?

计算机视觉作为一门快速发展的技术领域&#xff0c;其就业前景非常广阔。以下是对计算机视觉就业前景的分析&#xff1a; 市场规模&#xff1a;计算机视觉行业的市场规模正在持续扩大。根据行业分析报告&#xff0c;预计全球计算机视觉市场规模将在2025年达到530亿美元&#xf…

【Web实操10】定位实操_图片上面定位文字

参考实现的效果是这样的&#xff1a; 目前还没有学到渐变色&#xff0c;所以标签效果的渐变色没有实现&#xff0c;只是利用radius设置了圆角图形&#xff0c;辅之以背景色和设置其中文本文字的颜色和居中对齐。 在自己写的过程中&#xff0c;对于标签的定位写成了相对定位&a…

RabbitMQ的安装使用

RabbitMQ是什么&#xff1f; MQ全称为Message Queue&#xff0c;消息队列&#xff0c;在程序之间发送消息来通信&#xff0c;而不是通过彼此调用通信。 RabbitMQ 主要是为了实现系统之间的双向解耦而实现的。当生产者大量产生数据时&#xff0c;消费者无法快速消费&#xff0c;…