Skip to content

Commit 87de804

Browse files
authored
Add Speech API streaming sample. (#144)
* Add Speech API streaming example. * Remove comment. * Add test. * Fix failing test. * Rename variable.
1 parent ca59c02 commit 87de804

File tree

5 files changed

+197
-6
lines changed

5 files changed

+197
-6
lines changed

speech/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,18 @@ Example:
4242

4343
[recognition_docs]: https://cloud.google.com/speech/
4444
[recognition_code]: recognize.js
45+
46+
### Recognition (Streaming)
47+
48+
View the [documentation][recognition_streaming_docs] or the [source code][recognition_streaming_code].
49+
50+
__Run the sample:__
51+
52+
Usage: `node recognize_streaming <path-to-audio-file>`
53+
54+
Example:
55+
56+
node recognize_streaming "/path/to/audio.file"
57+
58+
[recognition_streaming_docs]: https://cloud.google.com/speech/
59+
[recognition_streaming_code]: recognize_streaming.js

speech/package.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
"node": ">=0.10.x"
1010
},
1111
"dependencies": {
12-
"googleapis": "^7.1.0"
13-
},
14-
"devDependencies": {
15-
"async": "^1.5.2"
12+
"async": "^1.5.2",
13+
"google-auto-auth": "^0.2.4",
14+
"google-proto-files": "^0.2.4",
15+
"googleapis": "^7.1.0",
16+
"grpc": "^0.15.0"
1617
}
1718
}

speech/recognize_streaming.js

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
var async = require('async');
17+
var fs = require('fs');
18+
var path = require('path');
19+
var grpc = require('grpc');
20+
var googleProtoFiles = require('google-proto-files');
21+
var googleAuth = require('google-auto-auth');
22+
23+
// [START proto]
24+
var PROTO_ROOT_DIR = googleProtoFiles('..');
25+
var PROTO_FILE_PATH = googleProtoFiles('cloud', 'speech', 'v1', 'cloud_speech.proto');
26+
27+
var protoDescriptor = grpc.load({
28+
root: PROTO_ROOT_DIR,
29+
file: path.relative(PROTO_ROOT_DIR, PROTO_FILE_PATH)
30+
}, 'proto', {
31+
binaryAsBase64: true,
32+
convertFieldsToCamelCase: true
33+
});
34+
var speechProto = protoDescriptor.google.cloud.speech.v1;
35+
// [END proto]
36+
37+
// [START authenticating]
38+
function getSpeechService (callback) {
39+
var googleAuthClient = googleAuth({
40+
scopes: [
41+
'https://www.googleapis.com/auth/cloud-platform'
42+
]
43+
});
44+
45+
googleAuthClient.getAuthClient(function (err, authClient) {
46+
if (err) {
47+
return callback(err);
48+
}
49+
50+
var credentials = grpc.credentials.combineChannelCredentials(
51+
grpc.credentials.createSsl(),
52+
grpc.credentials.createFromGoogleCredential(authClient)
53+
);
54+
55+
console.log('Loading speech service...');
56+
var stub = new speechProto.Speech('speech.googleapis.com', credentials);
57+
return callback(null, stub);
58+
});
59+
}
60+
// [END authenticating]
61+
62+
// [START construct_request]
63+
function getAudioFile (inputFile, callback) {
64+
fs.readFile(inputFile, function (err, audioFile) {
65+
if (err) {
66+
return callback(err);
67+
}
68+
console.log('Got audio file!');
69+
return callback(null, audioFile);
70+
});
71+
}
72+
// [END construct_request]
73+
74+
function main (inputFile, callback) {
75+
var audioFile;
76+
77+
async.waterfall([
78+
function (cb) {
79+
getAudioFile(inputFile, cb);
80+
},
81+
function (_audioFile, cb) {
82+
audioFile = _audioFile;
83+
getSpeechService(cb);
84+
},
85+
// [START send_request]
86+
function sendRequest (speechService, cb) {
87+
console.log('Analyzing speech...');
88+
var responses = [];
89+
var call = speechService.recognize();
90+
91+
// Listen for various responses
92+
call.on('error', cb);
93+
call.on('data', function (recognizeResponse) {
94+
if (recognizeResponse) {
95+
responses.push(recognizeResponse);
96+
}
97+
});
98+
call.on('end', function () {
99+
cb(null, responses);
100+
});
101+
102+
// Write the initial recognize reqeust
103+
call.write(new speechProto.RecognizeRequest({
104+
initialRequest: new speechProto.InitialRecognizeRequest({
105+
encoding: 'LINEAR16',
106+
sampleRate: 16000,
107+
interimResults: false,
108+
continuous: false,
109+
enableEndpointerEvents: false
110+
})
111+
}));
112+
113+
// Write an audio request
114+
call.write(new speechProto.RecognizeRequest({
115+
audioRequest: new speechProto.AudioRequest({
116+
content: audioFile
117+
})
118+
}));
119+
120+
// Signal that we're done writing
121+
call.end();
122+
}
123+
// [END send_request]
124+
], callback);
125+
}
126+
127+
// [START run_application]
128+
if (module === require.main) {
129+
if (process.argv.length < 3) {
130+
console.log('Usage: node recognize_streaming <inputFile>');
131+
process.exit();
132+
}
133+
var inputFile = process.argv[2];
134+
main(inputFile, console.log);
135+
}
136+
// [END run_application]
137+
138+
exports.main = main;

test/functions/sendgrid.test.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ function getMockContext () {
175175
};
176176
}
177177

178-
describe('functions:pubsub', function () {
178+
describe('functions:sendgrid', function () {
179179
it('Send fails if not a POST request', function () {
180180
var expectedMsg = 'Only POST requests are accepted';
181181
var mocks = getMocks();
@@ -566,7 +566,9 @@ describe('functions:pubsub', function () {
566566
bucket: 'event-bucket',
567567
name: name
568568
});
569-
569+
sendgridSample.mocks.job.on('error', function (err) {
570+
assert.equal(err, error);
571+
});
570572
setTimeout(function () {
571573
sendgridSample.mocks.job.emit('error', error);
572574
}, 10);
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2016, Google, Inc.
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
'use strict';
15+
16+
var path = require('path');
17+
var recognizeExample = require('../../speech/recognize_streaming');
18+
19+
describe('speech:recognize_streaming', function () {
20+
it('should list entries', function (done) {
21+
recognizeExample.main(
22+
path.join(__dirname, '../../speech/resources/audio.raw'),
23+
function (err, results) {
24+
assert(!err);
25+
assert(results);
26+
assert(results.length === 1);
27+
assert(results[0].results);
28+
assert(console.log.calledWith('Got audio file!'));
29+
assert(console.log.calledWith('Loading speech service...'));
30+
assert(console.log.calledWith('Analyzing speech...'));
31+
done();
32+
}
33+
);
34+
});
35+
});

0 commit comments

Comments
 (0)