最近项目需要接入实时语音,然后就是接入的腾讯的Gvoice语音。 接入流程请参照官网gcloud.qq.com/document/59… 其实GVoice接入很简单把官方的demo下载,然后把APPID(gameID) 和 APPkey 替换,代码直接搬过来用就行了。 在这里值得一说的是,在接入语音遇到的问题
- 测试时候语音有回音,只需要把两台设备离远点就没有了。
- 在GVoice开启Mic的时候可能导致程序崩溃,是因为设备没有开启权限。解决办法直接做一个mic的权限判断,如果没有开启权限就不要去调用开启mic的方法。
- 在实力化GVoice的时候需要传入一个openID,最开始我是用的登录的token,然后发现在加入房间的时候会报错,我估计是因为token的字符太长了,然后我换成用户ID就好了。
- 注意设置服务器[[GVGCloudVoice sharedInstance] setServerInfo:GVoice_server]; ###代码:
#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;
复制代码
实现:
#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设置麦克风权限"];
}
}];
}
复制代码