UnityWebGL使用sherpa-ncnn实时语音识别

k2-fsa/sherpa-ncnn:在没有互联网连接的情况下使用带有 ncnn 的下一代 Kaldi 进行实时语音识别。支持iOS、Android、Raspberry Pi、VisionFive2、LicheePi4A等。 (github.com)

如果是PC端可以直接使用ssssssilver大佬的 https://github.com/ssssssilver/sherpa-ncnn-unity.git

我这边要折腾的是WebGL版本的,所以修改了一番

1、WebSocket,客户端使用了psygames/UnityWebSocket: :whale: The Best Unity WebSocket Plugin for All Platforms. (github.com)

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityWebSocket;public class uSherpaWebGL : MonoBehaviour
{IWebSocket ws;public Text text;Queue<string> msgs = new Queue<string>();// Start is called before the first frame updatevoid Start(){ws = new WebSocket("ws://127.0.0.1:9999");ws.OnOpen += OnOpen;ws.OnMessage += OnMessage;ws.OnError += OnError;ws.OnClose += OnClose;ws.ConnectAsync();}// Update is called once per framevoid Update(){if (msgs.Count > 0){string msg = msgs.Dequeue();text.text += msg;}}byte[] desArray;public void OnData(float[] input){Debug.Log("input.Length:" + input.Length);SendData(input);}void SendData(float[] input){var desArraySize = Buffer.ByteLength(input);IntPtr srcArrayPtr = Marshal.UnsafeAddrOfPinnedArrayElement(input, 0);desArray = new byte[desArraySize];Marshal.Copy(srcArrayPtr, desArray, 0, desArraySize);if (ws != null && ws.ReadyState == WebSocketState.Open){ws.SendAsync(desArray);}}void OnOpen(object sender, OpenEventArgs e){Debug.Log("WS connected!");}void OnMessage(object sender, MessageEventArgs e){if (e.IsBinary){string str = Encoding.UTF8.GetString(e.RawData);Debug.Log("WS received message: " + str);msgs.Enqueue(str);}else if (e.IsText){}}void OnError(object sender, ErrorEventArgs e){Debug.Log("WS error: " + e.Message);}void OnClose(object sender, CloseEventArgs e){Debug.Log(string.Format("Closed: StatusCode: {0}, Reason: {1}", e.StatusCode, e.Reason));}private void OnApplicationQuit(){if (ws != null && ws.ReadyState != WebSocketState.Closed){ws.CloseAsync();}}
}

服务器端使用了Fleck

