首页 文章 精选 留言 我的

精选列表

搜索[chrome os],共10000篇文章
优秀的个人博客,低调大师

Golang 基于chrome浏览器语音识别web演示系统WebHTK开发之 引擎篇

要说引擎篇,也谈不上。底层语音识别的实现,是基于HTK开源语音识别工具:http://htk.eng.cam.ac.uk/#前面用过这个工具,也用JNI转成java可调用的接口,所以还算比较熟悉。这次引擎,也只是用cgo来转。HMM模型都是用HTK的工具训练好的,只要有数据,baidu,google上教程还是很多的,自带的HTKBOOK就是最权威的教程。 在实现阶段,主要就是用到三个工具:HCopy(提取特征),HVite(viterbi算法识别),HParse(制作语法词网)。看看都需要哪些文件: 这些文件中,只有上述三个HCopy.c,HVite.c,HParse.c还有main主函数,所以只要把三个main函数重命名下,传参仍不变,并修改下这三个文件中一些相同命名的函数(比方Usage这类的),再写个asr.h的头文件,把上述重命名的三个main函数加进去就ok了,asr.h: 1 2 3 4 5 #ifndef ASR_H int HCopy( int argc, char *argv[]); int HVite( int argc, char *argv[]); int HParse( int argc, char *argv[]); #endif 再看下HTKengine.go: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package HTKengine //#include "asr.h" //#include "string.h" //#include "stdlib.h" import "C" import "unsafe" type cmd struct { HCOPY string HVITE string HPARSE string } var Command *cmd = &cmd{ "HCopy" , "HVite" , "HParse" } func HCopy(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HCopy(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } func HVite(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HVite(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } func HParse(args []string) { arg := make([](*_Ctype_char), 0 ) l := len(args) for i, _ := range args { char := C.CString(args[i]) defer C.free(unsafe.Pointer( char )) strptr := (*_Ctype_char)(unsafe.Pointer( char )) arg = append(arg, strptr) } C.HParse(C. int (l), (**_Ctype_char)(unsafe.Pointer(&arg[ 0 ]))) } 原来的main都是要跟上args参数的,这里把他作为接口调用,所以还是需要传进args []string。在我前面的博客中,有提到cgo,可以参考下: golang在window环境下用cgo编译c语言 Golang cgo编程 [] string 转 C语言 char** 在前面录音篇,有大概讲到在服务器保存wav文件,HCopy就直接跟在wav保存的代码后,而HVite跟在HCopy后。现在时间不允许,否则,可以改下HCopy的代码,直接传byte[]数据。其实在pocketsphinx中就是这么实现的,有空也可以给pocketsphinx写几个cgo的接口来调用。 关于这个系列的博客,应该不会再写什么了,web到这,功能已经完成80%,后面也就是添加些,动态添加待识别语句到数据库的功能,说白了,就是你想识别哪些语句,你可以自己定义,提交给服务器,通过HParse重新制作词网来搞定的。也没有什么跟web开发有很大关系的,顶多是涉及到数据库,不过目前我对数据库了解不多,也只用到简单的CRUD操作,所以嘛,就不多写了。 上周接到网易游戏的面试电话,木有任何准备,被虐的狗一样啊。所以近阶段的博客,应该会写些java,golang数据结构方面的吧。 本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1374334,如需转载请自行联系原作者

优秀的个人博客,低调大师

Golang 基于chrome浏览器语音识别web演示系统WebHTK开发之 UI篇

