Google 云语音 API iOS returns 401 未通过 Firebase 存储文件进行身份验证
Google Cloud Speech API iOS returns 401 UNAUTHENTICATED with Firebase Storage File
我正在尝试使用我的 iOS 应用程序中的 Google Cloud Speech Api 转录长文件(>1 分钟)。
为此,我执行以下操作:
1) 如文档中所写,我匿名向 firebase 验证用户
[[FIRAuth auth]
signInAnonymouslyWithCompletion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
// ...
if (!error){
self.user = user;
[self.user getTokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
if (!error) {
self.token = token;
[self uploadFile];
}
}];
}
}];
2) 然后我将我的文件上传到 Firebase 存储并获取 URI
- (void)uploadFile
{
FIRStorage * storage = [FIRStorage storage];
FIRStorageReference *storageRef = [storage reference];
FIRStorageReference *sonetRef = [storageRef child:@"transcribeTest/sonet130.mp3"];
NSData *sonet = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sonet130" ofType:@"mp3"]];
FIRStorageUploadTask *uploadTask = [sonetRef putData:sonet metadata:nil completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) {
if (error != nil) {
// Uh-oh, an error occurred!
} else {
// Metadata contains file metadata such as size, content-type, and download URL.
NSURL *downloadURL = metadata.downloadURL;
NSString *path = [NSString stringWithFormat:@"gs://%@/%@",metadata.bucket,metadata.path];
NSURL * gsURL = [NSURL URLWithString:path];//@"gs://%@",downloadURL.path]];
[self trnscribeFileAtURL:gsURL];
}
}];
[uploadTask resume];
}
3) 下一步应该是向 Google Cloud Speech API 发送 Asyncrecognize 请求。但是我收到 401 错误 ''。
-(void)trnscribeFileAtURL:(NSURL*)url
{
NSString *service = @"https:/speech.googleapis.com/v1beta1/speech:asyncrecognize";
service = [service stringByAppendingString:@"?key="];
service = [service stringByAppendingString:API_KEY];
NSData *audioData = [NSData dataWithContentsOfFile:[self soundFilePath]];
NSDictionary *configRequest = @{@"encoding":@"LINEAR16",
@"sampleRate":@(SAMPLE_RATE),
@"languageCode":@"en-UK",
@"maxAlternatives":@30};
NSDictionary *audioRequest = @{@"uri":url.absoluteString};
NSDictionary *requestDictionary = @{@"config":configRequest,
@"audio":audioRequest};
NSError *error;
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestDictionary
options:0
error:&error];
NSString *path = service;
NSURL *URL = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
// if your API key has a bundle ID restriction, specify the bundle ID like this:
[request addValue:[[NSBundle mainBundle] bundleIdentifier] forHTTPHeaderField:@"X-Ios-Bundle-Identifier"];
NSString *contentType = @"application/json";
[request addValue:contentType forHTTPHeaderField:@"Content-Type"];
[request addValue:[NSString stringWithFormat:@"Bearer %@",self.token] forHTTPHeaderField:@"Authorization"];
[request setHTTPBody:requestData];
[request setHTTPMethod:@"POST"];
NSURLSessionTask *task =
[[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(),
^{
NSString *stringResult = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
_textView.text = stringResult;
NSLog(@"RESULT: %@", stringResult);
});
}];
[task resume];
}
响应JSON:
2017-02-28 19:58:05.837337 Speech[8057:2054726] RESULT: {
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
看起来问题出在这行代码上:
[request addValue:[NSString stringWithFormat:@"Bearer %@",self.token] forHTTPHeaderField:@"Authorization"];
我正在尝试传递从 Firebase 匿名身份验证获得的令牌,但它不适合。我搜索了我无法找到如何为匿名用户获取正确凭据的方法。请帮忙。
简短的回答是您不能使用 Firebase Auth 令牌直接从客户端访问 Google API,例如 Speech 或 Vision。正如错误消息所说,这些 API 需要以下之一:
- Google OAuth 2.0(用户启动或通过服务帐户启动)
- 登录 cookie
在 the Speech docs on authentication 中查看更多信息。
执行此操作的最简单方法可能是使用类似 Cloud Functions 的方法并监听文件上传,然后处理音频,然后将其写回数据库。
什么API_KEY?
你没有提到它!
我正在尝试使用我的 iOS 应用程序中的 Google Cloud Speech Api 转录长文件(>1 分钟)。
为此,我执行以下操作:
1) 如文档中所写,我匿名向 firebase 验证用户
[[FIRAuth auth]
signInAnonymouslyWithCompletion:^(FIRUser *_Nullable user, NSError *_Nullable error) {
// ...
if (!error){
self.user = user;
[self.user getTokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) {
if (!error) {
self.token = token;
[self uploadFile];
}
}];
}
}];
2) 然后我将我的文件上传到 Firebase 存储并获取 URI
- (void)uploadFile
{
FIRStorage * storage = [FIRStorage storage];
FIRStorageReference *storageRef = [storage reference];
FIRStorageReference *sonetRef = [storageRef child:@"transcribeTest/sonet130.mp3"];
NSData *sonet = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sonet130" ofType:@"mp3"]];
FIRStorageUploadTask *uploadTask = [sonetRef putData:sonet metadata:nil completion:^(FIRStorageMetadata * _Nullable metadata, NSError * _Nullable error) {
if (error != nil) {
// Uh-oh, an error occurred!
} else {
// Metadata contains file metadata such as size, content-type, and download URL.
NSURL *downloadURL = metadata.downloadURL;
NSString *path = [NSString stringWithFormat:@"gs://%@/%@",metadata.bucket,metadata.path];
NSURL * gsURL = [NSURL URLWithString:path];//@"gs://%@",downloadURL.path]];
[self trnscribeFileAtURL:gsURL];
}
}];
[uploadTask resume];
}
3) 下一步应该是向 Google Cloud Speech API 发送 Asyncrecognize 请求。但是我收到 401 错误 ''。
-(void)trnscribeFileAtURL:(NSURL*)url
{
NSString *service = @"https:/speech.googleapis.com/v1beta1/speech:asyncrecognize";
service = [service stringByAppendingString:@"?key="];
service = [service stringByAppendingString:API_KEY];
NSData *audioData = [NSData dataWithContentsOfFile:[self soundFilePath]];
NSDictionary *configRequest = @{@"encoding":@"LINEAR16",
@"sampleRate":@(SAMPLE_RATE),
@"languageCode":@"en-UK",
@"maxAlternatives":@30};
NSDictionary *audioRequest = @{@"uri":url.absoluteString};
NSDictionary *requestDictionary = @{@"config":configRequest,
@"audio":audioRequest};
NSError *error;
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestDictionary
options:0
error:&error];
NSString *path = service;
NSURL *URL = [NSURL URLWithString:path];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
// if your API key has a bundle ID restriction, specify the bundle ID like this:
[request addValue:[[NSBundle mainBundle] bundleIdentifier] forHTTPHeaderField:@"X-Ios-Bundle-Identifier"];
NSString *contentType = @"application/json";
[request addValue:contentType forHTTPHeaderField:@"Content-Type"];
[request addValue:[NSString stringWithFormat:@"Bearer %@",self.token] forHTTPHeaderField:@"Authorization"];
[request setHTTPBody:requestData];
[request setHTTPMethod:@"POST"];
NSURLSessionTask *task =
[[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(),
^{
NSString *stringResult = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
_textView.text = stringResult;
NSLog(@"RESULT: %@", stringResult);
});
}];
[task resume];
}
响应JSON:
2017-02-28 19:58:05.837337 Speech[8057:2054726] RESULT: {
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
看起来问题出在这行代码上:
[request addValue:[NSString stringWithFormat:@"Bearer %@",self.token] forHTTPHeaderField:@"Authorization"];
我正在尝试传递从 Firebase 匿名身份验证获得的令牌,但它不适合。我搜索了我无法找到如何为匿名用户获取正确凭据的方法。请帮忙。
简短的回答是您不能使用 Firebase Auth 令牌直接从客户端访问 Google API,例如 Speech 或 Vision。正如错误消息所说,这些 API 需要以下之一:
- Google OAuth 2.0(用户启动或通过服务帐户启动)
- 登录 cookie
在 the Speech docs on authentication 中查看更多信息。
执行此操作的最简单方法可能是使用类似 Cloud Functions 的方法并监听文件上传,然后处理音频,然后将其写回数据库。
什么API_KEY?
你没有提到它!