anyRTC Zoom模式多人音視頻開發(fā)教程-iOS [附源碼]

應(yīng)廣大開發(fā)者要求,寫一下用anyRTC多人視頻sdk來(lái)模仿zoom多人視頻樣式,以下開始正文:

GitHub地址

https://github.com/BoYuanZjq/ZoomDemo

anyRTC多人音視頻sdk提供了4中模式,其中一種模式為zoom模式,我們只需要在進(jìn)會(huì)之前設(shè)置該種模式即可。

anyRTC SDK集成

集成sdk,是作為一名合格的開發(fā)人員必備的技能,根據(jù)官方集成文檔集成即可。

1. pod集成

pod 'RTMeetEngine'

2. 添加必要權(quán)限

在Info.plist中添加如下權(quán)限

<key>NSCameraUsageDescription</key>
<string>項(xiàng)目需要訪問(wèn)視頻</string>
<key>NSMicrophoneUsageDescription</key>
<string>項(xiàng)目需要訪問(wèn)音頻</string>

3. 打開音頻可后臺(tái)運(yùn)行
TARGETS->Capabilities->Background Modes->選中Audio,AirPlay,and Picture in Picture

后臺(tái)運(yùn)行

4. 配置開發(fā)者信息

在AppDelegate.h文件中把相應(yīng)的開發(fā)者信息替換一下, 配置項(xiàng)在官網(wǎng)創(chuàng)建應(yīng)用中可查看

static NSString *developerID = @"xxx";
static NSString *token = @"xxx";
static NSString *key = @"xxx";
static NSString *appID = @"xxx";

然后在AppDelegate.m中調(diào)用配置方法即可

[AnyRTCMeetEngine initEngineWithAnyRTCInfo:developerID andAppId:appID andKey:key andToke:token];

至此,anyRTC SDK集成已經(jīng)完畢,似不似如絲般順滑?接下來(lái)我們就可以愉快地和SDK玩耍了。

主頁(yè)面
主頁(yè)面

在主界面,我們需要檢查先Camera和Audio權(quán)限。

//授權(quán)相機(jī)
- (void)videoAuthAction
{
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
        NSLog(@"%@",granted ? @"相機(jī)準(zhǔn)許":@"相機(jī)不準(zhǔn)許");
    }];
}

//授權(quán)麥克風(fēng)
- (void)audioAuthAction
{
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
        NSLog(@"%@",granted ? @"麥克風(fēng)準(zhǔn)許":@"麥克風(fēng)不準(zhǔn)許");
    }];
}

zoom多人視頻頁(yè)面

主頁(yè)面輸入會(huì)議號(hào),點(diǎn)擊加入會(huì)議

zoom模式簡(jiǎn)介

zoom多人視頻模式,是解決手機(jī)上同時(shí)渲染多路性能的問(wèn)題而生,其中分為三種場(chǎng)景

  1. 駕駛模式:只接收音頻,不發(fā)送音視頻,發(fā)送音頻,根據(jù)客戶自己選擇。
  2. 說(shuō)話者模式:該模式,只顯示自己和當(dāng)前正在說(shuō)話的人,也可以選中一個(gè)人員,進(jìn)行雙人鎖定通信。
  3. 分屏模式:該模式每屏顯示4個(gè)圖像,包括自己,分屏顯示所有人。

該模式適合1~32人的大型音視頻會(huì)議,有效的解決了在服務(wù)器不合流的情況下手機(jī)性能問(wèn)題。

初始化RTMeetKit

- (void)initMeetKit {
    RTMeetOption *option = [RTMeetOption defaultOption];
    option.videoScreenOrientation =  RTC_SCRN_Auto;
    option.videoMode = AnyRTCVideoQuality_Low2;
    option.maxNum = 64;
    // 設(shè)置zoom 模式
    option.meetingType = AnyMeetingTypeZoom;
    self.meetKit = [[RTMeetKit alloc] initWithDelegate:self andOption:option];
    // 自己平臺(tái)用戶Id
    NSString *userID = [NSString stringWithFormat:@"%d",arc4random()%10];
    //加入房間
    [self.meetKit joinRTC:self.meetId andIsHoster:NO andUserId:userID andUserData:@"{}"];
    //打開網(wǎng)絡(luò)檢測(cè)
    [self.meetKit setNetworkStatus:YES];
    //打開音頻檢測(cè)(有人說(shuō)話的音量大?。?    [self.meetKit setAudioActiveCheck:YES];
}

