UNPKG

watson-speech

Version:

IBM Watson Speech to Text and Text to Speech SDK for web browsers.

197 lines (152 loc) 6.95 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: media-element-audio-stream.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: media-element-audio-stream.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>'use strict'; var Readable = require('stream').Readable; var util = require('util'); /** * Turns a MediaStream object (from getUserMedia) into a Node.js Readable stream and converts the audio to Buffers * * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia * * @param {MediaStream|HTMLMediaElement} source - either https://developer.mozilla.org/en-US/docs/Web/API/MediaStream or https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement * @param {Object} [opts] options * @param {Number|null} [opts.bufferSize=null] https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createScriptProcessor * @param {Boolean} [opts.muteSource=false] - If true, the audio will not be sent back to the source * @constructor */ function MediaElementAudioStream(source, opts) { opts = util._extend({ // "It is recommended for authors to not specify this buffer size and allow the implementation to pick a good // buffer size to balance between latency and audio quality." // https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createScriptProcessor // Possible values: null, 256, 512, 1024, 2048, 4096, 8192, 16384 bufferSize:null, muteSource: false, autoplay: true, crossOrigin: "anonymous" // required for cross-domain audio playback }, opts); // We can only emit one channel's worth of audio, so only one input. (Who has multiple microphones anyways?) var inputChannels = 1; // we shouldn't need any output channels (going back to the browser - that's what the gain node is for), but chrome is buggy and won't give us any audio without one var outputChannels = 1; Readable.call(this, opts); var self = this; var recording = true; // I can't seem to find any documentation for this on &lt;audio> elements, but it seems to be required for cross-domain usage (in addition to CORS headers) //source.crossOrigin = opts.crossOrigin; /** * Convert and emit the raw audio data * @see https://developer.mozilla.org/en-US/docs/Web/API/ScriptProcessorNode/onaudioprocess * @param {AudioProcessingEvent} e https://developer.mozilla.org/en-US/docs/Web/API/AudioProcessingEvent */ function processAudio(e) { // onaudioprocess can be called at least once after we've stopped if (recording) { var raw = e.inputBuffer.getChannelData(0); /** * @event MicrophoneStream#raw * @param {Float32Array} data raw audio data from browser - each sample is a number from -1 to 1 */ self.emit('raw', raw); // Standard (non-object mode) Node.js streams only accepts Buffers or Strings var nodebuffer = new Buffer(raw.buffer); /** * Emit the readable/data event with a node-style buffer. * Note: this is essentially a new DataView on the same underlying ArrayBuffer. * The raw audio data is not actually coppied or changed. * * @event MicrophoneStream#data * @param {Buffer} chunk node-style buffer with audio data; buffers are essentially a Uint8Array */ self.push(nodebuffer); } } var context = new AudioContext(); var audioInput = context.createMediaElementSource(source); var scriptProcessor = context.createScriptProcessor(opts.bufferSize, inputChannels, outputChannels); scriptProcessor.onaudioprocess = processAudio; if (!opts.muteSource) { var gain = context.createGain(); audioInput.connect(gain); gain.connect(context.destination); } audioInput.connect(scriptProcessor); // other half of workaround for chrome bugs scriptProcessor.connect(context.destination); // https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events function start() { source.play(); source.removeEventListener("canplaythrough", start); } if (opts.autoplay) { source.addEventListener("canplaythrough", start); } function end() { recording = false; scriptProcessor.disconnect(); self.push(null); self.emit('close'); } source.addEventListener("ended", end); this.stop = function() { source.pause(); end(); }; source.addEventListener("error", this.emit.bind(this, 'error')); process.nextTick(function() { self.emit('format', { channels: 1, bitDepth: 32, sampleRate: context.sampleRate, signed: true, float: true }); }); } util.inherits(MediaElementAudioStream, Readable); MediaElementAudioStream.prototype._read = function(/* bytes */) { // no-op, (back-pressure flow-control doesn't really work on sound) }; /** * Converts a Buffer back into the raw Float32Array format that browsers use. * Note: this is just a new DataView for the same underlying buffer - * the actual audio data is not copied or changed here. * * @param {Buffer} chunk node-style buffer of audio data from a 'data' event or read() call * @return {Float32Array} raw 32-bit float data view of audio data */ MediaElementAudioStream.toRaw = function toFloat32(chunk) { return new Float32Array(chunk.buffer); }; module.exports = MediaElementAudioStream; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="FormatStream.html">FormatStream</a></li><li><a href="MediaElementAudioStream.html">MediaElementAudioStream</a></li><li><a href="RecognizeStream.html">RecognizeStream</a></li><li><a href="TimingStream.html">TimingStream</a></li></ul><h3>Events</h3><ul><li><a href="MicrophoneStream.html#event:data">data</a></li><li><a href="MicrophoneStream.html#event:raw">raw</a></li><li><a href="RecognizeStream.html#event:connection-close">connection-close</a></li><li><a href="RecognizeStream.html#event:data">data</a></li><li><a href="RecognizeStream.html#event:error">error</a></li><li><a href="RecognizeStream.html#event:results">results</a></li></ul><h3>Global</h3><ul><li><a href="global.html#MAX_WAV">MAX_WAV</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Feb 08 2016 16:11:17 GMT+0000 (UTC) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>