没啥好说的,直接上现阶段的HTML代码,后续修改,再更新该篇博客。 record.html: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 <!DOCTYPE html> <html> <head> <meta charset= "utf-8" /> <meta http-equiv= "X-UA-Compatible" content= "IE=edge" /> <meta name= "viewport" content= "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name= "keywords" content= "PONPON,HTK,Go语言" /> <meta name= "description" content= "基于Beego开发语音识别演示系统" /> <meta name= "generator" content= "PONPON" /> <link href= "/static/css/bootstrap.min.css" rel= "stylesheet" > <link href= "/static/css/docs.css" rel= "stylesheet" > <link href= "http://cdn.bootcss.com/highlight.js/7.3/styles/github.min.css" rel= "stylesheet" > <link rel= "shortcut icon" href= "/static/img/Logoicon.jpg" > <link rel= "stylesheet" href= "http://libs.baidu.com/fontawesome/4.0.3/css/font-awesome.min.css" /> <link rel= "alternate" type= "application/rss+xml" href= "/rss.xml" /> <script type= "text/javascript" src= "/static/lib/recorder.js" > </script> <script type= "text/javascript" src= "/static/lib/jquery-1.10.1.min.js" > </script> <script type= "text/javascript" src= "/static/lib/recController.js" > </script> <title>WebHTK 演示系统</title> </head> <body> <nav id= "header" > <div class= "container960 text-center" > <h3 id= "header-h" class= "center" >闽南语 - 语音识别演示系统</h3> <ul id= "resultbox" class= "center" style= "padding-top:425px;font-size:20px;text-align: center;color:#FFC8B6;font-family:'微软雅黑'" > <li >识别结果</li> </ul> <form style= "padding-top:20px;" > <a id= "img" href= "javascript://" > <img src= "/static/img/aa.png" style= "width:85px;height:85px;" alt= "" /> </a> </form> <div id= "message" style= "padding-top:10px;font-size:16px;color:#F5FFFA;text-align: center;font-family:'微软雅黑'" >点击麦克风,开始录音!</div> <script type= "text/javascript" > var recording = false ; function test() { if (!recording) { document.getElementById( "img" ).innerHTML= "<img src='/static/img/a1.png' style='width:85px;height:85px;'' alt=''/>" ; toRecord(); recording= true ; } else { document.getElementById( "img" ).innerHTML= "<img src='/static/img/aa.png' style='width:85px;height:85px;'' alt=''/>" ; toSend(); recording = false ; } }; function toRecord(){ rec.record(); var dd = ws.send( "start" ); $( "#message" ).text( "再次点击,结束录音!" ); intervalKey = setInterval( function () { rec.exportWAV( function (blob) { rec.clear(); ws.send(blob); }); }, 300); } function toSend(){ rec.stop(); if (intervalKey == null ) { $( "#message" ).text( "请先录音再发送!" ); return }; ws.send(sampleRate); ws.send(channels); ws.send( "stop" ); rec.clear(); clearInterval(intervalKey); intervalKey = null ; } </script> </div> </nav> <audio class= "hide" controls autoplay></audio> </body> </html> recorder.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 ( function (window) { var WORKER_PATH = '/static/lib/recorderWorker.js' ; var Recorder = function (source, chan, cfg) { var config = cfg || {}; var channels = chan || 1; var bufferLen = config.bufferLen || 8192; this .context = source.context; this .node = this .context.createJavaScriptNode(bufferLen, channels, channels); var worker = new Worker(config.workerPath || WORKER_PATH); worker.postMessage({ command: 'init' , config: { sampleRate: this .context.sampleRate } }); var recording = false , currCallback; this .node.onaudioprocess = function (e) { if (!recording) return ; worker.postMessage({ command: 'record' , buffer: [ e.inputBuffer.getChannelData(0) ] }); } this .configure = function (cfg) { for ( var prop in cfg) { if (cfg.hasOwnProperty(prop)) { config[prop] = cfg[prop]; } } } this .record = function () { recording = true ; } this .stop = function () { recording = false ; } this .clear = function () { worker.postMessage({ command: 'clear' }); } this .getBuffer = function (cb) { currCallback = cb || config.callback; worker.postMessage({ command: 'getBuffer' }) } this .exportWAV = function (cb, type) { currCallback = cb || config.callback; type = type || config.type || 'audio/wav' ; if (!currCallback) throw new Error( 'Callback not set' ); worker.postMessage({ command: 'exportWAV' , type: type }); } worker.onmessage = function (e) { var blob = e.data; currCallback(blob); } source.connect( this .node); this .node.connect( this .context.destination); }; window.Recorder = Recorder; })(window); recorderWorker.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 var recLength = 0, recBuffersL = [], sampleRate; this .onmessage = function (e) { switch (e.data.command) { case 'init' : init(e.data.config); break ; case 'record' : record(e.data.buffer); break ; case 'exportWAV' : exportWAV(e.data.type); break ; case 'getBuffer' : getBuffer(); break ; case 'clear' : clear(); break ; } }; function init(config) { sampleRate = config.sampleRate; } function record(inputBuffer) { recBuffersL.push(inputBuffer[0]); recLength += inputBuffer[0].length; } function exportWAV(type) { var bufferL = mergeBuffers(recBuffersL, recLength); var interleaved = interleave(bufferL); var dataview = encodeWAV(interleaved); var audioBlob = new Blob([dataview], { type: type }); this .postMessage(audioBlob); } function getBuffer() { var buffers = []; buffers.push(mergeBuffers(recBuffersL, recLength)); this .postMessage(buffers); } function clear(inputBuffer) { recLength = 0; recBuffersL = []; } function mergeBuffers(recBuffers, recLength) { var result = new Float32Array(recLength); var offset = 0; for ( var i = 0; i < recBuffers.length; i++) { result.set(recBuffers[i], offset); offset += recBuffers[i].length; } return result; } function interleave(inputL) { var length; var result; var index = 0, inputIndex = 0; if (sampleRate == 48000) { length = inputL.length / 6; result = new Float32Array(length); while (index < length) { result[index++] = (inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 6; } } else if (sampleRate == 44100) { length = inputL.length / 6; result = new Float32Array(length); while (index < length) { if (inputIndex % 12 == 0) { result[index++] = (inputL[inputIndex] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 7; } else { result[index++] = (inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++] + inputL[inputIndex++]) / 6; }; } } else { length = inputL.length; result = new Float32Array(length); while (index < length) { result[index++] = inputL[inputIndex++]; } }; return result; } function floatTo16BitPCM(output, offset, input) { for ( var i = 0; i < input.length; i++, offset += 2) { var s = Math.max(-1, Math.min(1, input[i])); output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true ); } } function writeString(view, offset, string) { for ( var i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } } function encodeWAV(samples) { var buffer = new ArrayBuffer(samples.length * 2); var view = new DataView(buffer); floatTo16BitPCM(view, 0, samples); return view; } recController.js: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 var onFail = function (e) { console.log( 'Rejected!' , e); }; var onSuccess = function (s) { var context = new webkitAudioContext(); var mediaStreamSource = context.createMediaStreamSource(s); rec = new Recorder(mediaStreamSource, channels); sampleRate = 8000; } navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; var rec; var intervalKey = null ; var audio = document.querySelector( '#audio' ); var sampleRate; var channels = 1; function startRecording() { if (navigator.getUserMedia) { navigator.getUserMedia({ audio: true }, onSuccess, onFail); } else { console.log( 'navigator.getUserMedia not present' ); } } startRecording(); //-------------------- var ws = new WebSocket( 'ws://' + window.location.host + '/join' ); ws.onopen = function () { console.log( "Openened connection to websocket" ); }; ws.onclose = function () { console.log( "Close connection to websocket" ); } ws.onerror = function () { console.log( "Cannot connection to websocket" ); } ws.onmessage = function (result) { var data = JSON.parse(result.data); console.log( '识别结果:' + data.Pinyin); var result = document.getElementById( "resultbox" ) result.getElementsByTagName( "li" )[0].innerHTML = data.Hanzi; document.getElementById( "message" ).innerHTML = "点击麦克风,开始录音!" ; } 进入页面: 正在录音: 识别结果,目前还为将拼音转换为汉字,下图为“点亮星光”的显示结果图: 本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1367846,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册