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,如需转载请自行联系原作者
相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
目录
相关文章
|
30天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
90 3
|
12天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
94 44
|
5天前
|
Web App开发 缓存 安全
WIN11 Chrome 双击打不开闪退及Chrome浏览器不能拖拽文件crx
【11月更文挑战第6天】本文介绍了 WIN11 系统中 Chrome 浏览器双击打不开闪退及不能拖拽文件 crx 的原因和解决方法。包括浏览器版本过旧、扩展程序冲突、硬件加速问题、缓存过多、安全软件冲突、系统文件损坏、用户配置文件损坏等问题的解决方案,以及 crx 文件的屏蔽、权限问题和文件格式问题的处理方法。
|
7天前
|
Web App开发 Linux iOS开发
Chrome浏览器如何导出所有书签并导入书签
【11月更文挑战第4天】本文介绍了如何在 Chrome 浏览器中导出和导入书签。导出时,打开书签管理器,点击“整理”按钮选择“导出书签”,保存为 HTML 文件。导入时,同样打开书签管理器,点击“整理”按钮选择“导入书签”,选择之前导出的 HTML 文件即可。其他主流浏览器也支持导入这种格式的书签文件。
|
14天前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
96 9
|
8天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
21 1
|
10天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
13天前
|
前端开发 JavaScript
Bootstrap Web 前端 UI 框架
Bootstrap 是快速开发 Web 应用程序的前端工具包。
29 3
|
13天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
27 2
|
1月前
|
Web App开发 开发者