zoukankan      html  css  js  c++  java
  • 云信小课堂|如何实现音视频通话

     

    image.png

    大家好,欢迎大家来到「云信小课堂 」。

    本栏目致力于解答有关 IM 和音视频的一切问题,产品特点、使用场景、技术名词、接入指南、功能实现......欢迎大家留言提问,我们每节课会选取大家感兴趣的问题进行解答。

    概述

    微信的火热让网络语音/视频通话逐步替代了传统手机通话,那么如果快速实现一款轻量的音视频通话应用呢?其实并不复杂,几十行代码就能实现。

    开学第一课,我们一起聊一聊如何快速实现音视频通话。

    功能解析

    我们先来定义一下一款轻量的音视频通话应用需要哪些功能,首先基础类功能可能包含

    • 加入/离开通话
    • 语音/视频通话
    • 音频/视频开启与关闭

     

    具体可参见下图,当然在基础类功能之上我们也可以引入美颜、变声等更多高级的玩法,本期暂不做展开,后面会陆续为大家介绍哦!

     

    1.png

     

    功能实现

    本章以  iOS 为例介绍如何使用 NERTC SDK 实现音视频通话,更多终端参见网易云信官方 Github

    以下内容为大家介绍如果基于 网易云信 音视频通话2.0 SDK 快速实现音视频通话功能,基本步骤如下:

    1. 集成SDK(网易云信音视频2.0 SDK)
    2. 设置本地视图
    3. 加入频道
    4. 设置远端视图
    5. 音频流
    6. 离开频道
    7. 销毁音视频实例

    集成 SDK

    CocoaPods 集成

    集成前,请先前往SDK下载页面查看当前最新版本,并查询本地仓库中对应的版本是否为最新版本。若不是最新版本,建议先更新本地仓库,以确保可以集成最新的SDK版本。

    pod search NERtcSDK      //本地仓库中查询 NERtcSDK 信息    
    pod repo update          //更新本地仓库    
    pod install              //执行安装

    至此, NERTC SDK 已经导入完成。

    手动导入 SDK 集成

    • 请先前往 SDK 下载页获取当前最新版本;
    • 将解压得到的 NERtcSDK.framework 和 NMCBasicModuleFramework.framework 文件拷贝到工程项目文件夹下;
    • 以 Xcode Version 11.5 为例,进入TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content 菜单,点击 +,再点击 Add Other…,将上述解压得到的 SDK 文件添加进去。同时,将 Embed 属性设置为 Embed & Sign,以使得 SDK 动态库和应用签名保持一致;

    至此, NERTC SDK 已经导入完成。

    实现音视频通话

    本节以 iOS 为例介绍如何使用 NERTC SDK 实现音视频通话,主要流程如下图所示:

    (更多终端参见网易云信官方 Github

    2.png

    3.png

    *此处 Server 指的是云信 SDK Sever。

     

    初始化

    • 引入头文件
    #import <NERtcSDK/NERtcSDK.h>
    • 执行初始化
    @interface  Myapp () 
    ...NERtcEngine coreEngine = [NERtcEngine sharedEngine];NERtcEngineContext context = [[NERtcEngineContext alloc] init];
    context.engineDelegate = self;
    context.appKey = AppKey;
    [coreEngine setupEngineWithContext:context];
    ...
    

    初始化的参数类 NERtcEngineContext 属性说明:

    @interface NERtcEngineContext : NSObject
    /**
     已开通音视频功能的云信应用的AppKey。
     */@property (nonatomic, copy) NSString *appKey;
    /**
     log的相关设置,由开发者提供。可选参数。
     */@property (nonatomic, strong) NERtcLogSetting *logSetting;
    /**
     通话相关信息的回调接口,由开发者提供。
     */@property (nonatomic, weak) id<NERtcEngineDelegateEx> engineDelegate;
    @end

    设置本地视图

    启动视频流

    • API 描述
    @protocol INERtcEngine <NSObject>/**
     开启自己的视频。可以在加入频道前和频道后调用。
    
     @param enabled 是否开启
     @return 操作返回值,成功则返回 0
    */
    - (int)enableLocalVideo:(BOOL)enabled;@end
    • 示例代码
    [NERtcEngine.sharedEngine enableLocalVideo:YES]; 

    设置本地视频画布

    启动视频流后,可以设置本地视频画布,用来显示本地采集的视频画面。

    • API 描述
    @protocol INERtcEngine <NSObject>/**
     设置本地视频画布
    
     @param canvas 视频窗口,如果需要删除则传 nil
     @return 操作返回值,成功则返回 0
     */
    - (int)setupLocalVideoCanvas:(NERtcVideoCanvas *)canvas;@end
    • 示例代码
    NERtcVideoCanvas *canvas = [[NERtcVideoCanvas alloc] init];
    canvas.container = self.localUserView;[NERtcEngine.sharedEngine setupLocalVideoCanvas:canvas];

    设置成功后,即可显示本地视频画面。

    加入频道

    加入频道前,请确保已完成初始化相关事项。若您的业务中涉及呼叫邀请等机制,可以使用信令。

    • API 描述
    @protocol INERtcEngine <NSObject>/**
    加入频道
     @param token 频道token
     @param channelName 频道名
     @param uId 当前用户的Id
     @param completion 操作完成的 block 回调
     @return 操作返回值,被执行了则返回 0
     */
    - (int)joinChannelWithToken:(NSString *)token                channelName:(nullable NSString *)channelName                      myUid:(uint64_t)uId                 completion:(NERtcJoinChannelCompletion)completion;@end
    • 参数说明
      • token:频道 token。支持传入以下内容:
        • 空字符串。该种方式需要先开通非安全模式。安全性不高,建议在产品正式上线前转为安全模式;
        • 安全认证签名密钥。安全模式下必需。若未传入正确的 token 将无法进入频道。建议使用安全模式;
      • channelName:频道名称,传入相同频道名称的用户会进入同一个通话频道;
      • UID:用户的唯一标识 Id,频道内每个用户的 UID 必须是唯一的;

     

    • 示例代码
    //加入房间
    - (void)joinChannelWithRoomId:(NSString *)roomId
                           userId:(uint64_t)userId {
        __weak typeof(self) weakSelf = self;
        [NERtcEngine.sharedEngine joinChannelWithToken:@""
                                           channelName:roomId
                                                 myUid:userId
                                            completion:^(NSError * _Nullable error, uint64_tchannelId, uint64_t elapesd) {
            if (error) {
                //加入失败了,弹框之后退出当前页面
            } else {
                //加入成功
            }
        }];
    } 

    设置远端视图

    视频通话过程中,除了要显示本地的视频画面,通常也要显示参与通话的其他用户的远端视频画面。

    监听远端用户进出频道

    • API 描述
    @protocol NERtcEngineDelegate <NSObject>/**
     其他用户加入频道的回调
    
     @param userID 用户的id
     @param userName 用户名称
     */
    - (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID                                   userName:(NSString *)userName;
    /**
     其他用户离开频道的回调
    
     @param userID 用户的id
     @param reason 离开的原因
     */
    - (void)onNERtcEngineUserDidLeaveWithUserID:(uint64_t)userID   


    设置远端视频画布

     

    监听到远端用户加入频道后,可以设置远端视频画布,用来显示远端用户的视频画面。

    • API 描述
    @protocol INERtcEngine <NSObject>
    /**
     设置远端的视频播放窗口
     只能在加入频道后调用
    
     @param userID 用户的id
     @param canvas 视频窗口,如果需要删除则传nil
     @return 操作返回值,成功则返回 0
     */
    - (int)setupRemoteVideoCanvas:(NERtcVideoCanvas *)canvas forUserID:(uint64_t)userID;@end
    

     

    • 示例代码
    - (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID                                  userName:(NSString *)userName {
    
        //如果已经setup了一个远端的canvas,则不需要再建立了
        ...
        if (_remoteCanvas != nil) {
            return;
        }
    
        //建立远端canvas,用来渲染远端画面
        NERtcVideoCanvas *canvas = [self setupRemoteCanvasWithUid:userID];
        [NERtcEngine.sharedEngine setupRemoteVideoCanvas:canvas                                           forUserID:userID];
        ...
    }
    
    ···
    
    - (void)onNERtcEngineUserDidLeaveWithUserID:(uint64_t)userID                                     reason:(NERtcSessionLeaveReason)reason {
    
    
        //如果远端的人离开了,重置远端模型和UI
        ...
        [NERtcEngine.sharedEngine setupRemoteVideoCanvas:nil                                           forUserID:userID];
        ...
    }
    

    监听远端视频流发布

    当频道中的其他用户有视频流发出/关闭时,分别会走入以下回调:

    • API 描述
    @protocol NERtcEngineDelegate <NSObject>
    /**
     其他用户打开视频的回调
    
     @param userID 用户id
     @param profile 用户发送视频的最大分辨率类型
     */
    - (void)onNERtcEngineUserVideoDidStartWithUserID:(uint64_t)userID videoProfile:(NERtcVideoProfileType)profile;
    /**
     其他用户关闭视频的回调
    
     @param userID 用户id
     */
    - (void)onNERtcEngineUserVideoDidStop:(uint64_t)userID;@end
    

      

    订阅远端视频流

     

    在设置完远端视频画布后,且监听到远端用户有视频发布时,可以订阅远端用户的视频流。

     

    • API 描述
    @protocol  INERtcEngineEx /**
    订阅或取消订阅别人的视频,订阅了才会接收别人的视频数据。
    @param  subscribe 是否订阅 
    @param  userID 用户的id 
    @param  streamType 订阅的远端视频流类型 
    @return  操作返回值,成功则返回 0 
    */
    - (int)subscribeRemoteVideo:(BOOL)subscribe                   forUserID:(uint64_t)userID                  streamType:(NERtcRemoteVideoStreamType)streamType;@end
    
    • 示例代码
    // 监听到远端用户有视频流发布
    - (void)onNERtcEngineUserVideoDidStartWithUserID:(uint64_t)userID
                                        videoProfile:(NERtcVideoProfileType)profile {
        //如果已经订阅过远端视频流,则不需要再订阅了
        ...
        if (_remoteCanvas.subscribedVideo) {
            return;
        }
    
    
        //订阅远端视频流。
        _remoteCanvas.subscribedVideo = YES;
        [NERtcEngine.sharedEngine subscribeRemoteVideo:YES
                                     forUserID:userID
                                    streamType:kNERtcRemoteVideoStreamTypeHigh];
        ...}
    // 监听到远端用户停止视频流发布
    - (void)onNERtcEngineUserVideoDidStop:(uint64_t)userID {
        if (userID == _remoteCanvas.uid) {
            // 收到此回调后,SDK 内部会取消对应的视频流订阅,无需开发者主动取消订阅。
            ...
            _remoteStatLab.hidden = YES;
            ...
        }
    }
    

     

    订阅成功后,即可显示远端的视频画面。

    音频流

    在 NERtcSDK 中,本地音频的采集发布和远端音频订阅播放是默认启动的,正常情况下无需开发者主动干预。

    离开频道

    当通话结束,需要离开频道,可以调用以下接口:

    • API 描述
    @protocol INERtcEngine <NSObject>
    /**
     离开频道
    
     @return 操作返回值,成功则返回 0
     */
    - (int)leaveChannel;@end
    • 示例代码
    //UI 挂断按钮事件- (IBAction)onHungupAction:(UIButton *)sender {
        [NERtcEngine.sharedEngine leaveChannel];
        [self dismiss];
    }

    执行完 leaveChannel 方法后,SDK 会触发 离开频道回调通知开发者:

    • API 描述
    @protocol NERtcEngineDelegate <NSObject>/**
     离开频道回调
    
     @param result 离开的结果
     */
    - (void)onNERtcEngineDidLeaveChannelWithResult:(NERtcError)result;@end
    • 示例代码
    - (void)onNERtcEngineDidLeaveChannelWithResult:(NERtcError)result{
        // 进行业务数据清理
    }

    销毁音视频实例

    释放当前的 NERtcEngine 实例,建议在 App 确定不再需要使用 NERtcEngine 实例时,通过该接口释放 NERtcEngine 实例的对象资源。

    • API 描述
    @interface NERtcEngine : NSObject <INERtcEngineEx>
    /**
     释放当前的 NERtcEngine 实例
     建议在 App 确定不再需要使用 NERtcEngine 实例时,通过该接口释放 NERtcEngine 实例的对象资源;
     1. 该接口的工作方式为同步调用方式,必须在子线程中才能调用,否则会调用失败;如:
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{     [NERtcEngine destroyEngine];
     }); 2. 该接口不得在 SDK 的回调中调用,在接口返回前也不允许调用 SDK 的其他任何接口;3. 接口调用返回之后,如果需要再次使用 SDK,可以重新调用 sharedEngine 来获取一个新的 NERtcEngine 实例。
    
     */
    
    + (int)destroyEngine;@end
    • 示例代码
    - (void)dealloc {
        [NERtcEngine destroyEngine]; //销毁实例
    }
    

    示例项目

    为了便于大家学习理解,我们将上文内容作为开源项目发布在了 Github 上,各位有兴趣可以前往查看示例项目。

     
     
     
     
  • 相关阅读:
    【转】二叉树中两个节点的最近的公共父节点
    查找最小的k个元素
    字符串的排列
    php字符串操作
    Android手机app启动的时候第一个Activity必须是MainActivity吗
    ASP.NET网站前端页面的复制
    MySQL字段类型说明
    转:Zend Server Community Edition(CE) 安装手记
    数据库远程导入导出步骤
    转:两种转换mysql数据编码的方法latin1转utf8
  • 原文地址:https://www.cnblogs.com/wangyiyunxin/p/14007897.html
Copyright © 2011-2022 走看看