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 相关文章推荐
一个简单的JavaScript 日期计算算法
Sep 11 Javascript
javascript cookies操作集合
Apr 12 Javascript
flash调用js中的方法,让js传递变量给flash的办法及思路
Aug 07 Javascript
onmouseover和onmouseout的一些问题思考
Aug 14 Javascript
jquery表单对象属性过滤选择器实例分析
May 18 Javascript
JSON对象 详解及实例代码
Oct 18 Javascript
Vue.js路由组件vue-router使用方法详解
Dec 02 Javascript
写jQuery插件时的注意点
Feb 20 Javascript
Vue的MVVM实现方法
Aug 16 Javascript
laravel5.3 vue 实现收藏夹功能实例详解
Jan 21 Javascript
详解vue添加删除元素的方法
Jun 30 Javascript
JavaScript动态生成表格的示例
Nov 02 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
php获取文件类型和文件信息的方法
2015/07/10 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
javascript中的prototype属性使用说明(函数功能扩展)
2010/08/16 Javascript
jQuery学习笔记之控制页面实现代码
2012/02/27 Javascript
JavaScript设计模式之原型模式(Object.create与prototype)介绍
2014/12/28 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
jQuery弹出遮罩层效果完整示例
2016/09/13 Javascript
微信小程序 获取设备信息 API实例详解
2016/10/02 Javascript
javaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序整理总结
2016/10/10 Javascript
教你5分钟学会用requirejs(必看篇)
2017/07/25 Javascript
vue使用mint-ui实现下拉刷新和无限滚动的示例代码
2017/11/06 Javascript
Javascript网页抢红包外挂实现分享
2018/01/11 Javascript
Element UI 自定义正则表达式验证方法
2018/09/04 Javascript
如何检查一个对象是否为空
2019/04/11 Javascript
VUE实现移动端列表筛选功能
2019/08/23 Javascript
在Angular中实现一个级联效果的下拉框的示例代码
2020/05/20 Javascript
vue使用swiper实现左右滑动切换图片
2020/10/16 Javascript
[02:44]DOTA2英雄基础教程 钢背兽
2013/12/19 DOTA
[02:33]DOTA2英雄基础教程 司夜刺客
2013/12/04 DOTA
Python基础教程之if判断,while循环,循环嵌套
2019/04/25 Python
Python安装与基本数据类型教程详解
2019/05/29 Python
使用python来调用CAN通讯的DLL实现方法
2019/07/03 Python
flask利用flask-wtf验证上传的文件的方法
2020/01/17 Python
Python爬虫基于lxml解决数据编码乱码问题
2020/07/31 Python
使用python实现学生信息管理系统
2021/02/25 Python
Android本地应用打开方法——通过html5写连接
2016/03/11 HTML / CSS
canvas中普通动效与粒子动效的实现代码示例
2019/01/03 HTML / CSS
Bed Bath & Beyond加拿大官网:购买床上用品、浴巾、厨房电器等
2019/10/04 全球购物
安全资金保障制度
2014/01/23 职场文书
本科应届生自荐信
2014/06/29 职场文书
2014年部门工作总结
2014/11/12 职场文书
孔庙导游词
2015/02/04 职场文书
2015年电信员工工作总结
2015/05/26 职场文书
解决Vue+SpringBoot+Shiro跨域问题
2021/06/09 Vue.js
MySQL的全局锁和表级锁的具体使用
2021/08/23 MySQL
mysql 排序失效
2022/05/20 MySQL