Search code examples
javagoogle-cloud-platformspeech-recognitionjava-audio

Define GOOGLE_APPLICATION_CREDENTIALS for google-cloud-speech , Java Desktop Application


I am completely new using google-cloud-java.

Trying to do some Speech Recognition using the google-cloud-speech .

I have written the below code , but there is a problem , i don't know how to specify the credentials so i get the below error, no clue how to do it and searching the web 2 hours now :

java.io.IOException: The Application Default Credentials are not available. They
 are available if running in Google Compute Engine. Otherwise, the environment v
ariable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defini
ng the credentials. See https://developers.google.com/accounts/docs/application-
default-credentials for more information.

Send audio from Microphone to Google Servers and return Text

package googleSpeech;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.TargetDataLine;

import com.google.api.gax.rpc.ClientStream;
import com.google.api.gax.rpc.ResponseObserver;
import com.google.api.gax.rpc.StreamController;
import com.google.cloud.speech.v1.RecognitionConfig;
import com.google.cloud.speech.v1.SpeechClient;
import com.google.cloud.speech.v1.StreamingRecognitionConfig;
import com.google.cloud.speech.v1.StreamingRecognizeRequest;
import com.google.cloud.speech.v1.StreamingRecognizeResponse;
import com.google.protobuf.ByteString;

public class GoogleSpeechTest {

    public GoogleSpeechTest() {

        //Set credentials?

        //Target data line
        TargetDataLine microphone;
        AudioInputStream audio = null;

        //Check if Microphone is Supported
        checkMicrophoneAvailability();


        //Capture Microphone Audio Data
        try {

            // Signed PCM AudioFormat with 16kHz, 16 bit sample size, mono
            AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);

            //Check if Microphone is Supported
            if (!AudioSystem.isLineSupported(info)) {
                System.out.println("Microphone is not available");
                System.exit(0);
            }

            //Get the target data line
            microphone = (TargetDataLine) AudioSystem.getLine(info);
            microphone.open(format);
            microphone.start();

            //Audio Input Stream
            audio = new AudioInputStream(microphone);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        //Send audio from Microphone to Google Servers and return Text
        try (SpeechClient client = SpeechClient.create()) {

            ResponseObserver<StreamingRecognizeResponse> responseObserver = new ResponseObserver<StreamingRecognizeResponse>() {

                public void onStart(StreamController controller) {
                    // do nothing
                }

                public void onResponse(StreamingRecognizeResponse response) {
                    System.out.println(response);
                }

                public void onComplete() {
                }

                public void onError(Throwable t) {
                    System.out.println(t);
                }
            };

            ClientStream<StreamingRecognizeRequest> clientStream = client.streamingRecognizeCallable().splitCall(responseObserver);

            RecognitionConfig recConfig = RecognitionConfig.newBuilder().setEncoding(RecognitionConfig.AudioEncoding.LINEAR16).setLanguageCode("en-US").setSampleRateHertz(16000)
                    .build();
            StreamingRecognitionConfig config = StreamingRecognitionConfig.newBuilder().setConfig(recConfig).build();

            StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder().setStreamingConfig(config).build(); // The first request in a streaming call has to be a config

            clientStream.send(request);

            while (true) {
                byte[] data = new byte[10];
                try {
                    audio.read(data);
                } catch (IOException e) {
                    System.out.println(e);
                }
                request = StreamingRecognizeRequest.newBuilder().setAudioContent(ByteString.copyFrom(data)).build();
                clientStream.send(request);
            }
        } catch (Exception e) {
            System.out.println(e);
        }

    }

    /**
     * Checks if the Microphone is available
     */
    public static void checkMicrophoneAvailability() {
        enumerateMicrophones().forEach((string , info) -> {
            System.out.println("Name :" + string);
        });
    }

    /**
     * Generates a hashmap to simplify the microphone selection process. The keyset is the name of the audio device's Mixer The value is the first
     * lineInfo from that Mixer.
     * 
     * @author Aaron Gokaslan (Skylion)
     * @return The generated hashmap
     */
    public static HashMap<String,Line.Info> enumerateMicrophones() {
        HashMap<String,Line.Info> out = new HashMap<String,Line.Info>();
        Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo();
        for (Mixer.Info info : mixerInfos) {
            Mixer m = AudioSystem.getMixer(info);
            Line.Info[] lineInfos = m.getTargetLineInfo();
            if (lineInfos.length >= 1 && lineInfos[0].getLineClass().equals(TargetDataLine.class))//Only adds to hashmap if it is audio input device
                out.put(info.getName(), lineInfos[0]);//Please enjoy my pun
        }
        return out;
    }

    public static void main(String[] args) {
        new GoogleSpeechTest();
    }

}

Following the given answers till now

My credentials.json looks like and i am getting the error:

{
    "installed": {
        "client_id": "",
        "project_id": "",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://accounts.google.com/o/oauth2/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "",
        "redirect_uris": [
            "urn:ietf:wg:oauth:2.0:oob",
            "http://localhost"
        ]
    }
}

Error :

java.io.IOException: Error reading credential file from environment variable GOO
GLE_APPLICATION_CREDENTIALS, value 'D:/GOXR3PLUS STUDIO/XR3IA/creds.json': Error
 reading credentials from stream, 'type' field not specified.

Update 3

Fixed the error following this link -> https://github.com/Triple-T/gradle-play-publisher/issues/141


Solution

  • Your credentials file look like this:

    Credentials Assuming you use Eclipse, Follow these steps

    First step

    first step

    Second Step

    second step

    Another way to load the file inside Java but please use at your own risk

    public class SetEnv {
    
        public static void setEnv(Map<String, String> newenv)
                throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
            try {
                Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
                Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
                theEnvironmentField.setAccessible(true);
                Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
                env.putAll(newenv);
                Field theCaseInsensitiveEnvironmentField = processEnvironmentClass
                        .getDeclaredField("theCaseInsensitiveEnvironment");
                theCaseInsensitiveEnvironmentField.setAccessible(true);
                Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
                cienv.putAll(newenv);
            } catch (NoSuchFieldException e) {
                Class[] classes = Collections.class.getDeclaredClasses();
                Map<String, String> env = System.getenv();
                for (Class cl : classes) {
                    if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
                        Field field = cl.getDeclaredField("m");
                        field.setAccessible(true);
                        Object obj = field.get(env);
                        Map<String, String> map = (Map<String, String>) obj;
                        map.clear();
                        map.putAll(newenv);
                    }
                }
            }
        }
    }
    

    and Call it like this:

    Map<String, String> google = new HashMap<>();
    google.put("GOOGLE_APPLICATION_CREDENTIALS",
            new ClassPathResource("google_credentials.json").getURI().getPath());
    SetEnv.setEnv(google);
    

    For your last error. The problem was because your generated file is invalid. You need to create a new valid one.

    From the API Manager, just create select "Create credentials" > "Service Account key" and generate a new key for the Service that is associated to your Google Play account.