react-mic-record
Version:
Record audio from your microphone
570 lines (448 loc) • 19.9 kB
JavaScript
/*!
* react-mic-record v1.0.6
* MIT Licensed
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("react"));
else if(typeof define === 'function' && define.amd)
define(["react"], factory);
else if(typeof exports === 'object')
exports["react-mic-record"] = factory(require("react"));
else
root["react-mic-record"] = factory(root["React"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_6__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_ReactMicRecord__ = __webpack_require__(1);
/* harmony export (immutable) */ __webpack_exports__["browserSupportsAudio"] = browserSupportsAudio;
function browserSupportsAudio() {
var AudioContextClass = window.AudioContext || window.webkitAudioContext;
if (!AudioContextClass) {
return false;
}
var tmp = new AudioContextClass();
if (!tmp) {
return false;
}
tmp.ok = true;
return !!tmp.createAnalyser;
}
/* harmony default export */ __webpack_exports__["default"] = __WEBPACK_IMPORTED_MODULE_0__components_ReactMicRecord__["a" /* default */];
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(6);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__libs_MicrophoneRecorder__ = __webpack_require__(4);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__libs_AudioContext__ = __webpack_require__(2);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__libs_AudioPlayer__ = __webpack_require__(3);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__libs_Visualizer__ = __webpack_require__(5);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ReactMicRecord; });
var _class,
_temp,
_jsxFileName = '/home/shroof/react-mic-record/src/components/ReactMicRecord.js';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var ReactMicRecord = (_temp = _class = function (_React$Component) {
_inherits(ReactMicRecord, _React$Component);
function ReactMicRecord(props) {
_classCallCheck(this, ReactMicRecord);
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
_this.audioContext = null;
_this.microphoneRecorder = null;
_this.state = {
canvas: null,
canvasCtx: null
};
return _this;
}
ReactMicRecord.prototype.componentDidMount = function componentDidMount() {
var _this2 = this;
var _props = this.props,
onStop = _props.onStop,
onStart = _props.onStart,
onData = _props.onData,
audioElem = _props.audioElem,
audioBitsPerSecond = _props.audioBitsPerSecond,
mimeType = _props.mimeType;
var canvas = this.visualizerRef;
var canvasCtx = canvas.getContext("2d");
var options = { audioBitsPerSecond: audioBitsPerSecond, mimeType: mimeType };
this.audioContext = new __WEBPACK_IMPORTED_MODULE_2__libs_AudioContext__["a" /* default */]();
if (audioElem) {
this.audioPlayer = new __WEBPACK_IMPORTED_MODULE_3__libs_AudioPlayer__["a" /* default */](audioElem, this.audioContext);
} else {
this.microphoneRecorder = new __WEBPACK_IMPORTED_MODULE_1__libs_MicrophoneRecorder__["a" /* default */](onStart, onStop, onData, options, this.audioContext);
}
this.setState({ canvas: canvas, canvasCtx: canvasCtx }, function () {
return _this2.visualize();
});
};
ReactMicRecord.prototype.componentWillUnmount = function componentWillUnmount() {
if (this.microphoneRecorder) {
this.microphoneRecorder.unMount();
this.clear();
}
};
ReactMicRecord.prototype.visualize = function visualize() {
var _props2 = this.props,
backgroundColor = _props2.backgroundColor,
strokeColor = _props2.strokeColor,
width = _props2.width,
height = _props2.height,
visualSetting = _props2.visualSetting;
var _state = this.state,
canvas = _state.canvas,
canvasCtx = _state.canvasCtx;
this.visualizer = new __WEBPACK_IMPORTED_MODULE_4__libs_Visualizer__["a" /* default */](this.audioContext, canvasCtx, canvas, width, height, backgroundColor, strokeColor);
if (visualSetting === 'sinewave') {
this.visualizer.visualizeSineWave();
} else if (visualSetting === 'frequencyBars') {
this.visualizer.visualizeFrequencyBars();
}
};
ReactMicRecord.prototype.clear = function clear() {
var _state2 = this.state,
canvasCtx = _state2.canvasCtx,
width = _state2.width,
height = _state2.height;
canvasCtx.clearRect(0, 0, width, height);
};
ReactMicRecord.prototype.render = function render() {
var _this3 = this;
var _props3 = this.props,
record = _props3.record,
width = _props3.width,
height = _props3.height,
className = _props3.className;
if (record) {
if (this.microphoneRecorder) {
this.microphoneRecorder.startRecording();
this.visualize();
}
} else {
if (this.microphoneRecorder) {
this.microphoneRecorder.stopRecording();
this.clear();
}
}
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement('canvas', { ref: function ref(c) {
return _this3.visualizerRef = c;
}, height: height, width: width, className: className, __source: {
fileName: _jsxFileName,
lineNumber: 90
},
__self: this
});
};
return ReactMicRecord;
}(__WEBPACK_IMPORTED_MODULE_0_react___default.a.Component), _class.defaultProps = {
backgroundColor: 'rgba(255, 255, 255, 0.5)',
strokeColor: '#000000',
className: 'visualizer',
audioBitsPerSecond: 128000,
mimeType: 'audio/webm;codecs=opus',
record: false,
width: 640,
height: 100,
visualSetting: 'sinewave'
}, _temp);
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AudioContext; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var AudioContext = function () {
function AudioContext() {
_classCallCheck(this, AudioContext);
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
this.analyser = this.audioCtx.createAnalyser();
}
AudioContext.prototype.getAudioContext = function getAudioContext() {
return this.audioCtx;
};
AudioContext.prototype.getAnalyser = function getAnalyser() {
return this.analyser;
};
return AudioContext;
}();
/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AudioPlayer; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var AudioPlayer = function AudioPlayer(audioElem, audioContext) {
_classCallCheck(this, AudioPlayer);
var audioCtx = audioContext.getAudioContext();
var analyser = audioContext.getAnalyser();
this.audioSource = audioCtx.createMediaElementSource(audioElem);
this.audioSource.connect(analyser);
analyser.connect(audioCtx.destination);
};
/***/ }),
/* 4 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MicrophoneRecorder; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var constraints = { audio: true, video: false }; // constraints - only audio needed
var MicrophoneRecorder = function () {
function MicrophoneRecorder(onStart, onStop, onData, options, audioContext) {
_classCallCheck(this, MicrophoneRecorder);
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
this.audioCtx = audioContext.getAudioContext();
this.analyser = audioContext.getAnalyser();
this.stream = null;
this.onStartCb = onStart;
this.onStopCb = onStop;
this.mediaOptions = options;
this.onData = onData;
this.chunks = [];
this.startTime = null;
}
MicrophoneRecorder.prototype.startRecording = function startRecording() {
var _this = this;
this.startTime = Date.now();
if (this.mediaRecorder) {
if (this.audioCtx && this.audioCtx.state === 'suspended') {
this.audioCtx.resume();
}
if (this.mediaRecorder && this.mediaRecorder.state === 'paused') {
this.mediaRecorder.resume();
return;
}
if (this.audioCtx && this.mediaRecorder && this.mediaRecorder.state === 'inactive') {
this.mediaRecorder.start(10);
var source = this.audioCtx.createMediaStreamSource(this.stream);
source.connect(this.analyser);
if (this.onStartCb) {
this.onStartCb();
}
}
} else {
if (navigator.mediaDevices) {
console.log('getUserMedia supported.');
navigator.mediaDevices.getUserMedia(constraints).then(function (str) {
_this.stream = str;
if (MediaRecorder.isTypeSupported(_this.mediaOptions.mimeType)) {
_this.mediaRecorder = new MediaRecorder(_this.stream, _this.mediaOptions);
} else {
_this.mediaRecorder = new MediaRecorder(_this.stream);
}
if (_this.onStartCb) {
_this.onStartCb();
}
_this.mediaRecorder.onstop = function () {
return _this.onStop();
};
_this.mediaRecorder.ondataavailable = function (e) {
_this.chunks.push(e.data);
if (_this.onData) {
_this.onData(e.data);
}
};
_this.mediaRecorder.start(10);
var source = _this.audioCtx.createMediaStreamSource(_this.stream);
source.connect(_this.analyser);
});
} else {
alert('Your browser does not support audio recording');
}
}
};
MicrophoneRecorder.prototype.stopRecording = function stopRecording() {
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
this.mediaRecorder.stop();
this.audioCtx.suspend();
}
};
MicrophoneRecorder.prototype.unMount = function unMount() {
this.stream && this.stream.getTracks()[0].stop();
this.mediaRecorder = null;
};
MicrophoneRecorder.prototype.onStop = function onStop() {
var blob = new Blob(this.chunks, { 'type': this.mediaOptions.mimeType });
this.chunks = [];
var blobObject = {
blob: blob,
startTime: this.startTime,
stopTime: Date.now(),
options: this.mediaOptions,
blobURL: window.URL.createObjectURL(blob)
};
if (this.onStopCb) {
this.onStopCb(blobObject);
}
};
return MicrophoneRecorder;
}();
/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Visualizer; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
var Visualizer = function () {
function Visualizer(audioContext, canvasCtx, canvas, width, height, backgroundColor, strokeColor) {
_classCallCheck(this, Visualizer);
this.analyser = audioContext.getAnalyser();
this.canvasCtx = canvasCtx;
this.canvas = canvas;
this.width = width;
this.height = height;
this.backgroundColor = backgroundColor;
this.strokeColor = strokeColor;
this.drawVisual = null;
}
Visualizer.prototype.visualizeSineWave = function visualizeSineWave() {
var _this = this;
this.analyser.fftSize = 2048;
var bufferLength = this.analyser.fftSize;
var dataArray = new Uint8Array(bufferLength);
this.canvasCtx.clearRect(0, 0, this.width, this.height);
var draw = function draw() {
_this.drawVisual = requestAnimationFrame(draw);
_this.analyser.getByteTimeDomainData(dataArray);
_this.canvasCtx.fillStyle = _this.backgroundColor;
_this.canvasCtx.fillRect(0, 0, _this.width, _this.height);
_this.canvasCtx.lineWidth = 2;
_this.canvasCtx.strokeStyle = _this.strokeColor;
_this.canvasCtx.beginPath();
var sliceWidth = _this.width * 1.0 / bufferLength;
var x = 0;
for (var i = 0; i < bufferLength; i++) {
var v = dataArray[i] / 128.0;
var y = v * _this.height / 2;
if (i === 0) {
_this.canvasCtx.moveTo(x, y);
} else {
_this.canvasCtx.lineTo(x, y);
}
x += sliceWidth;
}
_this.canvasCtx.lineTo(_this.canvas.width, _this.canvas.height / 2);
_this.canvasCtx.stroke();
};
draw();
};
Visualizer.prototype.visualizeFrequencyBars = function visualizeFrequencyBars() {
var _this2 = this;
this.analyser.fftSize = 256;
var bufferLength = this.analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
this.canvasCtx.clearRect(0, 0, this.width, this.height);
var draw = function draw() {
_this2.drawVisual = requestAnimationFrame(draw);
_this2.analyser.getByteFrequencyData(dataArray);
_this2.canvasCtx.fillStyle = _this2.backgroundColor;
_this2.canvasCtx.fillRect(0, 0, _this2.width, _this2.height);
var barWidth = _this2.width / bufferLength * 2.5;
var barHeight = void 0;
var x = 0;
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
var rgb = hexToRgb(_this2.strokeColor);
_this2.canvasCtx.fillStyle = _this2.strokeColor;
_this2.canvasCtx.fillRect(x, _this2.height - barHeight / 2, barWidth, barHeight / 2);
x += barWidth + 1;
}
};
draw();
};
return Visualizer;
}();
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_6__;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(0);
/***/ })
/******/ ]);
});