当前位置:   article > 正文

基于FlashWavRecorder实现IE11浏览器录音后用科大讯飞转文字_ie 浏览器 插件 录音

ie 浏览器 插件 录音

       终于折腾好了(使用FlashWavRecorder实现IE11浏览器录音后用科大讯飞转文字,我的是Vue.js项目),对一个前端仔来说,听到要兼容IE,都是不情愿的,但是需求来了,那就折腾起来吧。(主要这需求砍不了,菜刀没带)。但是经过这几天折腾,记录一下,不足之处,还望指教~

       首先呢,明确下我们的目标,支持IE11浏览器录音后转文字。我们用逆向思维思考下,音频转文字。我们目前用的是科大讯飞的SDK。前端的话,把我们拿到的音频数据,包装好,调用一下后端给的接口,然后后端调讯飞SDK,转化为文字,发回来给我们。所以我们最主要是拿到音频数据,即录音。那我们难点是IE11上录音,因为IE 不支持 navigator.mediaDevices.getUserMedia这样的API。这里用JS调用flash去实现IE上录音。(应该还可以调用ActiveX,没尝试)。

       这里在github找到两个可以运行起来的demo。传送门:recorder.js,FlashWavRecorder 

       这两个提供的example 都可以正常跑起来。recorder.js音质比较好,第二个杂音大点。但recorder.js不知道怎么取到录音后的音频数据,照理说,上传都可以实现了,拿到音频数据,理应可以。或许是我的能力问题,还请指点。FlashWavRecorder 有getBase64的方法,所以就选用FlashWavRecorder 了。

     

      调用别人的SDK,就要符合别人的游戏规则。如下摘自科大讯飞接入规则

1. 接口说明

  1. 授权认证,调用接口需要将 Appid,CurTime, Param 和 CheckSum 信息放在 HTTP 请求头中;
  2. 接口统一为 UTF-8 编码;
  3. 接口支持 http 和 https;
  4. 请求方式为POST。

2. 授权认证

在调用所有业务接口时,都需要在 Http Request Header 中配置以下参数用于授权认证:

参数格式说明必须
X-Appidstring讯飞开放平台注册申请应用的应用ID(appid)
X-CurTimestring当前UTC时间戳,从1970年1月1日0点0 分0 秒开始到现在的秒数
X-Paramstring相关参数JSON串经Base64编码后的字符串,见各接口详细说明
X-CheckSumstring令牌,计算方法:MD5(apiKey + curTime + param),三个值拼接的字符串,进行MD5哈希计算(32位小写),其中apiKey由讯飞提供,调用方管理。

     讯飞demo中有这个字段 文档没写 

bodystringdataUrl 

注:

  • apiKey:接口密钥,由讯飞开放平台提供,调用方注意保管,如泄露,可联系讯飞技术人员重置;
  • checkSum 有效期:出于安全性考虑,每个 checkSum 的有效期为 5 分钟(用 curTime 计算),同时 curTime 要与标准时间同步,否则,时间相差太大,服务端会直接认为 curTime 无效;
  • BASE64 编码采用 MIME 格式,字符包括大小写字母各26个,加上10个数字,和加号 + ,斜杠 / ,一共64个字符。

checkSum 生成示例:

  1. String apiKey="abcd1234";
  2. String curTime="1502607694";
  3. String param="eyAiYXVmIjogImF1ZGlvL0wxNjtyYXR...";
  4. String checkSum=MD5(apiKey+curTime+param);
Copy

3. 白名单

在调用所有业务接口时,授权认证通过后,服务端会检查调用方ip是否在讯飞开放平台配置的ip白名单中,对于没有配置到白名单中的IP发来的请求,服务端会拒绝服务。 注:

  • IP白名单可在控制台应用管理卡片上编辑,五分钟左右生效;
  • IP白名单最多可设置5个,更多的需求可通过工单联系技术人员;
  • 如果服务器返回结果如下所示,则表示由于未配置IP白名单,服务端拒绝服务:
  1. {
  2. "code":"10105",
  3. "desc":"illegal access|illegal client_ip",
  4. "data":"",
  5. "sid":"xxxxxx"
  6. }

