google gRPC在macOS中的简单使用

gRPC 官方文档中文版

1. 简述

A high-performance, open-source universal RPC framework

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持。

gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,使应用程序之间可以进行通信,而且也遵循service/client模型。在客户端调用service端提供的接口就像是调用本地函数一样,一般使用客户端快速能获取到服务器接口数据的时候,如:实时语音识别、翻译、语音合成等。

img

下面详解googleapis里的gRPC的使用

2. cocopods添加gRPC

  • ios-docs-samples 下载googleapis库
  • 找到并复制ios-docs-samples/speech-to-speech目录下的google文件夹和googleapis.podspec文件
  • 将上述两个文件复制到自己工程主目录
  • cd 到自己工程
  • pod install –verbose 或 pod update –verbose (过程较慢,需要翻墙)

3. 示例

客户端代码、不会服务器<可以自行研究>

google 官方API

3.1 语音识别

//  ZDASRService.h
#import <Foundation/Foundation.h>
#import <google/cloud/speech/v1p1beta1/CloudSpeech.pbobjc.h>

NS_ASSUME_NONNULL_BEGIN

typedef void (^SpeechRecognitionCompletionHandler)(BOOL done, StreamingRecognizeResponse *object, NSError *error);

@interface ZDASRService : NSObject

- (void)streamAudioData:(NSData *)audioData
           languageCode:(NSString *)languageCode
         withCompletion:(SpeechRecognitionCompletionHandler)completion;

- (void)stopStreaming;

- (BOOL)isStreaming;

@end
  
//  ZDASRService.m
NS_ASSUME_NONNULL_END
  
 #import "ZDASRService.h"
#import <GRPCClient/GRPCCall.h>
#import <RxLibrary/GRXBufferedPipe.h>
#import <ProtoRPC/ProtoRPC.h>
#import <google/cloud/speech/v1p1beta1/CloudSpeech.pbrpc.h>

@interface ZDASRService ()

@property (nonatomic, strong) Speech *client;
@property (nonatomic, strong) GRXBufferedPipe *writer;
@property (nonatomic, strong) GRPCProtoCall *call;

@property (nonatomic, assign) BOOL streaming;

@end

@implementation ZDASRService

- (id)init {
    self = [super init];
    if (self) {
        [self defaultSetting];
    }
    return self;
}

- (void)defaultSetting {
    
}

- (void)streamAudioData:(NSData *)audioData
           languageCode:(NSString *)languageCode
         withCompletion:(SpeechRecognitionCompletionHandler)completion {
    if (!_streaming) {
        _client = [[Speech alloc] initWithHost:[ZDDogAPIService shared].dogApis];
        _writer = [[GRXBufferedPipe alloc] init];
        _call = [_client RPCToStreamingRecognizeWithRequestsWriter:_writer eventHandler:^(BOOL done, StreamingRecognizeResponse * _Nullable response, NSError * _Nullable error) {
            completion(done, response, error);
        }];
        _call.requestHeaders[@"Authorization"] = [NSString stringWithFormat:@"Bearer %@", [[NSUserDefaults standardUserDefaults] valueForKey:kDeviceTokenKey]];
        _call.requestHeaders[@"appId"] = kAppId;
        _call.requestHeaders[@"userId"] = [[NSUserDefaults standardUserDefaults] valueForKey:kUserId];
        [_call start];
        _streaming = YES;
        
        RecognitionConfig *recognitionConfig = [RecognitionConfig message];
        recognitionConfig.encoding = RecognitionConfig_AudioEncoding_Linear16;
        recognitionConfig.sampleRateHertz = 16000;
        recognitionConfig.languageCode = languageCode;
        recognitionConfig.maxAlternatives = 30;
        recognitionConfig.enableAutomaticPunctuation = YES;
        recognitionConfig.audioChannelCount = 1;
        
        StreamingRecognitionConfig *streamingRecognitionConfig = [StreamingRecognitionConfig message];
        streamingRecognitionConfig.config = recognitionConfig;
        streamingRecognitionConfig.singleUtterance = NO;
        streamingRecognitionConfig.interimResults = YES;
        
        StreamingRecognizeRequest *streamingRecognizeRequest = [StreamingRecognizeRequest message];
        streamingRecognizeRequest.streamingConfig = streamingRecognitionConfig;
        [_writer writeValue:streamingRecognizeRequest];
    }
    StreamingRecognizeRequest *streamingRecognizeRequest = [StreamingRecognizeRequest message];
    streamingRecognizeRequest.audioContent = audioData;
    [_writer writeValue:streamingRecognizeRequest];
}

