js实现录音上传功能


Posted in Javascript onNovember 22, 2019

本文实例为大家分享了js代码实现录音上传,供大家参考,具体内容如下

1.html页面
2.Recorder.js内容
3.flask写法

1.html页面

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title id="title"></title>

</head>
<body>
<audio id="player" autoplay controls></audio>
<p>
 <button onclick="start_reco()">开始录音</button>
</p>
<p>
 <button onclick="ai_reco()" style="background-color: cornflowerblue">发送语音指令</button>
</p>
</body>
<script type="application/javascript" src="/static/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/static/Recorder.js"></script>
<script type="application/javascript">
 var reco = null;
 var audio_context = new AudioContext();//音频内容对象
 navigator.getUserMedia = (navigator.getUserMedia ||
  navigator.webkitGetUserMedia ||
  navigator.mozGetUserMedia ||
  navigator.msGetUserMedia); // 兼容其他浏览器

 navigator.getUserMedia({audio: true}, create_stream, function (err) {
  console.log(err)
 });

 function create_stream(user_media) {
  var stream_input = audio_context.createMediaStreamSource(user_media);
  reco = new Recorder(stream_input);
 }


 function start_reco() {
  reco.record();
 }

 function ai_reco() {
  reco.stop();

  reco.exportWAV(function (wav_file) {
   console.log(wav_file);
   var formdata = new FormData(); // form 表单 {key:value}
   formdata.append("audio", wav_file); // form input type="file"
   $.ajax({
    url: "/receive_audio",
    type: 'post',
    processData: false,
    contentType: false,
    data: formdata,
    dataType: 'json',
    success: function (data) {
     console.log(data);
     document.getElementById("player").src = "/get_audio/" + data.filename;
    }
   })
  });
  reco.clear();
 }

</script>
</html>

2.Recorder.js内容

直接复制保存即可

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Recorder = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";

module.exports = require("./recorder").Recorder;

},{"./recorder":2}],2:[function(require,module,exports){
'use strict';

var _createClass = (function () {
 function defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
   var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
  }
 }return function (Constructor, protoProps, staticProps) {
  if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
 };
})();

Object.defineProperty(exports, "__esModule", {
 value: true
});
exports.Recorder = undefined;

var _inlineWorker = require('inline-worker');

var _inlineWorker2 = _interopRequireDefault(_inlineWorker);

function _interopRequireDefault(obj) {
 return obj && obj.__esModule ? obj : { default: obj };
}

function _classCallCheck(instance, Constructor) {
 if (!(instance instanceof Constructor)) {
  throw new TypeError("Cannot call a class as a function");
 }
}

