GCS Speech-To-Text API returns ERROR 7 PERMISSION_DENIED

36 Views Asked by At

The below NodeJS service is calling two GCS services: Cloud Text-to-Speech API (TTS) Cloud Speech-to-Text API (STT)

However, while using the same json key file for both, only the TTS is working. The STT call returns the following error: Error: 7 PERMISSION_DENIED: The caller does not have permission

require('dotenv').config();

const fs = require('fs');
const express = require('express');
const bodyParser = require('body-parser');
const { TextToSpeechClient } = require('@google-cloud/text-to-speech');
const { SpeechClient } = require('@google-cloud/speech');

const app = express();
const port = 3005;

const credentialsPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
console.log('credentialsPath: ', credentialsPath);
const credentials = JSON.parse(fs.readFileSync(credentialsPath, 'utf8'));

//TTS
const client = new TextToSpeechClient({
    credentials: {
        client_email: credentials.client_email,
        private_key: credentials.private_key,
    },
});

//STT
const speechClient = new SpeechClient({
    credentials: {
        client_email: credentials.client_email,
        private_key: credentials.private_key,
    },
});

const LONG_RECORDING_THRESHOLD_MS = 59000; //Up to 1 min - use the Google's STT recognize method

app.use(bodyParser.json());

app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
});

/* TEXT-TO-SPEECH */
app.post('/synthesize', (req, res) => {
    console.log('Received request: ', req.body);
    const text = req.body.text;
    const voiceName = req.body.voice;
    const voice = {
        languageCode: 'en-US',
        name: voiceName,
    } || {
        languageCode: 'en-US', //not needed if name is specified
        name:'en-US-Standard-B', //See voices here: https://cloud.google.com/text-to-speech/docs/voices
        //ssmlGender:'MALE' //NEUTRAL / FEMALE - not needed if name is specified
    };
    const speed = req.body.speed || 1.0;

    const request = {
        input: { text: text },
        voice: voice,
        audioConfig: {
            audioEncoding: 'MP3',
            speakingRate: speed
        }
    };

    client.synthesizeSpeech(request)
        .then(([response]) => {
            //console.log('*** Response: ', response);
            res.set('Content-Type', 'audio/mp3');
            res.send(response.audioContent);
        })
        .catch(error => {
            console.log('TTS ERROR: ', error);
            res.status(500).send({ error: error.message });
        });
});



/* SPEECH-To-TEXT */
app.post('/transcribe', (req, res) => {
    const audio = req.body.audio;
    const duration = req.body.duration; // in milliseconds
    const encoding = 'LINEAR16';
    const sampleRateHertz = 16000;
    const languageCode = 'en-US';

    const request = {
        audio: { content: audio },
        config: {
            encoding: encoding,
            sampleRateHertz: sampleRateHertz,
            languageCode: languageCode,
        },
    };

    // Check audio length to decide which method to use
    if (duration <= LONG_RECORDING_THRESHOLD_MS) {
        speechClient.recognize(request)
            .then(handleResponse)
            .catch(handleError);
    } else {
        speechClient.longRunningRecognize(request)
            .then(data => {
                const operation = data[0];
                return operation.promise();
            })
            .then(handleResponse)
            .catch(handleError);
    }

    function handleResponse([response]) {
        const transcription = response.results
            .map(result => result.alternatives[0].transcript)
            .join('\n');
        res.send({ transcription: transcription });
    }

    function handleError(error) {
        console.log('STT ERROR: ', error);
        res.status(500).send({ error: error.message });
    }
});


app.listen(port, () => {
    console.log(`Server started on http://localhost:${port}`);
});

In GCS console, I have both API services enabled and associated with the project with the same service account. When I go to the Enabled APIs and Services section, I see both services, and when clicking on each of them, under the Credentials tab I can see the same (and only) service account I have, for which the JSON key file was created and referenced in the NodeJS file.

This is a fresh GCS account and project, no Organization, with only one service account created. When I view the Permissions for this service, I see one Principal with the Owner role. Hovering over the 'Edit' pencil, I see a tooltip: "Role cannot be edited as it is inherited from another resource".

I see no entries in the GCS log explorer.

What am I missing, please?

0

There are 0 best solutions below