watson-speech
Version:
IBM Watson Speech to Text and Text to Speech SDK for web browsers.
185 lines (149 loc) • 7.59 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: speech-to-text/timing-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: speech-to-text/timing-stream.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>'use strict';
var Transform = require('stream').Transform;
var util = require('util');
var defaults = require('defaults');
var noTimestamps = require('./no-timestamps');
/**
* Slows results down to no faster than real time.
*
* Useful when running recognizeFile because the text can otherwise appear before the words are spoken
*
* @param {Object} [opts]
* @param {*} [opts.emitAt=TimingStream.END] - set to TimingStream.START for a more subtitles-like output where results are returned as soon as the utterance begins
* @param {Number} [opts.delay=0] - Additional delay (in seconds) to apply before emitting words, useful for precise syncing to audio tracks. May be negative
* @constructor
*/
function TimingStream(opts) {
this.options = defaults(opts, {
emitAt: TimingStream.END,
delay: 0,
allowHalfOpen: true, // keep the readable side open after the source closes
writableObjectMode: true
});
Transform.call(this, opts);
this.startTime = Date.now();
// to support stopping mid-stream
this.stopped = false;
this.timeout = null;
}
util.inherits(TimingStream, Transform);
TimingStream.START = 1;
TimingStream.END = 2;
TimingStream.prototype._transform = function(msg, encoding, next) {
if (msg instanceof Buffer) {
return next(new Error('TimingStream requires the source to be in objectMode'));
}
if (Array.isArray(msg.results) && msg.results.length && noTimestamps(msg)) {
var err = new Error('TimingStream requires timestamps');
err.name = noTimestamps.ERROR_NO_TIMESTAMPS;
return next(err);
}
if (this.stopped) {
return;
}
var delayMs = this.getDelayMs(msg);
var objectMode = this.options.objectMode || this.options.readableObjectMode;
var hasTranscript = Array.isArray(msg.results && msg.results.length);
// to support text mode
if (!objectMode && hasTranscript) {
msg = msg.results[0].alternatives[0].transcript;
}
if (objectMode || hasTranscript) {
this.timeout = setTimeout(
function() {
next(null, msg);
},
delayMs
);
} else {
return next();
}
};
/**
* Grabs the appropriate timestamp from the given message, depending on options.emitAt and the type of message
*
* @private
* @param {Object} msg
* @return {Number} timestamp
*/
TimingStream.prototype.getMessageTime = function(msg) {
if (this.options.emitAt === TimingStream.START) {
if (Array.isArray(msg.results) && msg.results.length) {
return msg.results[msg.results.length - 1].alternatives[0].timestamps[0][TimingStream.START];
} else if (Array.isArray(msg.speaker_labels) && msg.speaker_labels.length) {
return msg.speaker_labels[0].from;
}
} else {
if (Array.isArray(msg.results) && msg.results.length) {
var timestamps = msg.results[msg.results.length - 1].alternatives[0].timestamps;
return timestamps[timestamps.length - 1][TimingStream.END];
} else if (Array.isArray(msg.speaker_labels) && msg.speaker_labels.length) {
return msg.speaker_labels[msg.speaker_labels.length - 1].to;
}
}
return 0; // failsafe for unknown message types
};
/**
* Gets the length of time to delay (in ms) before emitting the given message
*
* @private
* @param {Object} msg
* @return {Number} ms to delay
*/
TimingStream.prototype.getDelayMs = function(msg) {
var messageTime = this.getMessageTime(msg);
var nextTickTime = this.startTime + messageTime * 1000; // ms since epoch
var delayMs = nextTickTime - Date.now(); // ms from right now
return Math.max(0, delayMs); // never return a negative number
};
/**
* Overrides the start time, adjusting the delay applied to all pending results.
*
* Stream may emit up to 1 more result based on the older time after this is called.
*
* @param {Number} [time=Date.now()] Start time in Miliseconds since epoch
*/
TimingStream.prototype.setStartTime = function(time) {
this.startTime = time || Date.now();
};
TimingStream.prototype.promise = require('./to-promise');
// when stop is called, immediately stop emitting results
TimingStream.prototype.stop = function stop() {
this.stopped = true;
clearTimeout(this.timeout);
this.emit('stop');
};
module.exports = TimingStream;
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-watson-speech.html">watson-speech</a></li><li><a href="module-watson-speech_speech-to-text.html">watson-speech/speech-to-text</a></li><li><a href="module-watson-speech_speech-to-text_get-models.html">watson-speech/speech-to-text/get-models</a></li><li><a href="module-watson-speech_speech-to-text_recognize-file.html">watson-speech/speech-to-text/recognize-file</a></li><li><a href="module-watson-speech_speech-to-text_recognize-microphone.html">watson-speech/speech-to-text/recognize-microphone</a></li><li><a href="module-watson-speech_text-to-speech.html">watson-speech/text-to-speech</a></li><li><a href="module-watson-speech_text-to-speech_get-voices.html">watson-speech/text-to-speech/get-voices</a></li><li><a href="module-watson-speech_text-to-speech_synthesize.html">watson-speech/text-to-speech/synthesize</a></li></ul><h3>Classes</h3><ul><li><a href="FilePlayer.html">FilePlayer</a></li><li><a href="FormatStream.html">FormatStream</a></li><li><a href="RecognizeStream.html">RecognizeStream</a></li><li><a href="ResultStream.html">ResultStream</a></li><li><a href="SpeakerStream.html">SpeakerStream</a></li><li><a href="TimingStream.html">TimingStream</a></li><li><a href="UrlPlayer.html">UrlPlayer</a></li><li><a href="WebAudioL16Stream.html">WebAudioL16Stream</a></li><li><a href="WritableElementStream.html">WritableElementStream</a></li></ul><h3>Events</h3><ul><li><a href="RecognizeStream.html#event:close">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:listening">listening</a></li><li><a href="RecognizeStream.html#event:message">message</a></li><li><a href="RecognizeStream.html#event:open">open</a></li><li><a href="RecognizeStream.html#event:send-data">send-data</a></li><li><a href="RecognizeStream.html#event:send-json">send-json</a></li><li><a href="RecognizeStream.html#event:stop">stop</a></li><li><a href="SpeakerStream.html#event:data">data</a></li></ul><h3>Global</h3><ul><li><a href="global.html#getContentTypeFromFile">getContentTypeFromFile</a></li><li><a href="global.html#playFile">playFile</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.3</a> on Tue Feb 21 2017 17:41:51 GMT+0000 (UTC)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>