var Recorder = exports.Recorder = (function () {
 function Recorder(source, cfg) {
  var _this = this;

  _classCallCheck(this, Recorder);

  this.config = {
   bufferLen: 4096,
   numChannels: 2,
   mimeType: 'audio_pcm/wav'
  };
  this.recording = false;
  this.callbacks = {
   getBuffer: [],
   exportWAV: []
  };

  Object.assign(this.config, cfg);
  this.context = source.context;
  this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, this.config.bufferLen, this.config.numChannels, this.config.numChannels);

  this.node.onaudioprocess = function (e) {
   if (!_this.recording) return;

   var buffer = [];
   for (var channel = 0; channel < _this.config.numChannels; channel++) {
    buffer.push(e.inputBuffer.getChannelData(channel));
   }
   _this.worker.postMessage({
    command: 'record',
    buffer: buffer
   });
  };

  source.connect(this.node);
  this.node.connect(this.context.destination); //this should not be necessary

  var self = {};
  this.worker = new _inlineWorker2.default(function () {
   var recLength = 0,
    recBuffers = [],
    sampleRate = undefined,
    numChannels = undefined;

   self.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;
    numChannels = config.numChannels;
    initBuffers();
   }

   function record(inputBuffer) {
    for (var channel = 0; channel < numChannels; channel++) {
     recBuffers[channel].push(inputBuffer[channel]);
    }
    recLength += inputBuffer[0].length;
   }

   function exportWAV(type) {
    var buffers = [];
    for (var channel = 0; channel < numChannels; channel++) {
     buffers.push(mergeBuffers(recBuffers[channel], recLength));
    }
    var interleaved = undefined;
    if (numChannels === 2) {
     interleaved = interleave(buffers[0], buffers[1]);
    } else {
     interleaved = buffers[0];
    }
    var dataview = encodeWAV(interleaved);
    var audioBlob = new Blob([dataview], { type: type });

    self.postMessage({ command: 'exportWAV', data: audioBlob });
   }

   function getBuffer() {
    var buffers = [];
    for (var channel = 0; channel < numChannels; channel++) {
     buffers.push(mergeBuffers(recBuffers[channel], recLength));
    }
    self.postMessage({ command: 'getBuffer', data: buffers });
   }

   function clear() {
    recLength = 0;
    recBuffers = [];
    initBuffers();
   }

   function initBuffers() {
    for (var channel = 0; channel < numChannels; channel++) {
     recBuffers[channel] = [];
    }
   }

   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, inputR) {
    var length = inputL.length + inputR.length;
    var result = new Float32Array(length);

    var index = 0,
     inputIndex = 0;

    while (index < length) {
     result[index++] = inputL[inputIndex];
     result[index++] = inputR[inputIndex];
     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(44 + samples.length * 2);
    var view = new DataView(buffer);

    /* RIFF identifier */
    writeString(view, 0, 'RIFF');
    /* RIFF chunk length */
    view.setUint32(4, 36 + samples.length * 2, true);
    /* RIFF type */
    writeString(view, 8, 'WAVE');
    /* format chunk identifier */
    writeString(view, 12, 'fmt ');
    /* format chunk length */
    view.setUint32(16, 16, true);
    /* sample format (raw) */
    view.setUint16(20, 1, true);
    /* channel count */
    view.setUint16(22, numChannels, true);
    /* sample rate */
    view.setUint32(24, sampleRate, true);
    /* byte rate (sample rate * block align) */
    view.setUint32(28, sampleRate * 4, true);
    /* block align (channel count * bytes per sample) */
    view.setUint16(32, numChannels * 2, true);
    /* bits per sample */
    view.setUint16(34, 16, true);
    /* data chunk identifier */
    writeString(view, 36, 'data');
    /* data chunk length */
    view.setUint32(40, samples.length * 2, true);

    floatTo16BitPCM(view, 44, samples);

    return view;
   }
  }, self);

  this.worker.postMessage({
   command: 'init',
   config: {
    sampleRate: this.context.sampleRate,
    numChannels: this.config.numChannels
   }
  });

  this.worker.onmessage = function (e) {
   var cb = _this.callbacks[e.data.command].pop();
   if (typeof cb == 'function') {
    cb(e.data.data);
   }
  };
 }

 _createClass(Recorder, [{
  key: 'record',
  value: function record() {
   this.recording = true;
  }
 }, {
  key: 'stop',
  value: function stop() {
   this.recording = false;
  }
 }, {
  key: 'clear',
  value: function clear() {
   this.worker.postMessage({ command: 'clear' });
  }
 }, {
  key: 'getBuffer',
  value: function getBuffer(cb) {
   cb = cb || this.config.callback;
   if (!cb) throw new Error('Callback not set');

   this.callbacks.getBuffer.push(cb);

   this.worker.postMessage({ command: 'getBuffer' });
  }
 }, {
  key: 'exportWAV',
  value: function exportWAV(cb, mimeType) {
   mimeType = mimeType || this.config.mimeType;
   cb = cb || this.config.callback;
   if (!cb) throw new Error('Callback not set');

   this.callbacks.exportWAV.push(cb);

   this.worker.postMessage({
    command: 'exportWAV',
    type: mimeType
   });
  }
 }], [{
  key: 'forceDownload',
  value: function forceDownload(blob, filename) {
   var url = (window.URL || window.webkitURL).createObjectURL(blob);
   var link = window.document.createElement('a');
   link.href = url;
   link.download = filename || 'output.wav';
   var click = document.createEvent("Event");
   click.initEvent("click", true, true);
   link.dispatchEvent(click);
  }
 }]);

 return Recorder;
})();

exports.default = Recorder;

},{"inline-worker":3}],3:[function(require,module,exports){
"use strict";

module.exports = require("./inline-worker");
},{"./inline-worker":4}],4:[function(require,module,exports){
(function (global){
"use strict";

var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };

var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker);

var InlineWorker = (function () {
 function InlineWorker(func, self) {
 var _this = this;

 _classCallCheck(this, InlineWorker);

 if (WORKER_ENABLED) {
  var functionBody = func.toString().trim().match(/^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/)[1];
  var url = global.URL.createObjectURL(new global.Blob([functionBody], { type: "text/javascript" }));

  return new global.Worker(url);
 }

 this.self = self;
 this.self.postMessage = function (data) {
  setTimeout(function () {
  _this.onmessage({ data: data });
  }, 0);
 };

 setTimeout(function () {
  func.call(self);
 }, 0);
 }

 _createClass(InlineWorker, {
 postMessage: {
  value: function postMessage(data) {
  var _this = this;

  setTimeout(function () {
   _this.self.onmessage({ data: data });
  }, 0);
  }
 }
 });

 return InlineWorker;
})();

module.exports = InlineWorker;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1])(1)
});