加入會(huì)議成功的回調(diào)中設(shè)置zoom的說(shuō)話者模式

- (void)onRTCJoinMeetOK:(NSString*)strAnyRTCId {
    //預(yù)覽自己的視頻窗口
    [self.meetKit setLocalVideoCapturer:self.videoLayoutView.myVideoView];
    //設(shè)置zoom的說(shuō)話者模式
    [self.meetKit setZoomModel:AnyZoomTypeSingle];
}

有人進(jìn)入會(huì)議或者離開會(huì)議中把相關(guān)人員記錄或者刪除

// 有人進(jìn)來(lái)
-(void)onRTCOpenVideoRender:(NSString*)strRTCPeerId withRTCPubId:(NSString *)strRTCPubId withUserId:(NSString*)strUserId withUserData:(NSString*)strUserData {
    ZMVideoView *view = [[ZMVideoView alloc] init];
    view.peerId = strRTCPeerId;
    view.pubId = strRTCPubId;
    view.userId = strUserId;
    __weak typeof(self)weakSelf = self;
    view.tapEvent = ^() {
        if (weakSelf.zoomType==AnyZoomTypeSingle) {
            weakSelf.videoLayoutView.myVideoView.isBig = NO;
        }
        // 刷新布局
        [weakSelf.videoLayoutView layout];
    };
    //本地自己的strRTCPeerId 都為RTCMainParticipanter
    if (![strRTCPeerId isEqualToString:@"RTCMainParticipanter"]) {
        [self.meetKit setRTCVideoRender:strRTCPubId andRender:view.videoView];
    }
    [self.videoLayoutView.remoteArray addObject:view];
}
// 有人離開
-(void)onRTCCloseVideoRender:(NSString*)strRTCPeerId withRTCPubId:(NSString *)strRTCPubId withUserId:(NSString*)strUserId {
    for (ZMVideoView *view in self.videoLayoutView.remoteArray) {
        if ([view.peerId isEqualToString:strRTCPeerId]) {
            [view removeFromSuperview];
            [self.videoLayoutView.remoteArray removeObject:view];
            break;
        }
    }
}

zoom模式有人來(lái)或者離開后的統(tǒng)計(jì)信息,我們可以在該信息中對(duì)頁(yè)面布局做調(diào)整,比如增加一頁(yè),或者刪除一頁(yè),具體可以看代碼實(shí)現(xiàn)

- (void)onRTCZoomPageInfo:(AnyZoomType)nZoomType allPage:(int)nAllPage currentPage:(int)nCurrentPage allRenderNum:(int)nAllRenderNum beginIndex:(int)nIndex showNum:(int)nShowNum {
  // 對(duì)頁(yè)面做變化布局
}

不同模式需要的操作

- (void)changeZoomModel:(int)index {
    switch (index) {
        case 0:
        {
            //駕駛模式
            [self.meetKit setZoomModel:AnyZoomTypeDriver];
            //禁止傳輸視頻,此時(shí)可以說(shuō)話,只拉去音頻
            [self.meetKit setLocalVideoEnable:NO];
        }
            break;
        case 1:
        {
            // 單顯示模式(本地視頻打開)
            [self.meetKit setLocalVideoEnable:YES];
            // 設(shè)置單顯模式
            [self.meetKit setZoomModel:AnyZoomTypeSingle];
        }
            break;
        default:
        {
            // 設(shè)置分屏顯示
            if (self.zoomType != AnyZoomTypeNomal) {
                [self.meetKit setZoomModel:AnyZoomTypeNomal];
            }
            [self.meetKit setLocalVideoEnable:YES];
            // 設(shè)置頁(yè)碼
            [self.meetKit setZoomPage:index-2];
        }
            break;
    }
}

駕駛模式

駕駛模式根據(jù)自己需求是否把自己的音頻禁用,可以點(diǎn)擊說(shuō)話的時(shí)候打開禁用,取消說(shuō)話的時(shí)候,打開關(guān)閉禁用

 [self.meetKit setLocalAudioEnable:NO];
駕駛模式

說(shuō)話者模式

說(shuō)話者模式是自己和當(dāng)前說(shuō)話的人顯示,如果當(dāng)前會(huì)議只有自己一個(gè)人,全屏顯示自己的圖像,本地圖像以及遠(yuǎn)程圖像大小,自己布局決定。

說(shuō)話者模式

點(diǎn)擊小屏幕可以進(jìn)行大小屏切換。大小屏布局代碼如下:

            //說(shuō)話者模式布局代碼
            UIView *singView = [self.viewsArray objectAtIndex:1];
            if (self.remoteArray.count==0) {
                if (self.myVideoView.superview) {
                    [self.myVideoView removeFromSuperview];
                }
                self.myVideoView.frame = self.frame;
                [singView addSubview:self.myVideoView];
            }else{
                CGFloat X = CGRectGetWidth(self.frame) -90 -10;
                CGFloat Y = CGRectGetHeight(self.frame)-120 -10;
                CGFloat width = 90;
                CGFloat height = 120;
                ZMVideoView *otherView = [self.remoteArray firstObject];
                if (otherView.superview) {
                    [otherView removeFromSuperview];
                }
                if (self.myVideoView.superview) {
                    [self.myVideoView removeFromSuperview];
                }
                if (!self.myVideoView.isBig) {
                    otherView.frame = self.frame;
                    [singView addSubview:otherView];
                    [singView sendSubviewToBack:otherView];
                    
                    self.myVideoView.frame = CGRectMake(X, Y, width, height);
                    [singView addSubview:self.myVideoView];
                }else{
                    self.myVideoView.frame = self.frame;
                    [singView addSubview:self.myVideoView];
                    [singView sendSubviewToBack:self.myVideoView];
                    
                    otherView.frame = CGRectMake(X, Y, width, height);
                    [singView addSubview:otherView];
                }          

分屏顯示
分屏顯示每屏第一個(gè)視頻都為自己,切換到當(dāng)前模式下的時(shí)候,布局的視圖,全有有人來(lái)了的回調(diào)里存儲(chǔ)進(jìn)行布局即可。

分屏顯示

布局代碼如下,三分屏幕或者4分屏

            // 平分顯示
            CGFloat width = CGRectGetWidth(self.frame)/2;
            CGFloat height = width*4/3;
            CGFloat X = 0;
            CGFloat Y =(CGRectGetHeight(self.frame)-2*height)/2;
            UIView *singView = [self.viewsArray objectAtIndex:self.viewIndex];
            for (int i=0;i<self.remoteArray.count;i++ ) {
                
                ZMVideoView *view = [self.remoteArray objectAtIndex:i];
                if (view.superview) {
                    [view removeFromSuperview];
                }
                // 自己本地的視圖
                if ([view.peerId isEqualToString:@"RTCMainParticipanter"]) {
                    if (self.myVideoView.superview) {
                        [self.myVideoView removeFromSuperview];
                    }
                    [singView addSubview:self.myVideoView];
                    self.myVideoView.frame = CGRectMake(X, Y, width, height);
                    if ((i+1)%2==0) {
                        X = 0;
                        Y+=height;
                    }else{
                        X = X+width;
                    }
                }else{
                    [singView addSubview:view];
                    view.frame = CGRectMake(X, Y, width, height);
                    if ((i+1)%2==0) {
                        X = 0;
                        Y+=height;
                    }else{
                        X = X+width;
                    }
                }
            }

掛斷離開

- (void)closeButtonEvent:(UIButton*)sender {
    //離開頻道,釋放資源
    [self.meetKit leaveRTC];
    [self dismissViewControllerAnimated:YES completion:nil];
}

總結(jié)

上述即為zoom多人模式多人布局的寫法,大致步驟我做下總結(jié)

  1. 初始化引擎之前,在Controller中添加一個(gè)UIScrollView,并添加兩個(gè)視圖,第一個(gè)為駕駛模式頁(yè)面,另外一個(gè)是說(shuō)話者模式頁(yè)面。

  2. join成功之后,需要設(shè)置調(diào)用如下方法,設(shè)置為AnyZoomTypeSingle模式。

- (BOOL)setZoomModel:(AnyZoomType)eType;
  1. 等待onRTCZoomPageInfo 信息回調(diào),我們根據(jù)該回調(diào)進(jìn)行頁(yè)面顯示和布局。

其中還有一些方法,比如禁用自己的音頻和視頻,攝像頭翻轉(zhuǎn),鏡像開關(guān),揚(yáng)聲器開關(guān)等等一些接口,根據(jù)自己的需要添加即可。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容