(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["Recorder"] = factory(); else root["Recorder"] = factory(); })(typeof self !== 'undefined' ? self : this, function() { 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; /******/ /******/ // 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 = 0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(global) { var AudioContext = global.AudioContext || global.webkitAudioContext; // Constructor var Recorder = function( config ){ if ( !Recorder.isRecordingSupported() ) { throw new Error("Recording is not supported in this browser"); } this.state = "inactive"; this.config = Object.assign({ bufferLength: 4096, encoderApplication: 2049, encoderFrameSize: 20, encoderPath: 'encoderWorker.min.js', encoderSampleRate: 48000, leaveStreamOpen: false, maxBuffersPerPage: 40, mediaTrackConstraints: true, monitorGain: 0, numberOfChannels: 1, recordingGain: 1, resampleQuality: 3, streamPages: false, wavBitDepth: 16, }, config ); this.initWorker(); }; // Static Methods Recorder.isRecordingSupported = function(){ return AudioContext && global.navigator && global.navigator.mediaDevices && global.navigator.mediaDevices.getUserMedia && global.WebAssembly; }; // Instance Methods Recorder.prototype.clearStream = function(){ if ( this.stream ) { if ( this.stream.getTracks ) { this.stream.getTracks().forEach( function( track ){ track.stop(); }); } else { this.stream.stop(); } delete this.stream; } if ( this.audioContext ){ this.audioContext.close(); delete this.audioContext; } }; Recorder.prototype.encodeBuffers = function( inputBuffer ){ if ( this.state === "recording" ) { var buffers = []; for ( var i = 0; i < inputBuffer.numberOfChannels; i++ ) { buffers[i] = inputBuffer.getChannelData(i); } this.encoder.postMessage({ command: "encode", buffers: buffers }); } }; Recorder.prototype.initAudioContext = function( sourceNode ){ if (sourceNode && sourceNode.context) { this.audioContext = sourceNode.context; } if ( !this.audioContext ) { this.audioContext = new AudioContext(); } return this.audioContext; }; Recorder.prototype.initAudioGraph = function(){ var self = this; // First buffer can contain old data. Don't encode it. this.encodeBuffers = function(){ delete this.encodeBuffers; }; this.scriptProcessorNode = this.audioContext.createScriptProcessor( this.config.bufferLength, this.config.numberOfChannels, this.config.numberOfChannels ); this.scriptProcessorNode.connect( this.audioContext.destination ); this.scriptProcessorNode.onaudioprocess = function( e ) { self.encodeBuffers( e.inputBuffer ); }; this.monitorGainNode = this.audioContext.createGain(); this.setMonitorGain( this.config.monitorGain ); this.monitorGainNode.connect( this.audioContext.destination ); this.recordingGainNode = this.audioContext.createGain(); this.setRecordingGain( this.config.recordingGain ); this.recordingGainNode.connect( this.scriptProcessorNode ); }; Recorder.prototype.initSourceNode = function( sourceNode ){ var self = this; if ( sourceNode && sourceNode.context ) { return global.Promise.resolve( sourceNode ); } if ( this.stream && this.sourceNode ) { return global.Promise.resolve( this.sourceNode ); } return global.navigator.mediaDevices.getUserMedia({ audio : this.config.mediaTrackConstraints }).then( function( stream ){ self.stream = stream; return self.audioContext.createMediaStreamSource( stream ); }); }; Recorder.prototype.initWorker = function(){ var self = this; var streamPage = function( e ) { self.streamPage( e.data ); }; var storePage = function( e ) { self.storePage( e.data ); }; this.recordedPages = []; this.totalLength = 0; this.encoder = new global.Worker( this.config.encoderPath ); this.encoder.addEventListener( "message", this.config.streamPages ? streamPage : storePage ); }; Recorder.prototype.pause = function(){ if ( this.state === "recording" ){ this.state = "paused"; this.onpause(); } }; Recorder.prototype.resume = function() { if ( this.state === "paused" ) { this.state = "recording"; this.onresume(); } }; Recorder.prototype.setRecordingGain = function( gain ){ this.config.recordingGain = gain; if ( this.recordingGainNode && this.audioContext ) { this.recordingGainNode.gain.setTargetAtTime(gain, this.audioContext.currentTime, 0.01); } }; Recorder.prototype.setMonitorGain = function( gain ){ this.config.monitorGain = gain; if ( this.monitorGainNode && this.audioContext ) { this.monitorGainNode.gain.setTargetAtTime(gain, this.audioContext.currentTime, 0.01); } }; Recorder.prototype.start = function( sourceNode ){ if ( this.state === "inactive" ) { var self = this; this.initAudioContext( sourceNode ); this.initAudioGraph(); return this.initSourceNode( sourceNode ).then( function( sourceNode ){ self.state = "recording"; self.encoder.postMessage( Object.assign({ command: 'init', originalSampleRate: self.audioContext.sampleRate, wavSampleRate: self.audioContext.sampleRate }, self.config)); self.sourceNode = sourceNode; self.sourceNode.connect( self.monitorGainNode ); self.sourceNode.connect( self.recordingGainNode ); self.onstart(); }); } }; Recorder.prototype.stop = function(){ if ( this.state !== "inactive" ) { this.state = "inactive"; this.monitorGainNode.disconnect(); this.scriptProcessorNode.disconnect(); this.recordingGainNode.disconnect(); this.sourceNode.disconnect(); if ( !this.config.leaveStreamOpen ) { this.clearStream(); } this.encoder.postMessage({ command: "done" }); } }; Recorder.prototype.storePage = function( page ) { if ( page === null ) { var outputData = new Uint8Array( this.totalLength ); this.recordedPages.reduce( function( offset, page ){ outputData.set( page, offset ); return offset + page.length; }, 0); this.ondataavailable( outputData ); this.initWorker(); this.onstop(); } else { this.recordedPages.push( page ); this.totalLength += page.length; } }; Recorder.prototype.streamPage = function( page ) { if ( page === null ) { this.initWorker(); this.onstop(); } else { this.ondataavailable( page ); } }; // Callback Handlers Recorder.prototype.ondataavailable = function(){}; Recorder.prototype.onpause = function(){}; Recorder.prototype.onresume = function(){}; Recorder.prototype.onstart = function(){}; Recorder.prototype.onstop = function(){}; module.exports = Recorder; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1))) /***/ }), /* 1 */ /***/ (function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || Function("return this")() || (1,eval)("this"); } catch(e) { // This works if the window reference is available if(typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }) /******/ ]); });