3.flask写法

...
@app.route("/")
def index():
 return render_template("index.html")

@app.route("/receive_audio", methods=["POST"])
def receive_audio():
 file = request.files.get("audio")
 if file:
  filepath = os.path.join(BAISE_DIR, "data", "%s.m4a" % uuid4())
  file.save(filepath)

  text = baidu.auido2text(filepath)

  answer = tuling.chat(text)

  res = baidu.text2audio(answer)
  if res.get("err_no") == 200:
   return {"code": 200, "filename": res.get("filename")}

 return {"code": 201, "msg": "上传失败"}


@app.route("/get_audio/<filename>")
def get_audio(filename):
 return send_file(os.path.join(BAISE_DIR, "data", filename))

...

注意flask启动ip写成127.0.0.1 其他地址 js可能会报错

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery EasyUI API 中文文档 搜索框
Sep 29 Javascript
关于jquery中全局函数each使用介绍
Dec 10 Javascript
js中对函数设置默认参数值的3种方法
Oct 23 Javascript
JavaScript表单验证实例之验证表单项是否为空
Jan 10 Javascript
浅谈Javascript数组(推荐)
May 17 Javascript
JS中用try catch对代码运行的性能影响分析
Dec 26 Javascript
Node.js Express 框架 POST方法详解
Jan 23 Javascript
js图片上传的封装代码
Aug 01 Javascript
Bootstrap 中data-[*] 属性的整理
Mar 13 Javascript
JS非行间样式获取函数的实例代码
Jun 05 Javascript
JS桶排序的简单理解与实现方法示例
Nov 25 Javascript
详解ES6 CLASS在微信小程序中的应用实例
Apr 24 Javascript
解决vue自定义全局消息框组件问题
Nov 22 #Javascript
JavaScript实现省市联动效果
Nov 22 #Javascript
Vue混入mixins滚动触底的方法
Nov 22 #Javascript
超简单的微信小程序轮播图
Nov 22 #Javascript
微信小程序实现Swiper轮播图效果
Nov 22 #Javascript
Js代码中的span拼接问题解决
Nov 22 #Javascript
微信小程序商品详情页底部弹出框
Nov 22 #Javascript
You might like
DOTA2 无惧惊涛骇浪 昆卡大型水友攻略
2020/04/20 DOTA
php Xdebug 调试扩展的安装与使用.
2010/03/13 PHP
PHP类的静态(static)方法和静态(static)变量使用介绍
2012/02/19 PHP
一个经典实用的PHP图像处理类分享
2014/11/18 PHP
php判断数组是否为空的实例方法
2020/05/10 PHP
jquery ui dialog里调用datepicker的问题
2009/08/06 Javascript
js购物车实现思路及代码(个人感觉不错)
2013/12/23 Javascript
jQuery中:checkbox选择器用法实例
2015/01/03 Javascript
nodejs批量修改文件编码格式
2015/01/22 NodeJs
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
JavaScript希尔排序、快速排序、归并排序算法
2016/05/08 Javascript
移动端 一个简单易懂的弹出框
2016/07/06 Javascript
又一枚精彩的弹幕效果jQuery实现
2016/07/25 Javascript
详细总结Javascript中的焦点管理
2016/09/17 Javascript
JavaScript中数组slice和splice的对比小结
2016/09/22 Javascript
JS实现探测网站链接的方法【测试可用】
2016/11/08 Javascript
微信小程序 本地数据存储实例详解
2017/04/13 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
JS中的多态实例详解
2017/10/15 Javascript
收集前端面试题之url、href、src
2018/03/22 Javascript
vue中的数据绑定原理的实现
2018/07/02 Javascript
Vue axios 跨域请求无法带上cookie的解决
2020/09/08 Javascript
python微信公众号之关键词自动回复
2018/06/15 Python
Python多线程爬取豆瓣影评API接口
2019/10/22 Python
python3 webp转gif格式的实现示例
2019/12/10 Python
python3 配置logging日志类的操作
2020/04/08 Python
如何基于线程池提升request模块效率
2020/04/18 Python
python asyncio 协程库的使用
2021/01/21 Python
python实现图片转字符画
2021/02/19 Python
新百伦折扣店:Joe’s New Balance Outlet
2016/08/20 全球购物
自荐信模版
2013/10/24 职场文书
教师旷工检讨书
2014/01/18 职场文书
国际贸易专业个人求职信格式
2014/02/02 职场文书
十八大宣传标语
2014/10/09 职场文书
司法局群众路线教育实践活动开展情况总结
2014/10/25 职场文书
2014年个人业务工作总结
2014/11/17 职场文书