- (void)stopStreaming {
    if (!_streaming) {
        return;
    }
    StreamingRecognizeRequest *streamingRecognizeRequest = [StreamingRecognizeRequest message];
    streamingRecognizeRequest.audioContent = [NSData data];
    [_writer writeValue:streamingRecognizeRequest];
    [_writer finishWithError:nil];
    _streaming = NO;
}

- (BOOL)isStreaming {
    return _streaming;
}

@end

3.2 语音合成

//  ZDTTSService.h
#import <Foundation/Foundation.h>
#import "google/cloud/texttospeech/v1beta1/CloudTts.pbobjc.h"

NS_ASSUME_NONNULL_BEGIN

typedef void (^TTSRecognitionCompletionHandler)(NSData *__nullable data, NSString *__nullable error);

@interface ZDTTSService : NSObject

- (void)ttsRecognition:(NSString *)text
              language:(NSString *)language
     completionHandler:(TTSRecognitionCompletionHandler)handler;

@end

NS_ASSUME_NONNULL_END
  
//  ZDTTSService.m
#import "ZDTTSService.h"
#import <RxLibrary/GRXBufferedPipe.h>
#import <AVFoundation/AVFoundation.h>
#import <google/cloud/texttospeech/v1beta1/CloudTts.pbrpc.h>

@interface ZDTTSService ()

@property (nonatomic, strong) TextToSpeech *client;
@property (nonatomic, strong) GRXBufferedPipe *writer;
@property (nonatomic, strong) GRPCProtoCall *call;

@property (assign, nonatomic) BOOL mGoogleTimeout;

@end

@implementation ZDTTSService

- (id)init {
    self = [super init];
    if (self) {
        [self defaultSetting];
    }
    return self;
}

- (void)defaultSetting {
    self.mGoogleTimeout = NO;
}

