8

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

GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
  • The last message means, it successfully loads the `credentials` file but it is missing `type` field, look at an example of how it should look below. – ISlimani Jul 01 '18 at 23:15
  • @Dfor Tye Thanks i fixed the error following this link :) -> Fixed the error following this link -> https://github.com/Triple-T/gradle-play-publisher/issues/141 – GOXR3PLUS Jul 01 '18 at 23:20
  • I am gonna update my answer. Make it as valid please – ISlimani Jul 01 '18 at 23:20

2 Answers2

9

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.

ISlimani
  • 1,643
  • 14
  • 16
  • Updated my question based on your answer i am having a problem with the credentials , i am looking for an answer here https://github.com/Triple-T/gradle-play-publisher/issues/141 – GOXR3PLUS Jul 01 '18 at 23:15
  • The last message means, it successfully loads the `credentials` file but it is missing `type` field, look at an example of how it should look above. – ISlimani Jul 01 '18 at 23:16
  • You need to generate a file that looks exactly like the file above – ISlimani Jul 01 '18 at 23:17
  • Thanks i solved it , now i would like to make it platform independent with your method :) `setEnv` , i will accept your answer soon , need to do some testing . Love you :) – GOXR3PLUS Jul 01 '18 at 23:21
  • Not a problem. Just don't forget to make the answer valid for the others. – ISlimani Jul 01 '18 at 23:23
  • Love you :_) so much!! – GOXR3PLUS Jul 01 '18 at 23:25
  • I have a problem here , the .json will be inside the .jar file because the application is distributable https://github.com/goxr3plus/XR3Player , how can i get it from inside the .jar file .... i mean do i have to copy it from inside out ?... – GOXR3PLUS Jul 02 '18 at 00:22
2

I'm assuming you downloaded the credentials from the Google Cloud Console. They should be saved somewhere on your computer as a file.

You need to set the GOOGLE_APPLICATION_CREDENTIALS environment variable so that it points directly to that file. Specify a path to that file. For example, if the credentials are called creds.json in the folder above your current working directory, you can set the environment variable to ../creds.json. You can also specify an absolute path.

To actually set the environment variable, it's different per operating system. Here's a good post to help with that. If you're using Intellij, you can set it directly in the run configuration.

nareddyt
  • 1,016
  • 10
  • 20
  • Can i use something like `System.setProperty("GOOGLE_APPLICATION_CREDENTIALS", "creds.json");` ? Actually which json i should download ?The one in section `OAuth 2.0 client IDs` which i created ? – GOXR3PLUS Jul 01 '18 at 22:54
  • I am trying also with `GoogleCredentials credentials = GoogleCredentials.create(new AccessToken("access_token",Date));` Can you provide some Java code pliz.. – GOXR3PLUS Jul 01 '18 at 23:01