// See https://aka.ms/new-console-template for more information
using Fleck;
using System.Text;namespace uSherpaServer
{internal class Program{// 声明配置和识别器变量static SherpaNcnn.OnlineRecognizer recognizer;static SherpaNcnn.OnlineStream onlineStream;static string tokensPath = "tokens.txt";static string encoderParamPath = "encoder_jit_trace-pnnx.ncnn.param";static string encoderBinPath = "encoder_jit_trace-pnnx.ncnn.bin";static string decoderParamPath = "decoder_jit_trace-pnnx.ncnn.param";static string decoderBinPath = "decoder_jit_trace-pnnx.ncnn.bin";static string joinerParamPath = "joiner_jit_trace-pnnx.ncnn.param";static string joinerBinPath = "joiner_jit_trace-pnnx.ncnn.bin";static int numThreads = 1;static string decodingMethod = "greedy_search";static string modelPath;static float sampleRate = 16000;static IWebSocketConnection client;static void Main(string[] args){//需要将此文件夹拷贝到exe所在的目录modelPath = Environment.CurrentDirectory + "/sherpa-ncnn-streaming-zipformer-small-bilingual-zh-en-2023-02-16";// 初始化配置SherpaNcnn.OnlineRecognizerConfig config = new SherpaNcnn.OnlineRecognizerConfig{FeatConfig = { SampleRate = sampleRate, FeatureDim = 80 },ModelConfig = {Tokens = Path.Combine(modelPath,tokensPath),EncoderParam =  Path.Combine(modelPath,encoderParamPath),EncoderBin =Path.Combine(modelPath, encoderBinPath),DecoderParam =Path.Combine(modelPath, decoderParamPath),DecoderBin = Path.Combine(modelPath, decoderBinPath),JoinerParam = Path.Combine(modelPath,joinerParamPath),JoinerBin =Path.Combine(modelPath,joinerBinPath),UseVulkanCompute = 0,NumThreads = numThreads},DecoderConfig = {DecodingMethod = decodingMethod,NumActivePaths = 4},EnableEndpoint = 1,Rule1MinTrailingSilence = 2.4F,Rule2MinTrailingSilence = 1.2F,Rule3MinUtteranceLength = 20.0F};// 创建识别器和在线流recognizer = new SherpaNcnn.OnlineRecognizer(config);onlineStream = recognizer.CreateStream();StartWebServer();Update();Console.ReadLine();}static void StartWebServer(){//存储连接对象的池var connectSocketPool = new List<IWebSocketConnection>();//创建WebSocket服务端实例并监听本机的9999端口var server = new WebSocketServer("ws://127.0.0.1:9999");//开启监听server.Start(socket =>{//注册客户端连接建立事件socket.OnOpen = () =>{client = socket;Console.WriteLine("Open");//将当前客户端连接对象放入连接池中connectSocketPool.Add(socket);};//注册客户端连接关闭事件socket.OnClose = () =>{client = null;Console.WriteLine("Close");//将当前客户端连接对象从连接池中移除connectSocketPool.Remove(socket);};//注册客户端发送信息事件socket.OnBinary = message =>{float[] floatArray = new float[message.Length / 4];Buffer.BlockCopy(message, 0, floatArray, 0, message.Length);// 将采集到的音频数据传递给识别器onlineStream.AcceptWaveform(sampleRate, floatArray);};});}static string lastText = "";static void Update(){while (true){// 每帧更新识别器状态if (recognizer.IsReady(onlineStream)){recognizer.Decode(onlineStream);}var text = recognizer.GetResult(onlineStream).Text;bool isEndpoint = recognizer.IsEndpoint(onlineStream);if (!string.IsNullOrWhiteSpace(text) && lastText != text){if (string.IsNullOrWhiteSpace(lastText)){lastText = text;if (client != null){client.Send(Encoding.UTF8.GetBytes(text));//Console.WriteLine("text1:" + text);}}else{if (client != null){client.Send(Encoding.UTF8.GetBytes(text.Replace(lastText, "")));lastText = text;}}}if (isEndpoint){if (!string.IsNullOrWhiteSpace(text)){if (client != null){client.Send(Encoding.UTF8.GetBytes("。"));}// Console.WriteLine("text2:" + text);}recognizer.Reset(onlineStream);//Console.WriteLine("Reset");}Thread.Sleep(200); // ms}}}
}

2、Unity录音插件使用了uMicrophoneWebGL 绑定DataEvent事件实时获取话筒数据(float数组)

最后放上工程地址

客户端 uSherpa: fork from https://github.com/ssssssilver/sherpa-ncnn-unity.git改成 Unity WebGL版

服务器端 GitHub - xue-fei/uSherpaServer: uSherpaServer 给Unity提供流式语音识别的websocket服务

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

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

相关文章

汽车制造业安全事故频发,如何才能安全进行设计图纸文件外发?

汽车制造业产业链长&#xff0c;关联度高&#xff0c;汽车制造上游行业主要为钢铁、化工等行业&#xff0c;下游主要为个人消 费、基建、客运和军事等。在汽车制造的整个生命周期中&#xff0c;企业与上下游供应商、合作商之间有频繁、密切的数据交换&#xff0c;企业需要将设计…

在编程的世界里,我相信每一行代码都是一次对未来的投资

&#x1f600;前言 突然有感而发也是激励自己互勉 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 在编程的世界里&#xff0c;我相信每一行代码都是一次对未来的投资类似句子编程的本质代码的价值构建可持续的未来结语 在编程的世界里&#xff0c;我相信每一行代码都是一…

功能测试_分类_用例_方法

总结 测试分类 按阶段分类 是否查看源代码分类 是否运行分类 是否自动化 其他分类 软件质量模型 开发模型-瀑布模型 测试过程模型 v w 测试用例八大要素 用例编号 用例标题 …

【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 一、简单介绍Sizeof和Strlen1.1 Sizeof1.2 Strlen函数1.3 Sie…

聊聊 ASP.NET Core 中间件(一):一个简单的中间件例子

前言&#xff1a;什么是中间件 服务器在收到 HTTP 请求后会对用户的请求进行一系列的处理&#xff0c;比如检查请求的身份验证信息、处理请求报文头、检查是否存在对应的服务器端响应缓存、找到和请求对应的控制器类中的操作方法等&#xff0c;当控制器类中的操作方法执行完成…

MLP手写数字识别(3)-使用tf.data.Dataset模块制作模型输入(tensorflow)

1、tensorflow版本查看 import tensorflow as tfprint(Tensorflow Version:{}.format(tf.__version__)) print(tf.config.list_physical_devices())2、MNIST数据集下载与预处理 (train_images,train_labels),(test_images,test_labels) tf.keras.datasets.mnist.load_data()…

多线程事务怎么回滚

1、背景介绍 1&#xff0c;最近有一个大数据量插入的操作入库的业务场景&#xff0c;需要先做一些其他修改操作&#xff0c;然后在执行插入操作&#xff0c;由于插入数据可能会很多&#xff0c;用到多线程去拆分数据并行处理来提高响应时间&#xff0c;如果有一个线程执行失败…

深度学习500问——Chapter08:目标检测(7)

文章目录 8.3.8 RFBNet 8.3.9 M2Det 8.3.8 RFBNet RFBNet有哪些创新点 1. 提出RF block&#xff08;RFB&#xff09;模块 RFBNet主要想利用一些技巧使得轻量级模型在速度和精度上达到很好的trade-off的检测器。灵感来自人类视觉的感受野结构Receptive Fields&#xff08;RFs…

【Mac】mac 安装 prometheus 报错 prometheus: prometheus: cannot execute binary file

1、官网下载 Download | Prometheus 这里下载的是prometheus-2.51.2.linux-amd64.tar.gz 2、现象 解压之后启动Prometheus 启动脚本&#xff1a; nohup ./prometheus --config.fileprometheus.yml > prometheus.out 2>&1 & prometheus.out日志文件&#xff…

WIN10 anaconda 安装 CondaError: Run ‘conda init‘ before ‘conda activate‘

1 下载 https://www.anaconda.com/download/success 2 安装 3 修改环境变量 安装后修改环境变量 4 winrun 进入命令窗口 输入cmd 输入 conda info 5 创建 虚拟环境 conda create -n yolov8 python3.8 -y 6 CondaError: Run ‘conda init’ before ‘conda activate’ c…

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了&#xff0c;要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看&#xff0c;可以看我下面总结的干货&#xff0c;哈哈 第一个问题&#xff1a;stage架构和fa架构的区…

SpringBoot+阿里云实现验证码登录注册及重置密码

开通阿里云短信服务 阿里云官网 创建API的Key 可以使用手机号或者刷脸来进行创建Key 创建成功 开通完成以后接下来实现代码请求阶段 配置maven依赖 <!-- 阿里云 oss 短信 依赖--><dependency><groupId>com.aliyun</groupId><artifactId>dysm…

力扣763. 划分字母区间

Problem: 763. 划分字母区间 文章目录 题目描述思路复杂度Code 题目描述 思路 1.创建一个名为 last 的数组&#xff0c;用于存储每个字母在字符串 s 中最后出现的位置。然后&#xff0c;获取字符串 s 的长度 len。 2.计算每个字母的最后位置&#xff1a;遍历字符串 s&#xff0…

Python梯度提升决策树库之lightgbm使用详解

概要 LightGBM是一个快速、分布式、高性能的梯度提升决策树(Gradient Boosting Decision Tree)库,它在机器学习和数据挖掘领域被广泛应用。本文将介绍LightGBM库的安装方法、主要特性、基本功能、高级功能、以及在实际应用中的场景和总结。 安装 首先,需要安装LightGBM库…

ORACLE 性能优化 高水位调节

当我需要去做优化时,有一个固定的优化思路:SQL优化->索引优化->分区优化->优化器hints优化 SQL 语句优化 1. 选用适合的 ORACLE 优化器 ORACLE 的优化器共有 3 种 : a. RULE ( 基于规则 ) b. COST ( 基于成本 ) c. CHOOSE ( 选 择性) 设置缺省的优化器, 可以通…

基于RK1126的小型化低功耗AI相机,支持人体特征识别、人脸特征识别、案例帽识别等

提供可定制的⼀套 AI相机软硬件开发平台&#xff0c; 硬件采⽤ RockchipRV1126处理器解决 ⽅案&#xff0c;可选择搭配 SonyIMX系列传感器&#xff0c;POE供电与数据传输&#xff0c;采⽤ 38板标准结构设计&#xff0c;快速按需定制外壳&#xff0c;⽀撑从开发到验证到批量⽣产…

【webrtc】MessageHandler 6: 基于线程的消息处理:StunRequest实现包发送和超时重传

G:\CDN\rtcCli\m98\src\p2p\base\stun_request.cc使用OnMessage 实现包的发送和包的超时重传StunRequest 一个StunRequest 代表是一个独立的请求的发送STUN消息 要不是发送前构造好的,要不就是按照需要构建的使用StunRequestManager: 每一个STUNRequest 携带一个交互id 写入m…

【区块链】共识算法简介

共识算法简介 区块链三要素&#xff1a; 去中心化共识算法智能合约 共识算法作为区块链三大核心技术之一&#xff0c;其重要性不言而喻。今天就来简单介绍共识算法的基本知识。 最简单的解释&#xff0c;共识算法就是要让所有节点达成共识&#xff0c;保证少数服从多数&#x…

【docker】maven 打包docker的插件学习

docker-maven-plugin GitHub地址&#xff1a;https://github.com/spotify/docker-maven-plugin 您可以使用此插件创建一个 Docker 映像&#xff0c;其中包含从 Maven 项目构建的工件。例如&#xff0c;Java 服务的构建过程可以输出运行该服务的 Docker 映像。 该插件是 Spot…

【JAVA进阶篇教学】第九篇:MyBatis-Plus用法介绍

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第九篇&#xff1a;MyBatis-Plus用法介绍。 在 MyBatis-Plus 3.5.0 中&#xff0c;LambdaQueryWrapper支持多种条件构造方式&#xff0c;除了等于&#xff08;eq&#xff09;、不等于&#xff08;ne&#xff09;、大于&a…