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 =  "点击麦克风,开始录音!" ;
}


进入页面:

wKioL1MV5_zT5fsBAAi_Ila2WRE976.jpg


正在录音:

wKiom1MV6CXzTifFAAiwJsgx_8k251.jpg


识别结果,目前还为将拼音转换为汉字,下图为“点亮星光”的显示结果图:

wKioL1MV6APT2sxZAAjIrySOhP0350.jpg










本文转自 ponpon_ 51CTO博客,原文链接:http://blog.51cto.com/liuxp0827/1367846,如需转载请自行联系原作者
相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
目录
相关文章
|
Web App开发 安全 iOS开发
基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战
《基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战》详细解析了如何在macOS下通过Python脚本自动化清理Chrome浏览器的历史记录。文章以`clear_chrome_history.py`为例,结合PyCharm开发环境,深入讲解技术实现。内容涵盖进程检测、文件清理、虚拟环境配置及断点调试技巧,并提供安全增强与跨平台适配建议。该工具不仅保障个人隐私,还适用于自动化运维场景,具备较高实用价值。
483 0
|
Web App开发 数据采集 存储
WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率
本文探讨了如何利用Chrome DevTools Protocol (CDP) 与 Selenium WebDriver 提升浏览器自动化效率,结合代理IP技术高效采集微博数据。通过CDP,开发者可直接操作浏览器底层功能,如网络拦截、性能分析等,增强控制精度。示例代码展示了如何设置代理IP、cookie及user-agent来模拟真实用户行为,提高数据抓取成功率与稳定性。适用于需要频繁抓取互联网数据的应用场景。
1732 3
WebDriver与Chrome DevTools Protocol:如何在浏览器自动化中提升效率
|
Web App开发 JSON 安全
Chrome浏览器的跨域问题
【10月更文挑战第6天】
2851 123
|
Web App开发 存储 前端开发
Chrome浏览器的跨域问题
Chrome浏览器的跨域问题
1237 128
|
Web App开发 人工智能 JSON
AutoMouser:AI Chrome扩展程序,实时跟踪用户的浏览器操作,自动生成自动化操作脚本
AutoMouser是一款Chrome扩展程序,能够实时跟踪用户交互行为,并基于OpenAI的GPT模型自动生成Selenium测试代码,简化自动化测试流程。
1168 17
AutoMouser:AI Chrome扩展程序,实时跟踪用户的浏览器操作,自动生成自动化操作脚本
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
698 17
使用Web浏览器访问UE应用的最佳实践
|
人工智能 开发框架 自然语言处理
Eko:一句话就能快速构建复杂工作流的 AI 代理开发框架!快速实现自动操作电脑和浏览器完成任务
Eko 是 Fellou AI 推出的开源 AI 代理开发框架,支持自然语言驱动,帮助开发者快速构建从简单指令到复杂工作流的智能代理。
1865 12
Eko:一句话就能快速构建复杂工作流的 AI 代理开发框架!快速实现自动操作电脑和浏览器完成任务
|
人工智能 前端开发 计算机视觉
Inpaint-Web:纯浏览器端实现的开源图像处理工具
在刷短视频时,常看到情侣在景区拍照被路人“抢镜”,男朋友用手机将路人“P”掉,既贴心又有趣。最近我发现了一个纯前端实现的开源项目——inpaint-web,可在浏览器端删除照片中的部分内容,非常酷。该项目基于 WebGPU 和 WASM 技术,支持图像修复与放大,已在 GitHub 上获得 5.1k Star。项目地址:[GitHub](https://github.com/lxfater/inpaint-web)。
1131 3
 Inpaint-Web:纯浏览器端实现的开源图像处理工具
|
Web App开发 数据采集 JavaScript
Chrome浏览器实例的TypeScript自动化脚本
Chrome浏览器实例的TypeScript自动化脚本
|
存储 缓存 前端开发
Web端IM聊天消息该不该用浏览器本地存储?一文即懂!
鉴于目前浏览器技术的进步(主要是HTML5的普及),在Web网页端IM聊天应用的技术选型阶段,很多开发者都会纠结到底该不该像原生移动端IM那样将聊天记录缓存在浏览器的本地,还是像传统Web端即时通讯那样继续存储在服务端?本文将为你简洁明了地讲清楚浏览器本地存储技术(Web Storage),然后你就知道到底该怎么选择了。
547 1