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 (此处一定要注意,思密达)
图片.png
               3)集成 NIMSDK时候,会出现 $(inherited) 相关信息警告,找到三个属性分别将$(inherited)添加进去并放置到第一个位置;

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,858评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 当初如果在一起多好啊 真的是好喜欢好喜欢呀 喜欢到还会经常梦见呢 朝前看原来不代表放下 梦中的我们 你爱我 我爱你...
    viviVIP阅读 205评论 0 0
  • 我现在手上有四个笔记本,用途如下 第一个本子是用来记录千字文想法的,这个其实没有什么好说的,因为每天都要写,需要积...
    陈素封阅读 479评论 0 4