注:由于個人版本構建不同,所以備注代碼和方案不同!
第一.多方視頻(自己集成NIMSDK和注冊網易云信賬號)
0.導入頭文件 //多人視頻
#import <NIMSDK>
#import <NIMAVChat>
#import "UnityFunction.h"
1.注冊SDK(appKey 和 cerName根據自己賬號填寫,自己導入頭文件)
NSString *appKey = @"a543326452XXX285fd196b19524e0c55";
NSString *cerName = @"https://app.nXXXase.im/api";
[[NIMSDK sharedSDK] registerWithAppID:appKey cerName:cerName];
2.注冊網易云信服務器(token自己定義 和安卓統一,否則無法互通音視頻)(注冊和登錄方法是另行封裝的)
注: #define Password @"NIMSDK/NIMSDK_User_PassWord"
- (void)regist:(NSString*)account result:(LoginRegist)result {
NSDictionary *params =@{@"accid":account,
@"props":@"",
@"token":Password,
@"icon":@""};
[[NIMServerAPI sharedAPI] request:@"https://api.netease.im/nimserver/user/create.action" params:params completion:^(NSError *error, NSDictionary *resultDict) {
self.result = result;
if (error) {
_result(@"注冊失敗", error.code);
} else {
_result(@"注冊成功", 200);
}
}];
}
3.登錄(token自己定義 和安卓統一,否則無法互通音視頻)
- (void)login:(NSString*)account result:(LoginRegist)result {
[[[NIMSDK sharedSDK] loginManager] login:account token:Password completion:^(NSError *error) {
self.result = result;
if (error) {
_result(@"登錄失敗", error.code);
} else {
_result(@"登錄成功", 200);
// if (_userInfo) {
// _userInfo.userID =account;
// _userInfo->userPswd =Password;
}
// [_userInfo saveCurrentAccount];
}
}];
}
4.創建音視頻和代理,創建meeting
//音視頻相關
- (void)createVideoAndAudio {
NIMNetCallMeeting *meeting = [[NIMNetCallMeeting alloc] init];
meeting.name = _roomModel.number;
if (![[NIMSDK sharedSDK].loginManager isLogined]) {
NSLog(@"當前登錄用戶ID:%@",_currentUserID);
[[LoginOrRegist shareUserInfo]regist:_currentUserID result:^(NSString *message, NSInteger code) {
[[LoginOrRegist shareUserInfo] login:_currentUserID result:^(NSString *message, NSInteger code) {
if (code == 200) {
NSLog(@"登錄成功,進入房間");
[self joinNetCallWithRMeeting:meeting];
} else {
NSLog(@"登錄失敗原因%ld",(long)code);
}
}];
}];
} else {
NSLog(@"用戶已經登錄, 無需再登錄, 正加入房間");
[self joinNetCallWithRMeeting:meeting];
}
}
5.預約會議相關方法(注:UnityFunction方法是封裝的是傳給U3D的消息,可忽視)
- (void)reserveMeetingWithRoomId:(NSString *)roomId{
NIMNetCallMeeting *meeting = [[NIMNetCallMeeting alloc] init];
meeting.name = roomId;
meeting.type = NIMNetCallMediaTypeVideo;
meeting.ext = @"哈哈哈哈";
meeting.actor = NO;
[[NIMAVChatSDK sharedSDK].netCallManager reserveMeeting:meeting completion:^(NIMNetCallMeeting * _Nonnull meeting, NSError * _Nonnull error) {
if (!error) {
// [UnityFunction sendUnityMessage:0 function:UnityMessageCreateRoomResult error:meeting.name];
NSLog(@"預定成功 ,進入房間");
[self joinNetCallWithRMeeting:meeting];
} else {
if (error.code == 417) {
// [UnityFunction sendUnityMessage:417 function:UnityMessageCreateRoomResult error:@"該房間已存在"];
[self joinNetCallWithRMeeting:meeting];
} else {
// [UnityFunction sendUnityMessage:(int)error.code function:UnityMessageCreateRoomResult error:error.domain];
NSLog(@"預定房間失敗");
}
}
}];
}
6.加入會議相關方法(PermissionTool方法是獨自封裝的相機權限、麥克風權限等手動方法,可刪除不管)
- (void)joinNetCallWithRMeeting:(NIMNetCallMeeting *)rMeeting {
[PermissionTool getCamerasPermission:^(NSInteger authStatus) {
if (authStatus ==1) {
[PermissionTool getMicrophonePermission:^(NSInteger authStatus) {
if (authStatus == 1) {
NIMNetCallOption *callOption =[[NIMNetCallOption alloc]init];
// 發送視頻質量(SDK會處理 有可能無效)
callOption.preferredVideoQuality =NIMNetCallVideoQualityDefault;
// 禁止剪裁
callOption.disableVideoCropping =NO;
// 自動旋轉遠端畫面
callOption.autoRotateRemoteVideo =YES;
// 期望的視頻編碼器
callOption.preferredVideoEncoder =NIMNetCallVideoCodecDefault;
// 期望的視頻解碼器
callOption.preferredVideoDecoder =NIMNetCallVideoCodecDefault;
// 是否使用后置攝像頭
callOption.startWithBackCamera =NO;
// 啟用互動直播
callOption.enableBypassStreaming =YES;
// 互動直播推流地址
callOption.bypassStreamingUrl =nil;
// 是否在服務器錄制音頻
callOption.serverRecordAudio =YES;
callOption.autoDeactivateAudioSession = NO;
// 是否在服務器錄制視頻
callOption.serverRecordVideo =YES;
// 加入會議的類型->音頻/視頻
rMeeting.type =NIMNetCallMediaTypeVideo;
// 是否發送音視頻數據
rMeeting.actor = YES;
// 網路電話配置
rMeeting.option = callOption;
//進入房間聊天
[[NIMAVChatSDK sharedSDK].netCallManager joinMeeting:rMeeting completion:^(NIMNetCallMeeting * _Nonnull meeting, NSError * _Nonnull error) {
if (!error) {
NSLog(@"進入成功");
//默認關閉所有人視頻
[[NIMAVChatSDK sharedSDK].netCallManager setCameraDisable:YES];
[[NIMAVChatSDK sharedSDK].netCallManager setMute:YES];
} else {
NSLog(@"進入失敗");
[self reserveMeetingWithRoomId:_roomModel.number];
}
}];
} else {
NSLog(@"用戶拒絕訪問麥克風");
}
}];
} else {
NSLog(@"用戶拒絕訪問攝像頭");
}
}];
}
**注:終點標注兩個屬性 **
第一:callOption.autoDeactivateAudioSession = NO; 這個屬性是控制 “結束網絡通話時自動停止AudioSession” 用的;做游戲界面,由于需要進入主頁面有背景音樂,然后進入到游戲房間需要停止背景音樂,并在中途插入類似狼人殺的法官語音,退出后由于退出meeting會議,背景音樂消失,這個時候想讓主頁的背景音樂響起來就需要設置這個屬性為NO?。ㄎ业睦斫馐沁@個屬性控制了音頻相關控制設備,默認為占用狀態)
第二:rMeeting.actor = YES; meeting的這個actor屬性是設置旁觀者模式或者說是音視頻顯示主角;actor設置成YES的話,默認進入meeting后會自動對進入房間所有人進行拉流和推流,產生流量使用,并且打開所有人的攝像頭和麥克風,適用于雙人視頻;如果想做類似于輪到誰誰音視頻打開這種,需要默認設置actor為YES,并關閉攝像頭和麥克風
[[NIMAVChatSDK sharedSDK].netCallManager setCameraDisable:YES];
[[NIMAVChatSDK sharedSDK].netCallManager setMute:YES];
7.離開會議
- (void)MSUNetCallManagerLeaveMeeting {
NIMNetCallMeeting *meeting = [[NIMNetCallMeeting alloc] init];
meeting.name = _roomModel.number;
[[NIMAVChatSDK sharedSDK].netCallManager leaveMeeting:meeting];
}
8.代理方法(NIMNetCallManagerDelegate代理遵循)
// 遠程視頻圖層(屬性相關)
@property (nonatomic, strong) NTESGLView *videoView;
// 遠本地視頻View;
@property (nonatomic, weak) CALayer *localLayer;
/// 遠程視頻 (是控制遠程視頻流)
- (void)onRemoteYUVReady:(NSData *)yuvData width:(NSUInteger)width height:(NSUInteger)height from:(NSString *)user {
if (yuvData) {
_videoView.hidden = NO;
[_videoView render:yuvData width:width height:height];
} else {
_videoView.hidden =YES;
}
}
/// 本地視頻 (此處是控制本地視頻流)
- (void)onLocalPreviewReady:(CALayer *)layer {
[self isShowLocalPreviewPeady:NO aLayer:layer];
}
- (void)isShowLocalPreviewPeady:(BOOL)isShow aLayer:(CALayer*)layer {
if (!layer) {
layer =_localLayer;
}
layer.frame =CGRectMake(0, 0, WIDTH, HEIGHT);
_localLayer =layer;
_localLayer.hidden =!isShow;
[_videoView.layer addSublayer:_localLayer];
}
9.ijksdl (平心而論,此處這個是最坑爹的一個,無法言喻表達:呵呵噠?。?
ijksdl屬于IJKPlayer的不常用SDK的一部分,(對于這個,呵呵噠);IJKPlayer功能不敘述了,直播必須!集成這個ijksdl是云信中必有得,其中 NTESGLView 就是對 NTESIJKSDLGLView 的拉流封裝;
集成:1)導入 ijksdl文件夾(此處切記,必須將此文件夾放置工程下的第一個位置,不然會出現莫名其妙的錯誤,相對和絕對路徑混亂等錯誤);
2)拖入文件路徑進入 TARGETS - Build Setting - Header Seacher Paths (此處一定要注意,思密達)
圖片.png
3)集成 NIMSDK時候,會出現 $(inherited) 相關信息警告,找到三個屬性分別將$(inherited)添加進去并放置到第一個位置;
10.更改 .m文件類型,使之可以正常使用ijksdl相關文件和代碼
圖片.png