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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,136評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,886評論 18 139
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,223評論 4 61
  • 當初如果在一起多好啊 真的是好喜歡好喜歡呀 喜歡到還會經常夢見呢 朝前看原來不代表放下 夢中的我們 你愛我 我愛你...
    viviVIP閱讀 211評論 0 0
  • 我現在手上有四個筆記本,用途如下 第一個本子是用來記錄千字文想法的,這個其實沒有什么好說的,因為每天都要寫,需要積...
    陳素封閱讀 492評論 0 4