我们请求后端接口类似这样:

  1. that.$http.postObj('restful/voice/recognition', {
  2. 'body': sendurl,
  3. 'X-Appid': that.appid,
  4. 'X-CurTime': time,
  5. 'X-Param': xParam,
  6. 'X-CheckSum': xChecksum
  7. }).then((res) => {
  8. //成功识别语音后,在这里拿到文字 eg:res.data.data
  9. console.log(res)
  10. }
  11. }).catch((err) => {
  12. console.log(err)
  13. });
  1. //basic.js
  2. $(function () {
  3. //这里的$(function () {}) 原生写法是function DOMContentLoaded(){};
  4. //document.addEventListener('DOMContentLoaded', DOMContentLoaded, false);
  5. var RECORDER_APP_ID = "recorderApp";
  6. var $level = $('.level .progress');
  7. var appWidth = 24;
  8. var appHeight = 24;
  9. var flashvars = {'upload_image': '../images/upload.png'};
  10. var params = {};
  11. var attributes = {'id': RECORDER_APP_ID, 'name': RECORDER_APP_ID};
  12. swfobject.embedSWF("../recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes);
  13. //注意这句,要确保swfobject.js 已经加载好了 要准备个容器不然报错 <div id="flashcontent" />
  14. //这里使用 document.getElementById(RECORDER_APP_ID).style.top='-3333px'
  15. // 因为把swf对象设置为display:none 或者visibility:hidden 都是使用不了
  16. window.fwr_event_handler = function fwr_event_handler() {//flash插件相关状态反馈
  17. var name, $controls;
  18. switch (arguments[0]) {
  19. case "ready":
  20. FWRecorder.uploadFormId = "#uploadForm";
  21. FWRecorder.uploadFieldName = "upload_file[filename]";
  22. FWRecorder.connect(RECORDER_APP_ID, 0);//如果老是报 recoder is null 这里没有调进来
  23. FWRecorder.recorderOriginalWidth = appWidth;
  24. FWRecorder.recorderOriginalHeight = appHeight;
  25. break;
  26. case "permission_panel_closed":
  27. FWRecorder.recorderOriginalWidth = 0;
  28. FWRecorder.recorderOriginalHeight = 0;
  29. document.getElementById(RECORDER_APP_ID).style.top='-3333px'//隐藏白白一块
  30. FWRecorder.defaultSize();
  31. break;
  32. case "microphone_user_request":
  33. FWRecorder.showPermissionWindow();//这里请求后 会弹出 是否 允许 使用麦克风的请求
  34. break;
  35. ....这里省略局部代码
  36. case "microphone_level"://这里用于显示声波。如果成功接入麦克风,录音的时候会一直调用
  37. $level.css({height: arguments[1] * 100 + '%'});
  38. break;
  39. ....这里省略局部代码
  40. };
  41. .......这里省略局部代码
  42. });

          以上主要是理解swfobject.embedSWF的用法。这里有详细的传送门: swfobject.js使用

  1. //recoder.js
  2. (function(global) {
  3. var Recorder;
  4. var RECORDED_AUDIO_TYPE = "audio/wav";
  5. Recorder = {
  6. recorder: null,
  7. recorderOriginalWidth: 0,
  8. recorderOriginalHeight: 0,
  9. uploadFormId: null,
  10. uploadFieldName: null,
  11. isReady: false,
  12. connect: function(name, attempts) {//连接麦克风 主要是init recorder
  13. if(navigator.appName.indexOf("Microsoft") != -1) {
  14. Recorder.recorder = window[name];
  15. } else {
  16. Recorder.recorder = document[name];//swfObject对象 ,这里的 name='recorderApp'
  17. }
  18. if(attempts >= 40) {
  19. return;
  20. }
  21. // flash app needs time to load and initialize
  22. if(Recorder.recorder && Recorder.recorder.init) {
  23. Recorder.recorderOriginalWidth = Recorder.recorder.width;
  24. Recorder.recorderOriginalHeight = Recorder.recorder.height;
  25. if(Recorder.uploadFormId && $) {
  26. var frm = $(Recorder.uploadFormId);
  27. Recorder.recorder.init(frm.attr('action').toString(), Recorder.uploadFieldName, frm.serializeArray());
  28. }
  29. return;
  30. }
  31. setTimeout(function() {Recorder.connect(name, attempts+1);}, 100);
  32. },
  33. playBack: function(name) {//播放
  34. // TODO: Rename to `playback`
  35. Recorder.recorder.playBack(name);
  36. },
  37. stopRecording: function() {//停止录音
  38. Recorder.recorder.stopRecording();
  39. },
  40. resize: function(width, height) {//设置 麦克风权限请求框大小
  41. Recorder.recorder.width = width + "px";
  42. Recorder.recorder.height = height + "px";
  43. },
  44. defaultSize: function() {
  45. Recorder.resize(Recorder.recorderOriginalWidth, Recorder.recorderOriginalHeight);
  46. },
  47. show: function() {
  48. Recorder.recorder.show();
  49. },
  50. hide: function() {
  51. Recorder.recorder.hide();
  52. },
  53. getBase64: function(name) {//来获取base64数据 如果需要转回来 window.atob("base64")
  54. var data = Recorder.recorder.getBase64(name);
  55. return 'data:' + RECORDED_AUDIO_TYPE + ';base64,' + data;
  56. },
  57. getBlob: function(name) {//这里转化为blod 后面讯飞转文字的时候要用到。当然可以自己转
  58. var base64Data = Recorder.getBase64(name).split(',')[1];
  59. return base64toBlob(base64Data, RECORDED_AUDIO_TYPE);
  60. },
  61. showPermissionWindow: function(options) {
  62. Recorder.resize(240, 160);
  63. // need to wait until app is resized before displaying permissions screen
  64. var permissionCommand = function() {
  65. if (options && options.permanent) {
  66. Recorder.recorder.permitPermanently();
  67. } else {
  68. Recorder.recorder.permit();
  69. }
  70. };
  71. setTimeout(permissionCommand, 1);
  72. },
  73. };
  74. function base64toBlob(b64Data, contentType, sliceSize) {
  75. contentType = contentType || '';
  76. sliceSize = sliceSize || 512;
  77. var byteCharacters = atob(b64Data);
  78. var byteArrays = [];
  79. for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
  80. var slice = byteCharacters.slice(offset, offset + sliceSize);
  81. var byteNumbers = new Array(slice.length);
  82. for (var i = 0; i < slice.length; i++) {
  83. byteNumbers[i] = slice.charCodeAt(i);
  84. }
  85. var byteArray = new Uint8Array(byteNumbers);
  86. byteArrays.push(byteArray);
  87. }
  88. return new Blob(byteArrays, {type: contentType});
  89. }
  90. global.FWRecorder = Recorder;
  91. })(this);

然后写几个button 接入就好了。      大家可以动手试一试。

注意:如果是在vue.js中当成模块的时候,ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";

不能使用arguments.callee;不能使用arguments.caller;禁止this指向全局对象;不能使用fn.caller和fn.arguments获取函数调用的堆栈 等等   所以引入swfobject.js 的时候 要把 arguments.callee 替换掉。 传送门:严格模式下arguments.callee代替思路

  1. 例如有用arguments.callee的函数里,
  2. function (){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);
  3. 把匿名函数 改为具名函数 ? swfobject.js 里面好像有7处需要改
  4. function fn(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(fn,0);

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/140057
推荐阅读
相关标签
  

闽ICP备14008679号