Skip to content

Instantly share code, notes, and snippets.

@phsultan
Last active August 2, 2023 12:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save phsultan/3b38a508072d83e374cbbbcf13485f1c to your computer and use it in GitHub Desktop.
Save phsultan/3b38a508072d83e374cbbbcf13485f1c to your computer and use it in GitHub Desktop.
Google Speech Recognition with API key + gRPC
/**
* Make sure you're not already authenticated with gRPC, on MacOS you need
* to ensure the GOOGLE_APPLICATION_CREDENTIALS environment variable is not
* set : `unset GOOGLE_APPLICATION_CREDENTIALS`
*
* @google-cloud/speech and google-gax are used to load the necessary .proto files
*
* I tried to add the 'key' to the request itself, or as a metadata with the request
* and always getting the following error from gRPC :
* Error: 7 PERMISSION_DENIED: The request is missing a valid API key.
*/
var PROTO_PATH = __dirname + '/node_modules/\@google-cloud/speech/protos/google/cloud/speech/v1/cloud_speech.proto';
const grpc = require('grpc');
const fs = require('fs');
const merge = require('lodash.merge');
const gax = require('google-gax');
const path = require('path');
const API_KEY = 'INSERT YOUR API KEY HERE';
const fileName = './audio.raw';
const metadata = new grpc.Metadata();
metadata.add('x-goog-api-key', API_KEY);
// Load the applicable protos.
var protos = merge(
{},
gax.grpc().loadProto(
path.join(__dirname, 'node_modules', '\@google-cloud', 'speech', 'protos'),
'google/cloud/speech/v1/cloud_speech.proto'
)
);
// Reads a local audio file and converts it to base64
const file = fs.readFileSync(fileName);
const audioBytes = file.toString('base64');
// The audio file's encoding, sample rate in hertz, and BCP-47 language code
const audio = {
content: audioBytes,
};
const config = {
encoding: 'LINEAR16',
sampleRateHertz: 16000,
languageCode: 'en-US',
};
const request = {
audio: audio,
config: config,
key: API_KEY
};
const client = new protos.google.cloud.speech.v1.Speech('speech.googleapis.com:443', grpc.credentials.createSsl());
client.Recognize(request,
metadata,
function(err, response) {
if (err) {
console.log("ERR :", err);
return;
}
console.log("RESPONSE :", response);
});
@long1eu
Copy link

long1eu commented May 14, 2020

Did you found a solution?

@phsultan
Copy link
Author

No, I gave up trying to make this work with an API key and used a service account's JSON file instead to authenticate.

@long1eu
Copy link

long1eu commented May 14, 2020

I managed to make it work. The metadata key is x-goog-api-key.

@phsultan
Copy link
Author

Thanks a lot for reporting back ! Substituting metadata.add('key', API_KEY); with metadata.add('x-goog-api-key', API_KEY); makes it work then, right ?

@long1eu
Copy link

long1eu commented May 14, 2020 via email

@phsultan
Copy link
Author

Updated, thanks again @long1eu !

@long1eu
Copy link

long1eu commented May 14, 2020

😁

@phsultan
Copy link
Author

Not sure the diff to protos is still neeeded in fact :

-    option (google.api.http) = { post: "/v1/speech:recognize" body: "*" };
+    option (google.api.http) = { post: "/v1/speech:recognize" };

From your testing, do you think it is ?

@long1eu
Copy link

long1eu commented May 14, 2020 via email

@phsultan
Copy link
Author

👍

@Dizuite
Copy link

Dizuite commented Mar 16, 2021

Hello, I tried this code and have the following error : ERROR gax.grpc is not a function

I'm using this npm packages for this :

  • @google-cloud/speech
  • google-gax
  • lodash.merge
  • grpc

Here is my code :

const gcsUri = 'gs://my-bucket/audio.raw'
const encoding = 'Encoding of the audio file, e.g. LINEAR16'
const sampleRateHertz = 16000
const languageCode = 'BCP-47 language code, e.g. en-US'

metadata.add('x-goog-api-key', 'HERE_IS_MY_API_KEY')
var PROTO_PATH = __dirname + '/node_modules/\@google-cloud/speech/build/protos/google/cloud/speech/v1/cloud_speech.proto'

var protos = merge(
  {},
  gax.grpc().loadProto(
    path.join(__dirname, 'node_modules', '\@google-cloud', 'build', 'speech', 'protos'),
    'google/cloud/speech/v1/cloud_speech.proto'
  )
)

const client = new protos.google.cloud.speech.v1.Speech('speech.googleapis.com:443', grpc.credentials.createSsl())

const config = {
  encoding: encoding,
  sampleRateHertz: sampleRateHertz,
  languageCode: languageCode
}

const audio = {
  uri: gcsUri
}

const request = {
  config: config,
  audio: audio
}

const [operation] = await client.longRunningRecognize(request)

const [response] = await operation.promise()

const transcription = response.results.map(result => result.alternatives[0].transcript).join('\n')

console.log(transcription)

As you see I'm just trying to make working the documentation example of speech-to-text without service account and with a simple API key instead.

You can also see I modified the path to the proto file, adding the build folder I have in my structure (original from npm package)

Thank you for your help !

@phsultan
Copy link
Author

Hi @Dizuite,

Have you installed the google-gax library (npm install google-gax), and added it to your code (const gax = require('google-gax');) ?

@Dizuite
Copy link

Dizuite commented Mar 17, 2021

Hello @phsultan,

Thank you for your answer, yes I have it in my code and its initialized

const speech = require('@google-cloud/speech')
const grpc = require('grpc')
const metadata = new grpc.Metadata()
const merge = require('lodash.merge')
const gax = require('google-gax')

module.exports = {
  path: '/api',
  handler: app
}

Here is the google-gax line in my package.json dependencies

    "dependencies": {
        "google-gax": "^2.11.2",

Have a nice day !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment