我正在尝试为我的Android应用程序使用Google Cloud Platform的语音转文本API。我已经通过了一个录制的音频文件以转换为文本。 我无法解决被描述为“ 的应用程序默认凭据”的IOException。如果在Google Compute Engine中运行,则它们是可用的。否则,必须定义环境变量GOOGLE_APPLICATION_CREDENTIALS指向定义凭据的文件。有关更多信息,请参见https://developers.google.com/accounts/docs/application-default-credentials。”
我已经创建了一个服务帐户,启用了特定的API,创建了一个帐户密钥(cred.json)。 将环境变量“ GOOGLE_APPLICATION_CREDENTIALS”设置为文件的路径(上面的cred.json)。这是在Mac上的.bash_profile文件中完成的。
这是问题所在: 当我检查环境。使用
从终端获取变量回显$ GOOGLE_APPLICATION_CREDENTIALS
结果是cred.json文件的[路径]
但是,如果我尝试检查“ GOOGLE_APPLICATION_CREDENTIALS”,则在为该应用进行调试时,它显示为空。我使用
进行了检查Log.d("@sttenv", System.getenv("GOOGLE_APPLICATION_CREDENTIALS"));
这就是为什么我得到上面提到的IOException的原因。该行引发IOException。
SpeechClient speechClient = SpeechClient.create();
SpeechClient(它是代码本身的开始)给出了IOException。
try {
SpeechClient speechClient = SpeechClient.create();
// Reads the audio file into memory
Path path = Paths.get(tempFileName);
byte[] data = Files.readAllBytes(path);
ByteString audioBytes = ByteString.copyFrom(data);
// Builds the sync recognize request
RecognitionConfig config = RecognitionConfig.newBuilder()
.setEncoding(AudioEncoding.LINEAR16)
.setSampleRateHertz(44100)
.setLanguageCode("en-US")
.build();
RecognitionAudio audio = RecognitionAudio.newBuilder()
.setContent(audioBytes)
.build();
// Performs speech recognition on the audio file
RecognizeResponse response = speechClient.recognize(config, audio);
List<SpeechRecognitionResult> results = response.getResultsList();
for (SpeechRecognitionResult result : results) {
// There can be several alternative transcripts for a given chunk of speech. Just use the
// first (most likely) one here.
SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0);
//System.out.printf("Transcription: %s%n", alternative.getTranscript());
log.debug("Transcription: %s%n", alternative.getTranscript());
}
}
catch (IOException e){
e.printStackTrace();
}
我该如何解决?我尝试设置环境。来自终端的变量,无用。 我也想知道,如果我们将此应用程序安装在Android手机中(而不是在模拟器上),是否需要cred.json文件出现在手机本身中?因为cred.josn(帐户密钥)在我的Mac上。我正在尝试通过Android手机访问API?因此,我应该将cred.json保存在手机上,并提供给env的路径。变量?
答案 0 :(得分:0)
GOOGLE_APPLICATION_CREDENTIALS是一个编译时间变量。 您会注意到build.gradle中有一个任务,可以将凭证从变量指向的位置复制到原始目录中的credential.json文件:
task copySecretKey(type: Copy) {
def File secretKey = file "$System.env.GOOGLE_APPLICATION_CREDENTIALS"
from secretKey.getParent()
include secretKey.getName()
into 'src/main/res/raw'
rename secretKey.getName(), "credential.json"
}
然后应使用代码对这个文件进行寻址,以产生用于API服务的访问令牌:
private class AccessTokenTask extends AsyncTask<Void, Void, AccessToken> {
@Override
protected AccessToken doInBackground(Void... voids) {
final SharedPreferences prefs =
getSharedPreferences(PREFS, Context.MODE_PRIVATE);
String tokenValue = prefs.getString(PREF_ACCESS_TOKEN_VALUE, null);
long expirationTime = prefs.getLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, -1);
// Check if the current token is still valid for a while
if (tokenValue != null && expirationTime > 0) {
if (expirationTime
> System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION_TOLERANCE) {
return new AccessToken(tokenValue, new Date(expirationTime));
}
}
// ***** WARNING *****
// In this sample, we load the credential from a JSON file stored in a raw resource
// folder of this client app. You should never do this in your app. Instead, store
// the file in your server and obtain an access token from there.
// *******************
final InputStream stream = getResources().openRawResource(R.raw.credential);
try {
final GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
.createScoped(SCOPE);
final AccessToken token = credentials.refreshAccessToken();
prefs.edit()
.putString(PREF_ACCESS_TOKEN_VALUE, token.getTokenValue())
.putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME,
token.getExpirationTime().getTime())
.apply();
return token;
} catch (IOException e) {
Log.e(TAG, "Failed to obtain access token.", e);
}
return null;
}
@Override
protected void onPostExecute(AccessToken accessToken) {
mAccessTokenTask = null;
final ManagedChannel channel = new OkHttpChannelProvider()
.builderForAddress(HOSTNAME, PORT)
.nameResolverFactory(new DnsNameResolverProvider())
.intercept(new GoogleCredentialsInterceptor(new GoogleCredentials(accessToken)
.createScoped(SCOPE)))
.build();
mApi = SpeechGrpc.newStub(channel);
// Schedule access token refresh before it expires
if (mHandler != null) {
mHandler.postDelayed(mFetchAccessTokenRunnable,
Math.max(accessToken.getExpirationTime().getTime()
- System.currentTimeMillis()
- ACCESS_TOKEN_FETCH_MARGIN, ACCESS_TOKEN_EXPIRATION_TOLERANCE));
}
}
}