博客> iOS - 网易云信(天天狼人杀谁上麦谁音视频,多人视频)
iOS - 网易云信(天天狼人杀谁上麦谁音视频,多人视频)
2017-08-16 11:34 评论:0 阅读:196 OS_JJ
ios - 网易云信(天天狼人杀谁上麦谁音视频 多人视频)

注:由于个人版本构建不同,所以备注代码和方案不同!

第一.多方视频(自己集成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 (此处一定要注意,思密达)

 209601C0-682C-429D-BF8F-99F0E0E6F2C4.png 3)集成 NIMSDK时候,会出现 $(inherited) 相关信息警告,找到三个属性分别将$(inherited)添加进去并放置到第一个位置;

10.更改 .m文件类型,使之可以正常使用ijksdl相关文件和代码

 D98B95E5-FBBD-4FF9-8A84-B0EF495D4725.png

收藏
0
sina weixin mail 回到顶部