Skip to content

Commit 3014478

Browse files
MasterOdindpopp07
authored andcommitted
feat: separate strings out of primary SynthesizeStream pipe (#957)
This prevents strings from being written to the file, which corrupted files of some formats. Additionally, a number of events have been added to listen for these strings returned from the service: `binary_streams`, `marks`, `words`, `warnings`
1 parent 86506e3 commit 3014478

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

lib/synthesize-stream.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ interface SynthesizeStream extends Readable {
5252
*/
5353
class SynthesizeStream extends Readable {
5454

55+
static WEBSOCKET_ERROR: string = 'WebSocket error';
5556
static WEBSOCKET_CONNECTION_ERROR: string = 'WebSocket connection error';
5657

5758
private options;
@@ -68,7 +69,7 @@ class SynthesizeStream extends Readable {
6869
* Note that the WebSocket connection is not established until the first chunk of data is recieved. This allows for IAM token request management by the SDK.
6970
*
7071
* @param {Object} options
71-
* @param {String} options.text - The text that us to be synthesized. Provide plain text or text that is annotated with SSML. SSML input can include the SSML <mark> element. Pass a maximum of 5 KB of text.
72+
* @param {String} options.text - The text that us to be synthesized. Provide plain text or text that is annotated with SSML. SSML input can include the SSML <mark> element. Pass a maximum of 5 KB of text.
7273
* @param {String} options.accept - The requested audio format (MIME type) of the audio.
7374
* @param {String[]} [options.timings] - An array that specifies whether the service is to return word timing information for all strings of the input text
7475
* @param {String} [options.voice='en-US_MichaelVoice'] - The voice that is to be used for the synthesis.
@@ -98,7 +99,7 @@ class SynthesizeStream extends Readable {
9899

99100
const url =
100101
(options.url || 'wss://stream.watsonplatform.net/text-to-speech/api')
101-
.replace(/^http/, 'ws') +
102+
.replace(/^http/, 'ws') +
102103
'/v1/synthesize?' +
103104
queryString;
104105

@@ -126,18 +127,48 @@ class SynthesizeStream extends Readable {
126127

127128
socket.onmessage = message => {
128129
const chunk = message.data;
129-
// some messages are strings - emit those unencoded, but push them to
130-
// the stream as binary
131-
const data = typeof chunk === 'string' ? chunk : Buffer.from(chunk);
130+
// some info messages are sent as strings, telling the content_type and
131+
// timings. Emit them as separate events, but do not send them along the
132+
// pipe.
133+
if (typeof chunk === 'string') {
134+
try {
135+
const json = JSON.parse(chunk);
136+
if (json['binary_streams']) {
137+
self.emit('binary_streams', message, json);
138+
}
139+
else if (json['marks']) {
140+
self.emit('marks', message, json);
141+
}
142+
else if (json['words']) {
143+
self.emit('words', message, json);
144+
}
145+
else if (json['error']) {
146+
// this should have same structure as onerror emit
147+
const err = new Error(json['error']);
148+
err.name = SynthesizeStream.WEBSOCKET_ERROR;
149+
err['event'] = message;
150+
self.emit('error', err);
151+
}
152+
else if (json['warnings']) {
153+
self.emit('warnings', message, json);
154+
}
155+
}
156+
finally {
157+
self.emit('message', message, chunk);
158+
}
159+
return;
160+
}
161+
132162
/**
133163
* Emit any messages received over the wire, mainly used for debugging.
134164
*
135165
* @event SynthesizeStream#message
136166
* @param {Object} message - frame object received from service
137-
* @param {Object} data - a data attribute of the frame that's either a string or a Buffer/TypedArray
167+
* @param {Object} data - a data attribute of the frame that's a Buffer/TypedArray
138168
*/
169+
const data = Buffer.from(chunk);
139170
self.emit('message', message, data);
140-
self.push(Buffer.from(chunk));
171+
self.push(data);
141172
};
142173

143174
socket.onerror = event => {

0 commit comments

Comments
 (0)