- (void)ttsRecognition:(NSString *)text
              language:(nonnull NSString *)language
     completionHandler:(TTSRecognitionCompletionHandler)handler {
    NSArray *sIflyteks = @[@"zh-CN", @"zh-TW", @"zh-HK"];
    NSArray *sMicrosofts = @[@"ms-MY", @"bg-BG", @"sl-SI", @"he_IL"];
    if ([sIflyteks containsObject:language] || [sMicrosofts containsObject:language] || self.mGoogleTimeout) {
        [self ttsDogRecognition:text language:language completionHandler:handler];
    } else {
        [self ttsGoogleRecognition:text language:language completionHandler:handler];
    }
}
// google api合成
- (void)ttsGoogleRecognition:(NSString *)text
                    language:(NSString *)language
           completionHandler:(TTSRecognitionCompletionHandler)handler {
    text = [text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSMutableString *urlString = [NSMutableString stringWithString:[ZDDogAPIService shared].mGoogleUrl];
    [urlString appendFormat:@"&total=1"];
    [urlString appendFormat:@"&idx=0"];
    [urlString appendFormat:@"&textlen=%lu", (unsigned long)text.length];
    [urlString appendFormat:@"&q=%@", text];
    [urlString appendFormat:@"&tl=%@", language];
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:10.0];
    [request setHTTPMethod:@"GET"];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    if (error) {
                                                        if (error.code == -1001) {
                                                            self.mGoogleTimeout = YES;
                                                        }
                                                        handler(nil, error.localizedDescription);
                                                    } else {
                                                        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                        if (httpResponse.statusCode == 200) {
                                                            handler(data, @"");
                                                        }
                                                    }
                                                }];
    [dataTask resume];
}
// dog RPC
- (void)ttsDogRecognition:(NSString *)text
             language:(NSString *)language
        completionHandler:(TTSRecognitionCompletionHandler)handler {
    _client = [[TextToSpeech alloc] initWithHost:[ZDDogAPIService shared].dogApis];
    _writer = [[GRXBufferedPipe alloc] init];
        
    SynthesisInput *input = [[SynthesisInput alloc] init];
    input.text = text;

    VoiceSelectionParams *params = [[VoiceSelectionParams alloc] init];
    params.languageCode =  language;
    params.ssmlGender = SsmlVoiceGender_Female;
    
    AudioConfig *config = [[AudioConfig alloc] init];
    config.audioEncoding = AudioEncoding_Mp3;
    
    SynthesizeSpeechRequest *speechRequest = [[SynthesizeSpeechRequest alloc] init];
    speechRequest.audioConfig = config;
    speechRequest.input = input;
    speechRequest.voice = params;
    
    _call = [_client RPCToSynthesizeSpeechWithRequest:speechRequest handler:^(SynthesizeSpeechResponse * _Nullable response, NSError * _Nullable error) {
        handler(response.audioContent, error.localizedDescription);
    }];
    
    _call.requestHeaders[@"Authorization"] = [NSString stringWithFormat:@"Bearer %@", [[NSUserDefaults standardUserDefaults] valueForKey:kDeviceTokenKey]];
    _call.requestHeaders[@"appId"] = kAppId;
    [_call start];
}

@end

3.3 翻译

//  ZDTranslateService.h
#import <Foundation/Foundation.h>
#import <google/cloud/translate/v3beta1/TranslationService.pbobjc.h>

NS_ASSUME_NONNULL_BEGIN

typedef void (^TranslationCompletionHandler)(TranslateTextResponse *object, NSError *error);

@interface ZDTranslateService : NSObject

- (void)translateText:(NSString *)text
            sourceLan:(NSString *)sourceLan
            targetLan:(NSString *)targetLan
    completionHandler:(TranslationCompletionHandler)handler;

@end

NS_ASSUME_NONNULL_END
  
//  ZDTranslateService.m
#import "ZDTranslateService.h"
#import <google/cloud/translate/v3beta1/TranslationService.pbrpc.h>

@interface ZDTranslateService ()

@property (nonatomic, strong) TranslationService *client;
@property (nonatomic, strong) GRPCProtoCall *call;

@end

@implementation ZDTranslateService

- (id)init {
    self = [super init];
    if (self) {
        [self defaultSetting];
    }
    return self;
}

- (void)defaultSetting {
    
}

- (void)translateText:(NSString *)text
            sourceLan:(NSString *)sourceLan
            targetLan:(NSString *)targetLan
    completionHandler:(TranslationCompletionHandler)handler {
    _client = [[TranslationService alloc] initWithHost:[ZDDogAPIService shared].dogApis];
    TranslateTextRequest *translateRequest = [[TranslateTextRequest alloc] init];
    translateRequest.contentsArray = [NSMutableArray arrayWithArray:@[text]];
    translateRequest.mimeType = @"text/plain";
    translateRequest.sourceLanguageCode = sourceLan;
    translateRequest.targetLanguageCode = targetLan;
    
    _call = [_client RPCToTranslateTextWithRequest:translateRequest handler:^(TranslateTextResponse * _Nullable response, NSError * _Nullable error) {
        handler(response, error);
    }];
    _call.requestHeaders[@"Authorization"] = [NSString stringWithFormat:@"Bearer %@", [[NSUserDefaults standardUserDefaults] valueForKey:kDeviceTokenKey]];
    _call.requestHeaders[@"appId"] = kAppId;
    _call.requestHeaders[@"userId"] = [[NSUserDefaults standardUserDefaults] valueForKey:kUserId];
    [_call start];
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351