最近项目需要接入实时语音,然后就是接入的腾讯的Gvoice语音。
http://gcloud.qq.com/document/59268d64ff93679a05ef8271
其实GVoice接入很简单把官方的demo下载,然后把APPID(gameID) 和 APPkey 替换,代码直接搬过来用就行了。
1. 在这里值得一说的是,在接入语音遇到的问题,一个是测试的时候语音有回音,只需要把两台设备离远点就没有了。
2.在GVoice开启Mic的时候可能导致程序崩溃,是因为设备没有开启权限。解决办法直接做一个mic的权限判断,如果没有开启权限就不要去调用开启mic的方法。
3.在实力化GVoice的时候需要传入一个openID,最开始我是用的登录的token,然后发现在加入房间的时候会报错,我估计是因为token的字符太长了,然后我换成用户ID就好了。
这个是我自己封装的处理实时语音的类
#import <UIKit/UIKit.h>
#import "GVoice.h"
@interface GVoiceManager : UIViewController
+ (GVoiceManager *) shareManger;
/** 第三方初始化 必须初始化*/
- (void) GVoiceinite;
/** 加入房间*/
- (void) joinRoom:(NSString *)roomID;
/** 开始发语音,结束发语音*/
- (void) openMic:(BOOL)isopen;
/** 开启声音,关闭声音*/
- (void) openSpeaker:(BOOL) isopen;
/** 退出房间 */
- (void) quitRoom;
.m文件
#import "GVoiceManager.h" #import "Tool.h" #import "FaceAlertTool.h" #import "UserInfoManager.h" #import <AVFoundation/AVFoundation.h> @interface GVoiceManager ()<GVGCloudVoiceDelegate> @property (strong, nonatomic) NSTimer *pollTimer; @property (nonatomic,strong) NSString *roomID; @end @implementation GVoiceManager + (GVoiceManager *) shareManger{ static GVoiceManager *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[GVoiceManager alloc] init]; }); return instance; } - (void) GVoiceinite{ // NSString *openID = [[NSUserDefaults standardUserDefaults] valueForKey:@"access_token"]; [[GVGCloudVoice sharedInstance] setAppInfo:GVoice_appid withKey:GVoice_secert andOpenID:[[UserInfoManager managerUserInfo].userID cStringUsingEncoding:NSUTF8StringEncoding]]; [[GVGCloudVoice sharedInstance] initEngine]; [[GVGCloudVoice sharedInstance] setServerInfo:GVoice_server]; } /** 加入房间*/ - (void) joinRoom:(NSString *)roomID{ self.roomID = roomID; [GVGCloudVoice sharedInstance].delegate = self; [[GVGCloudVoice sharedInstance] setMode:RealTime]; [[NSUserDefaults standardUserDefaults] setValue:roomID forKey:GVoice_roomID]; [[NSUserDefaults standardUserDefaults] synchronize]; enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] joinTeamRoom:[roomID cStringUsingEncoding:NSUTF8StringEncoding] timeout:18000]; // enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] joinNationalRoom:[roomID cStringUsingEncoding:NSUTF8StringEncoding] role:Anchor timeout:18000]; NSLog(@"Voice加入房间res == %@",@(err)); _pollTimer = [NSTimer scheduledTimerWithTimeInterval:1.000/15 repeats:YES block:^(NSTimer * _Nonnull timer) { [[GVGCloudVoice sharedInstance] poll]; }]; } /** 开始发语音,结束发语音*/ - (void) openMic:(BOOL)isopen{ NSInteger flag = [self checkMic]; if(flag != 2){ [self authoMic]; return; } if (isopen) { enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] openMic]; NSLog(@"GVoice 开启Mic res == %@",@(err)); } else { enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] closeMic]; NSLog(@"GVoice 关闭Mic res == %@",@(err)); } } /** 开启声音,关闭声音*/ - (void) openSpeaker:(BOOL) isopen{ //首先的判断mic有没有权限 [self openMic:isopen]; if (isopen) { enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] openSpeaker]; NSLog(@"GVoice 开启Speaker res == %@",@(err)); } else { enum GCloudVoiceErrno err = [[GVGCloudVoice sharedInstance] closeSpeaker]; NSLog(@"GVoice 关闭Speaker res == %@",@(err)); } } /** 退出房间 */ - (void) quitRoom{ [[GVGCloudVoice sharedInstance] quitRoom:[[[NSUserDefaults standardUserDefaults] valueForKey:GVoice_roomID] cStringUsingEncoding:NSUTF8StringEncoding] timeout:18000]; } //MARK:--------------------提示-------------// #pragma mark delegate - (void) onJoinRoom:(enum GCloudVoiceCompleteCode) code withRoomName: (const char * _Nullable)roomName andMemberID:(int) memberID { NSString *msg; if (GV_ON_JOINROOM_SUCC == code) {//加入房间回调可自己实现 if(self.callbackGetInRoom)self.callbackGetInRoom(YES); msg = [NSString stringWithFormat:@"Join Room Success"]; } else { if(self.callbackGetInRoom)self.callbackGetInRoom(NO); msg = [NSString stringWithFormat:@"加入语音房间失败 with code: %d", code]; [FaceAlertTool svpShowInfo:msg]; } } - (void) onStatusUpdate:(enum GCloudVoiceCompleteCode) status withRoomName: (const char * _Nullable)roomName andMemberID:(int) memberID { } - (void) onQuitRoom:(enum GCloudVoiceCompleteCode) code withRoomName: (const char * _Nullable)roomName { [_pollTimer invalidate]; } - (void) onMemberVoice: (const unsigned int * _Nullable)members withCount: (int) count { for (int i=0; i<count; i++) { NSLog(@"Member %d status %d", *((int*)members+2*i), *((int *)members+2*i+1)); } } - (void) onUploadFile: (enum GCloudVoiceCompleteCode) code withFilePath: (const char * _Nullable)filePath andFileID:(const char * _Nullable)fileID { } - (void) onDownloadFile: (enum GCloudVoiceCompleteCode) code withFilePath: (const char * _Nullable)filePath andFileID:(const char * _Nullable)fileID { } - (void) onPlayRecordedFile:(enum GCloudVoiceCompleteCode) code withFilePath: (const char * _Nullable)filePath { } - (void) onApplyMessageKey:(enum GCloudVoiceCompleteCode) code { } - (void) onSpeechToText:(enum GCloudVoiceCompleteCode) code withFileID:(const char * _Nullable)fileID andResult:( const char * _Nullable)result { } - (void) onRecording:(const unsigned char* _Nullable) pAudioData withLength: (unsigned int) nDataLength { } - (void) onStreamSpeechToText:(enum GCloudVoiceCompleteCode) code withError:(int) error andResult:(const char *_Nullable)result { } //MARK:-------------------判断mic权限-------------// - (NSInteger) checkMic{ AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; NSInteger flag=0; switch (authStatus) { case AVAuthorizationStatusNotDetermined: //没有询问是否开启麦克风 flag = 1; break; case AVAuthorizationStatusRestricted: //未授权,家长限制 flag = 0; break; case AVAuthorizationStatusDenied: //玩家未授权 flag = 0; break; case AVAuthorizationStatusAuthorized: //玩家授权 flag = 2; break; default: break; } return flag; }//MARK:--------------------打开micphone权限-------------//
- (void) authoMic{ [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) { if (granted){// 用户同意授权 }else {// 用户拒绝授权 [FaceAlertTool svpShowInfo:@"请前往设置->ubaby设置麦克风权限"]; } }]; }