# WebASR **Repository Path**: xiaoyangge_admin/WebASR ## Basic Information - **Project Name**: WebASR - **Description**: 网页版的语音识别项目 - **Primary Language**: JavaScript - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 46 - **Created**: 2020-12-23 - **Last Updated**: 2020-12-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WebASR 网页版且离线的语音识别项目 * v0.1.0版完成!工程方面的基础功能全部实现,接下来就是研究模型了~ * 查看DEMO:https://haskely.github.io/WebASR * (国内访问 https://haskely.gitee.io/webasr ) ![WebASR网页截图](https://gitee.com/Haskely/WebASR/raw/master/screenshot/WebASR.png) [TOC] ## Introduction - 介绍 * 基于TensorFlowJS和WebAudioAPI的网页版的中文语音识别玩具项目。 * 纯手打Javascript + html,没有css,没有nodejs,没有前端框架,感受原始气息。 * 零服务器需要:波形绘图,短时傅里叶频谱计算,模型识别工作等完全在本地进行! * 支持实时录音或上传音频。 * 代码的可扩展性应该不错。 ## Usage - 用法 * 用 **最新版Chrome内核** 的浏览器(否则无法正常使用)打开 https://haskely.github.io/WebASR (或者国内访问 https://haskely.gitee.io/webasr ) * 网页上的按钮都点一点,就会了。 ## Installation - 自己部署 * 直接把项目所有文件放到任意可访问的路径上即可,一个静态网页而已。 * (保持项目中文件相对路径不变) * (因为浏览器的安全措施,需要基于http服务打开index.html,不能直接本地打开。参考run_server.bat 中的命令) ## Develop - 开发 ### 一、简单开发 #### 主要参数配置 - 打开本项目根目录下**main.js**文件,找到`//基础配置`注释处,参考相关注释配置参数。 ``` //基础配置 const numberOfChannels = 1, bufferSize = 256, total_duration = 10; const sampleRate = 8000, fft_s = 0.032, hop_s = 0.008; const ModelDir = './ASR/Model/Network/tensorflowjs/tfjsModel/tfjs_mobilev3small_thchs30/'; const minPinYinN = 10; const useWebWorker = true; ... //配置完毕 ``` > * numberOfChannels 音频声道数。整数,默认为1。支持的值最多为32。 > > * bufferSize 以采样帧为单位的缓冲区大小。必须是以下值之一:0、256、512、1024、2048、4096、8192、16384。为0时系统自动选择。这时你的刷新帧率就是sampleRate/bufferSize。 > > * total_duration 网页中各种音频绘制的时间总长度。 > > --- > > * sampleRate 音频采样率 可取 8000、16000、32000、48000 之一 > > * fft_s 一个短时傅里叶变换的窗长,单位为秒 > > * hop_s 短时傅里叶变换窗之间间隔长,单位为秒 > > 注意:以上三个参数应该与下面ModelDir文件夹下feature.json中的参数一致,否则模型将加载失败。 > > --- > > * ModelDir TensorflowJS 模型文件夹,该文件夹下应该存在一个model.json,一个feature.json,若干个.bin文件。 > > * minPinYinN 正整数,流式模型推断音频最小的长度;如果为4,则一次推断输出4个拼音片段,并保留中间两个;下一次推断与这次推断的覆盖长度为4/2 = 2 。 > > * useWebWorker 是否使用异步进行模型推断:若为false,则模型推断与音频刷新同步进行,大概率导致音频卡顿,但是保证实时率;若为true,则推断异步进行,不会阻塞音频流逝,但推断输出一般会有积压延迟(一开始会很严重,初始积压接近8秒,但后面就很快跟上了,最终稳定到时延0.5-2秒)。 #### 模型部署 - 使用 **DeepASR** 项目(暂未开源)中的Model实例的convert2tfjs方法会自动生成**TensorflowJS Graph Model**格式的模型。这是一个文件夹,其目录结构一般为: ``` TFJSModelDir │ feature.json │ group1-shard1of4.bin │ group1-shard2of4.bin │ group1-shard3of4.bin │ group1-shard4of4.bin │ model.json ``` - 将该文件夹中文件复制到本项目任意子文件夹下,并将该子文件夹相对路径复制到**main.js**中`//基础配置`注释处的**ModelDir**变量中即可。 > 例如我把**TensorflowJS Graph Model**格式的模型文件夹"TFJSModel"复制到了/WebASR/Models/TFJSModel,其中WebASR是本项目根目录。 > > 则将`const ModelDir = 'xxx'` 修改为 > > ``` > //基础配置 > ... > const ModelDir = './Models/TFJSModel/'; > ... > ``` > > 即可。 > > 其实直接研究TensorflowJS model的输入输出格式以及本项目源代码,以及TensorflowJS官网的文档,可以自己生成需要的tfjs 模型进行替换。 ### 二、深入API 通过阅读 **main.js** 可知,里面除了处理html页面元素的代码外,其他的就是调用了 “**AudioFlow**” 类实例的api。 而“**AudioFlow**” 类的父类是“**AudioProcesser**”类。按顺序介绍: #### AudioProcesser 这个类的作用是,从一个或多个音频输入源获取原始的音频波形数据数组进行任意代码处理。它就是对[WebAudioAPI](https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Audio_API)的一层封装,更准确的是,对其[`ScriptProcessorNode`](https://developer.mozilla.org/zh-CN/docs/Web/API/ScriptProcessorNode)的一层封装。 - 通过构造函数**constructor**构造AudioProcesser的实例时就指定好处理音频数据的代码。 - 通过AudioProcesser实例的**open**、**start**、**stop**、**close**方法控制数据处理流程的初始化、开始、暂停、停止并释放内存。 - 通过**addAudioSource**、**delAudioSource**实现动态加载音频源和删除音频源。 以上这些方法的用法和作用在代码中均有详细注释。 样例: ```javascript import { AudioFlowProcesser } from "../../Audio/AudioFlowProcesser.js"; const audioFlowProcesser = new AudioFlowProcesser( null, // audioSource = null, 暂不指定音频源。 'sound', //audioDestination = 'sound', 音频会输出到扬声器 8000, //sampleRate = 8000, 指定采样率为8000 undefined, //latencyHint = undefined, 不指定latencyHint,让系统自动选择 256, //ScriptNode_bufferSize = 256, 缓冲区大小为256(采样帧),结合上面指定采样率为8000,得到音频刷新帧率为8000/256 = 31.25 FPS。 1, //ScriptNode_numberOfInputChannels = 1, 声道数为1。 processAudioData = (audioData) => { const audioClipInfo = { "音频采样率":audioData.sampleRate , "音频数据":audioData.channels , "音频末尾时间戳":audioData.audioEndTime , "音频声道数":audioData.numberOfChannels , "音频帧数":audioData.sampleLength , "音频时长":audioData.timeLength , "音频开头时间戳":audioData.audioStartTime }; console.log(`收到音频小片段:${audioClipInfo}`); }, ); async function addMicrophone(){ const recordStream = await navigator.mediaDevices.getUserMedia( {audio: true}); //开启麦克风 audioFlowProcesser.addAudioSource(recordStream); //audioFlowProcesser加入麦克风音频源 }; audioFlowProcesser.open(); audioFlowProcesser.start(); addMicrophone(); ``` #### AudioFlow **AudioFlow**是对AudioProcesser类的进一步封装,是在AudioProcesser类的基础上又添加了很多实用功能。比如绘制流式音频波形图、流式计算短时傅里叶变换频谱并画图、调用语音识别模型进行推断等。 其内部逻辑是事件驱动的。每当AudioProcesser中processAudioData函数获取到了一段audioData小片段便触发相应事件,开始执行后续处理流程,比如执行波形绘制并拼接,更新整个波形图;如果开启了频谱计算,则每计算出一段频谱则触发对应的事件,可自定义后续处理流程。 - openAudio 开始收取音频 - keepAudio 保留收取到的最近一段时间的音频 - openWaveDraw 开始绘制音频波形图 - openStft 开始计算短时傅里叶音频频谱 - keepStft 保留一段时间的音频频谱 - openStftDraw 开始绘制音频频谱图 - openASR 开始语音识别 - keepASR 保留一段时长的语音识别推断结果 - openASRDraw 绘制语音识别结果 - openVoiceWakeUp (开发中)开启语音唤醒功能 以上API用法参考代码注释。 样例:样例就是 main.js , 这个项目就是直接基于AudioFlow的框架做的。