Skip to content

Commit fc2e756

Browse files
committed
objectmode now works for all three APIs
1 parent e6c4be1 commit fc2e756

11 files changed

+141
-88
lines changed

dist/watson-speech.js

Lines changed: 88 additions & 55 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
},
4141
"dependencies": {
4242
"clone": "^1.0.2",
43+
"defaults": "^1.0.3",
4344
"microphone-stream": "^3.0.2",
4445
"object.pick": "^1.1.1",
4546
"readable-blob-stream": "^1.1.0",

speech-to-text/format-stream.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var Transform = require('stream').Transform;
44
var util = require('util');
55
var clone = require('clone');
6+
var defaults = require('defaults');
67

78
/**
89
* Applies some basic formating to transcriptions:
@@ -18,11 +19,11 @@ var clone = require('clone');
1819
* @constructor
1920
*/
2021
function FormatStream(opts) {
21-
this.options = util._extend({
22+
this.options = defaults(opts, {
2223
model: '', // some models should have all spaces removed
2324
hesitation: '\u2026', // ellipsis
2425
decodeStrings: true
25-
}, opts);
26+
});
2627
Transform.call(this, opts);
2728

2829
this.isJaCn = ((this.options.model.substring(0,5) === 'ja-JP') || (this.options.model.substring(0,5) === 'zh-CN'));

speech-to-text/getusermedia.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = function getUserMedia(constraints) {
55
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
66
return navigator.mediaDevices.getUserMedia(constraints);
77
}
8+
// todo: return a fake promise if window.Promise is undefined
89
return new Promise(function(resolve, reject) {
910
var gum = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
1011
if (!gum) {

speech-to-text/media-element-audio-stream.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
var Readable = require('stream').Readable;
33
var util = require('util');
4+
var defaults = require('defaults');
45

56
/**
67
* Turns a MediaStream object (from getUserMedia) into a Node.js Readable stream and converts the audio to Buffers
@@ -18,18 +19,18 @@ var util = require('util');
1819
*/
1920
function MediaElementAudioStream(source, opts) {
2021

21-
opts = util._extend({
22+
opts = defaults(opts, {
2223
// "It is recommended for authors to not specify this buffer size and allow the implementation to pick a good
2324
// buffer size to balance between latency and audio quality."
2425
// https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createScriptProcessor
2526
// Possible values: null, 256, 512, 1024, 2048, 4096, 8192, 16384
2627
// however, webkitAudioContext (safari) requires it to be set
2728
bufferSize: (typeof AudioContext != "undefined" ? null : 4096),
2829
muteSource: false,
29-
autoplay: true,
30+
autoPlay: true,
3031
crossOrigin: "anonymous", // required for cross-domain audio playback
3132
objectMode: true // true = emit AudioBuffers w/ audio + some metadata, false = emite node.js Buffers (with binary data only
32-
}, opts);
33+
});
3334

3435
// We can only emit one channel's worth of audio, so only one input. (Who has multiple microphones anyways?)
3536
var inputChannels = 1;
@@ -92,7 +93,7 @@ function MediaElementAudioStream(source, opts) {
9293
source.play();
9394
source.removeEventListener("canplaythrough", start);
9495
}
95-
if (opts.autoplay) {
96+
if (opts.autoPlay) {
9697
// play immediately if we have enough data, otherwise wait for the canplaythrough event
9798
if(source.readyState === source.HAVE_ENOUGH_DATA) {
9899
source.play();

speech-to-text/recognize-blob.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var RecognizeStream = require('./recognize-stream.js');
2020
var FilePlayer = require('./file-player.js');
2121
var FormatStream = require('./format-stream.js');
2222
var TimingStream = require('./timing-stream.js');
23-
var util = require('util');
23+
2424

2525

2626
/**
@@ -43,12 +43,13 @@ module.exports = function recognizeBlob(options) {
4343

4444
var realtime = options.realtime || typeof options.realtime === 'undefined' && options.play;
4545

46-
var rsOpts = util._extend({
47-
// if we're piping through the timing stream, we need objectMode input to get the timing data
48-
readableObjectMode: options.objectMode || realtime
49-
}, options);
46+
// we don't want the readable stream to have objectMode on the input even if we're setting it for the output
47+
// unless were in realtime mode - in which case the timing stream requires objectMode input.
48+
var rsOpts = Object.assign({}, options);
49+
rsOpts.readableObjectMode = options.objectMode || realtime;
5050
delete rsOpts.objectMode;
5151

52+
5253
var recognizeStream = new RecognizeStream(rsOpts);
5354
var stream = new BlobStream(options.data).pipe(recognizeStream);
5455

speech-to-text/recognize-element.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,19 @@ module.exports = function recognizeElement(options) {
3535
throw new Error("WatsonSpeechToText: missing required parameter: opts.token");
3636
}
3737

38-
options['content-type'] = 'audio/l16;rate=16000'; // raw wav audio (no header)
39-
var recognizeStream = new RecognizeStream(options);
38+
// we don't want the readable stream to have objectMode on the input even if we're setting it for the output
39+
var rsOpts = Object.assign({}, options);
40+
rsOpts.readableObjectMode = options.objectMode;
41+
rsOpts['content-type'] = 'audio/l16;rate=16000';
42+
delete rsOpts.objectMode;
43+
44+
var recognizeStream = new RecognizeStream(rsOpts);
4045

4146
var sourceStream = new MediaElementAudioStream(options.element , {
4247
objectMode: true,
4348
bufferSize: options.bufferSize,
4449
muteSource: options.muteSource,
45-
autoplay: options.autoPlay
50+
autoPlay: options.autoPlay !== false // default to true if it's undefined
4651
});
4752

4853
var stream = sourceStream
@@ -55,5 +60,5 @@ module.exports = function recognizeElement(options) {
5560

5661
recognizeStream.on('stop', sourceStream.stop.bind(sourceStream));
5762

58-
return stream;;
63+
return stream;
5964
};

speech-to-text/recognize-microphone.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,22 @@ module.exports = function recognizeMicrophone(options) {
3838
throw new Error("WatsonSpeechToText: missing required parameter: opts.token");
3939
}
4040

41-
options['content-type'] = 'audio/l16;rate=16000'; // raw wav audio (no header)
42-
var recognizeStream = new RecognizeStream(options);
41+
// we don't want the readable stream to have objectMode on the input even if we're setting it for the output
42+
var rsOpts = Object.assign({}, options);
43+
rsOpts.readableObjectMode = options.objectMode;
44+
rsOpts['content-type'] = 'audio/l16;rate=16000';
45+
delete rsOpts.objectMode;
46+
47+
var recognizeStream = new RecognizeStream(rsOpts);
48+
4349

4450
getUserMedia({video: false, audio: true}).then(function(mic) {
4551
var micStream = new MicrophoneStream(mic, {
4652
objectMode: true,
4753
bufferSize: options.bufferSize
4854
});
4955
micStream
50-
.pipe(new L16({writableObjectMode: true, downsample: false}))
56+
.pipe(new L16({writableObjectMode: true}))
5157
.pipe(recognizeStream);
5258

5359
recognizeStream.on('stop', micStream.stop.bind(micStream));

speech-to-text/recognize-stream.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var util = require('util');
2222
var pick = require('object.pick');
2323
var W3CWebSocket = require('websocket').w3cwebsocket;
2424
var contentType = require('./content-type');
25+
var defaults = require('defaults');
2526

2627

2728
var OPENING_MESSAGE_PARAMS_ALLOWED = ['continuous', 'max_alternatives', 'timestamps', 'word_confidence', 'inactivity_timeout',
@@ -103,7 +104,11 @@ RecognizeStream.prototype.initialize = function () {
103104
var url = (options.url || "wss://stream.watsonplatform.net/speech-to-text/api").replace(/^http/, 'ws') + '/v1/recognize?' + queryString;
104105

105106
// turn off all the extras if we're just outputting text
106-
var defaults = {
107+
var textModeDefaults = {
108+
action: 'start',
109+
'content-type': 'audio/wav',
110+
continuous: true,
111+
inactivity_timeout: 30,
107112
interim_results: false,
108113
word_confidence: false,
109114
timestamps: false,
@@ -112,24 +117,21 @@ RecognizeStream.prototype.initialize = function () {
112117

113118
// but turn everything on if we're in objectMode and the end user can consume it
114119
var objectModeDefaults = {
120+
action: 'start',
121+
'content-type': 'audio/wav',
122+
continuous: true,
123+
inactivity_timeout: 30,
115124
interim_results: true,
116125
word_confidence: true,
117126
timestamps: true,
118127
max_alternatives: 3
119128
};
120129

121-
var openingMessage = util._extend({
122-
action: 'start',
123-
'content-type': 'audio/wav',
124-
continuous: true,
125-
max_alternatives: 3,
126-
inactivity_timeout: 30
127-
},
128-
(options.objectMode || options.readableObjectMode) ? objectModeDefaults : defaults,
129-
pick(options, OPENING_MESSAGE_PARAMS_ALLOWED)
130+
var openingMessage = defaults(
131+
pick(options, OPENING_MESSAGE_PARAMS_ALLOWED),
132+
(options.objectMode || options.readableObjectMode) ? objectModeDefaults : textModeDefaults
130133
);
131134

132-
133135
var self = this;
134136

135137
//node params: requestUrl, protocols, origin, headers, extraRequestOptions

speech-to-text/timing-stream.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var Duplex = require('stream').Duplex;
44
var util = require('util');
55
var clone = require('clone');
6+
var defaults = require('defaults');
67

78
/**
89
* Slows results down to no faster than real time.
@@ -15,12 +16,12 @@ var clone = require('clone');
1516
* @constructor
1617
*/
1718
function TimingStream(opts) {
18-
this.options = util._extend({
19+
this.options = defaults(opts, {
1920
emitAt: TimingStream.START,
2021
delay: 0,
2122
allowHalfOpen: true, // keep the readable side open after the source closes
2223
writableObjectMode: true
23-
}, opts);
24+
});
2425
Duplex.call(this, opts);
2526

2627
this.startTime = Date.now();

0 commit comments

Comments
 (0)