diff --git a/speech/README.md b/speech/README.md index 5a32bcfaac..6be6555ea6 100644 --- a/speech/README.md +++ b/speech/README.md @@ -42,3 +42,18 @@ Example: [recognition_docs]: https://cloud.google.com/speech/ [recognition_code]: recognize.js + +### Recognition (Streaming) + +View the [documentation][recognition_streaming_docs] or the [source code][recognition_streaming_code]. + +__Run the sample:__ + +Usage: `node recognize_streaming ` + +Example: + + node recognize_streaming "/path/to/audio.file" + +[recognition_streaming_docs]: https://cloud.google.com/speech/ +[recognition_streaming_code]: recognize_streaming.js diff --git a/speech/package.json b/speech/package.json index 84e4f4fede..523fb7323d 100644 --- a/speech/package.json +++ b/speech/package.json @@ -9,9 +9,10 @@ "node": ">=0.10.x" }, "dependencies": { - "googleapis": "^7.1.0" - }, - "devDependencies": { - "async": "^1.5.2" + "async": "^1.5.2", + "google-auto-auth": "^0.2.4", + "google-proto-files": "^0.2.4", + "googleapis": "^7.1.0", + "grpc": "^0.15.0" } } diff --git a/speech/recognize_streaming.js b/speech/recognize_streaming.js new file mode 100644 index 0000000000..9bf67f6350 --- /dev/null +++ b/speech/recognize_streaming.js @@ -0,0 +1,138 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var async = require('async'); +var fs = require('fs'); +var path = require('path'); +var grpc = require('grpc'); +var googleProtoFiles = require('google-proto-files'); +var googleAuth = require('google-auto-auth'); + +// [START proto] +var PROTO_ROOT_DIR = googleProtoFiles('..'); +var PROTO_FILE_PATH = googleProtoFiles('cloud', 'speech', 'v1', 'cloud_speech.proto'); + +var protoDescriptor = grpc.load({ + root: PROTO_ROOT_DIR, + file: path.relative(PROTO_ROOT_DIR, PROTO_FILE_PATH) +}, 'proto', { + binaryAsBase64: true, + convertFieldsToCamelCase: true +}); +var speechProto = protoDescriptor.google.cloud.speech.v1; +// [END proto] + +// [START authenticating] +function getSpeechService (callback) { + var googleAuthClient = googleAuth({ + scopes: [ + 'https://www.googleapis.com/auth/cloud-platform' + ] + }); + + googleAuthClient.getAuthClient(function (err, authClient) { + if (err) { + return callback(err); + } + + var credentials = grpc.credentials.combineChannelCredentials( + grpc.credentials.createSsl(), + grpc.credentials.createFromGoogleCredential(authClient) + ); + + console.log('Loading speech service...'); + var stub = new speechProto.Speech('speech.googleapis.com', credentials); + return callback(null, stub); + }); +} +// [END authenticating] + +// [START construct_request] +function getAudioFile (inputFile, callback) { + fs.readFile(inputFile, function (err, audioFile) { + if (err) { + return callback(err); + } + console.log('Got audio file!'); + return callback(null, audioFile); + }); +} +// [END construct_request] + +function main (inputFile, callback) { + var audioFile; + + async.waterfall([ + function (cb) { + getAudioFile(inputFile, cb); + }, + function (_audioFile, cb) { + audioFile = _audioFile; + getSpeechService(cb); + }, + // [START send_request] + function sendRequest (speechService, cb) { + console.log('Analyzing speech...'); + var responses = []; + var call = speechService.recognize(); + + // Listen for various responses + call.on('error', cb); + call.on('data', function (recognizeResponse) { + if (recognizeResponse) { + responses.push(recognizeResponse); + } + }); + call.on('end', function () { + cb(null, responses); + }); + + // Write the initial recognize reqeust + call.write(new speechProto.RecognizeRequest({ + initialRequest: new speechProto.InitialRecognizeRequest({ + encoding: 'LINEAR16', + sampleRate: 16000, + interimResults: false, + continuous: false, + enableEndpointerEvents: false + }) + })); + + // Write an audio request + call.write(new speechProto.RecognizeRequest({ + audioRequest: new speechProto.AudioRequest({ + content: audioFile + }) + })); + + // Signal that we're done writing + call.end(); + } + // [END send_request] + ], callback); +} + +// [START run_application] +if (module === require.main) { + if (process.argv.length < 3) { + console.log('Usage: node recognize_streaming '); + process.exit(); + } + var inputFile = process.argv[2]; + main(inputFile, console.log); +} +// [END run_application] + +exports.main = main; diff --git a/test/functions/sendgrid.test.js b/test/functions/sendgrid.test.js index 9c3b84cf38..470e5013b3 100644 --- a/test/functions/sendgrid.test.js +++ b/test/functions/sendgrid.test.js @@ -175,7 +175,7 @@ function getMockContext () { }; } -describe('functions:pubsub', function () { +describe('functions:sendgrid', function () { it('Send fails if not a POST request', function () { var expectedMsg = 'Only POST requests are accepted'; var mocks = getMocks(); @@ -566,7 +566,9 @@ describe('functions:pubsub', function () { bucket: 'event-bucket', name: name }); - + sendgridSample.mocks.job.on('error', function (err) { + assert.equal(err, error); + }); setTimeout(function () { sendgridSample.mocks.job.emit('error', error); }, 10); diff --git a/test/speech/recognize_streaming.test.js b/test/speech/recognize_streaming.test.js new file mode 100644 index 0000000000..f3dff00f52 --- /dev/null +++ b/test/speech/recognize_streaming.test.js @@ -0,0 +1,35 @@ +// Copyright 2016, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var path = require('path'); +var recognizeExample = require('../../speech/recognize_streaming'); + +describe('speech:recognize_streaming', function () { + it('should list entries', function (done) { + recognizeExample.main( + path.join(__dirname, '../../speech/resources/audio.raw'), + function (err, results) { + assert(!err); + assert(results); + assert(results.length === 1); + assert(results[0].results); + assert(console.log.calledWith('Got audio file!')); + assert(console.log.calledWith('Loading speech service...')); + assert(console.log.calledWith('Analyzing speech...')); + done(); + } + ); + }); +});