V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cookiezmq
V2EX  ›  分享发现

基于声网 SDK 实现 macOS 端的一对一视频通话

  •  
  •   cookiezmq · 2022-09-26 14:11:20 +08:00 · 940 次点击
    这是一个创建于 790 天前的主题,其中的信息可能已经有所发展或是发生改变。

    音视频互动包括直播是当前比较热门的玩法,我们经常见到有 PK 连麦、直播答题、一起 KTV 、电商直播、互动大班课、视频相亲等。本文将演示如何通过声网 SDK 在 macOS 端实现一个视频通话应用

    前提条件

    注:如果你的网络环境部署了防火墙,请根据声网文档中心的「应用企业防火墙限制」打开相关端口。

    准备开发环境

    本节介绍如何创建项目,并将声网 SDK 集成至你的项目中。

    创建 macOS 项目

    参考以下步骤创建一个 macOS 项目。若已有 macOS 项目,可以跳脱这一步,直接查看本文「集成 SDK 」小节。

    1. 打开 Xcode 并点击 Create a new Xcode project 。

    2. 选择项目类型为 Cocoa App ,并点击 Next 。

    3. 输入项目信息,如项目名称、开发团队信息、组织名称和语言,并点击 Next 。

    如果你没有添加过开发团队信息,会看到 Add account… 按钮。点击该按钮并按照屏幕提示登入 Apple ID ,完成后即可选择你的账户作为开发团队。

    1. 选择项目存储路径,并点击 Create 。

    2. 进入 TARGETS > Project Name > General > Signing 菜单,选择 Automatically manage signing ,并在弹出菜单中点击 Enable Automatic 。 在这里插入图片描述

    集成 SDK

    选择如下任意一种方式将声网 SDK 集成到你的项目中。

    方法一:使用 CocoaPods 自动集成

    1. 开始前确保你已安装 Cocoapods 。参考 Getting Started with CocoaPods 安装说明。

    2. 在 Terminal 里进入项目根目录,并运行 pod init 命令。项目文件夹下会生成一个 Podfile 文本文件。

    3. 打开 Podfile 文件,修改文件为如下内容。注意将 Your App 替换为你的 Target 名称。

    # platform :macOS, '10.11' use_frameworks!
    target 'Your App' do
      pod 'AgoraRtcEngine_macOS'
    end
    
    1. 在 Terminal 内运行 pod update 命令更新本地库版本。

    2. 运行 pod install 命令安装声网 SDK 。成功安装后,Terminal 中会显示 Pod installation complete! ,此时项目文件夹下会生成一个 xcworkspace 文件。

    3. 打开新生成的 xcworkspace 文件。

    方法二:手动复制 SDK 文件

    1. 前往 SDK 下载页面,获取最新版的声网 SDK ,然后解压。

    2. 将 libs 文件夹内的 AgoraRtcEngineKit.framework 文件复制到项目文件夹下。

    3. 打开 Xcode ,进入 TARGETS > Project Name > Build Phases > Link Binary with Libraries 菜单,点击 + 添加如下库。在添加 AgoraRtcEngineKit.framework 文件时,还需在点击 + 后点击 Add Other…,找到本地文件并打开。 在这里插入图片描述

    4. AgoraRtcEngineKit.framework

    5. Accelerate.framework

    6. CoreWLAN.framework

    7. libc++.dylib

    8. libresolv.9.tbd

    9. SystemConfiguration.framework

    10. VideoToolbox.framework

    添加媒体设备权限

    1. 根据场景需要,打开 Xcode ,在 info.plist 文件中,点击 + 图标开始添加如下内容,获取相应的设备权限: 在这里插入图片描述 在这里插入图片描述

    2. 若你的项目已启用 App Sandbox 或 Hardened Runtime 设置,则需勾选如下内容,获取相应的设备权限: 在这里插入图片描述在这里插入图片描述

    实现音视频通话

    本节介绍如何实现音视频通话。视频通话的 API 调用时序见下图: 在这里插入图片描述

    1. 创建用户界面

    根据场景需要,为你的项目创建音视频通话的用户界面。若已有用户界面,可以直接查看导入类。

    如果你想实现一个视频通话,我们推荐你添加如下 UI 元素:

    • 本地视频窗口

    • 远端视频窗口

    • 结束通话按钮

    当你使用示例项目中的 UI 设计时,你将会看到如下界面: 在这里插入图片描述

    2. 导入类

    在项目中导入 AgoraRtcEngineKit 类:

    // Objective-C
    #import <AgoraRtcEngineKit/AgoraRtcEngineKit.h>
    // Swift
    import AgoraRtcEngineKit
    

    声网 Native SDK 默认使用 libc++ (LLVM),如需使用 libstdc++ (GNU),请联系 [email protected] 。SDK 提供的库是 Fat Image ,包含 32/64 位模拟器、32/64 位真机版本。

    3. 初始化 AgoraRtcEngineKit

    在调用其他声网 API 前,需要创建并初始化 AgoraRtcEngineKit 对象。

    你需要在该步骤中填入项目的 App ID 。请参考如下步骤在控制台创建声网项目并获取 App ID 。

    1. 登录控制台

    2. 点击创建,按照屏幕提示设置"项目名""使用场景",鉴权机制,在测试阶段可以选择“调试模式:APP ID”然后点击提交。

    3. 在项目管理页面,你可以获取该项目的 App ID

    调用 sharedEngineWithAppId 方法,传入获取到的 App ID ,即可初始化 AgoraRtcEngineKit

    你还可以根据场景需要,在初始化时注册想要监听的回调事件,如本地用户加入频道及解码远端用户视频首帧等。

    // Objective-C
    - (void)initializeAgoraEngine {
        // 输入 App ID 并初始化 AgoraRtcEngineKit 类
        self.agoraKit = [AgoraRtcEngineKit sharedEngineWithAppId:appID delegate:self];
    }
    
    // Swift
    func initializeAgoraEngine() {
       // 输入 App ID 并初始化 AgoraRtcEngineKit 类。
       agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: AppID, delegate: self)
    }
    

    4. 设置本地视图

    如果你想实现一个语音通话,可以直接查看加入频道。

    成功初始化 AgoraRtcEngineKit 对象后,需要在加入频道前设置本地视图,以便在通话中看到本地图像。参考以下步骤设置本地视图:

    • 调用 enableVideo 方法启用视频模块。

    • 调用 setupLocalVideo 方法设置本地视图。

    // Objective-C
    // 启用视频模块
    [self.agoraKit enableVideo];
    - (void)setupLocalVideo {
        AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
        videoCanvas.uid = 0;
        videoCanvas.view = self.localVideo;
        videoCanvas.renderMode = AgoraVideoRenderModeHidden;
        // 设置本地视图
        [self.agoraKit setupLocalVideo:videoCanvas];
    }
    // Swift
    // 启用视频模块
    agoraKit.enableVideo()
    func setupLocalVideo() {
      let videoCanvas = AgoraRtcVideoCanvas()
      videoCanvas.uid = 0
      videoCanvas.view = localVideo
      videoCanvas.renderMode = .hidden
      // 设置本地视图
      agoraKit.setupLocalVideo(videoCanvas)
    }
    

    5. 加入频道

    完成初始化和设置本地视图后(视频通话场景),你就可以调用 joinChannelByToken 方法加入频道。你需要在该方法中传入如下参数:

    • channelId : 传入能标识频道的频道 ID 。输入频道 ID 相同的用户会进入同一个频道。

    • token :传入能标识用户角色和权限的 Token 。可设为如下一个值:

    若项目已启用 App 证书,请使用 Token 。

    • nil

    • 临时 Token 。临时 Token 服务有效期为 24 小时。你可以在控制台里生成一个临时 Token ,详见获取临时 Token 。

    • 在你的服务器端生成的 Token 。在安全要求高的场景下,我们推荐你使用此种方式生成的 Token ,详见生成 Token 。

    • uid : 本地用户的 ID 。数据类型为整型,且频道内每个用户的 uid 必须是唯一的。若将 uid 设为 0 ,则 SDK 会自动分配一个 uid ,并在 joinSuccessBlock 回调中报告。

    • joinSuccessBlock :成功加入频道回调。 joinSuccessBlock 优先级高于 didJoinChannel ,2 个同时存在时, didJoinChannel 会被忽略。需要有 didJoinChannel 回调时,请将 joinSuccessBlock 设置为 nil

    更多的参数设置注意事项请参考 joinChannelByToken 接口中的参数描述。

    // Objective-C
    - (void)joinChannel {
        // 加入频道
        [self.agoraKit joinChannelByToken:token channelId:@"demoChannel1" info:nil uid:0 joinSuccess:^(NSString *channel, NSUInteger uid, NSInteger elapsed) {
        }];
    }
    
    // Swift
    func joinChannel() {
        // 加入频道
        agoraKit.joinChannel(byToken: Token, channelId: "demoChannel1", info:nil, uid:0) { [unowned self] (channel, uid, elapsed) -> Void in}
        self.isLocalVideoRender = true
                self.logVC?.log(type: .info, content: "did join channel")
            }
            isStartCalling = true
    }
    

    6. 设置远端视图

    视频通话中,通常你也需要看到其他用户。在加入频道后,可通过调用 setupRemoteVideo 方法设置远端用户的视图。

    远端用户成功加入频道后,SDK 会触发 firstRemoteVideoDecodedOfUid 回调,该回调中会包含这个远端用户的 uid 信息。在该回调中调用 setupRemoteVideo 方法,传入获取到的 uid ,设置远端用户的视图。

    // Objective-C
    // 监听 firstRemoteVideoDecodedOfUid 回调。
    // SDK 接收到第一帧远端视频并成功解码时,会触发该回调。
    // 可以在该回调中调用 setupRemoteVideo 方法设置远端视图。
    - (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteVideoDecodedOfUid:(NSUInteger)uid size: (CGSize)size elapsed:(NSInteger)elapsed {
        if (self.remoteVideo.hidden) {
            self.remoteVideo.hidden = NO;
        }
        AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
        videoCanvas.uid = uid;
        videoCanvas.view = self.remoteVideo;
        videoCanvas.renderMode = AgoraVideoRenderModeHidden;
        // 设置远端视图
        [self.agoraKit setupRemoteVideo:videoCanvas];
    }
    
    // Swift
    // 监听 firstRemoteVideoDecodedOfUid 回调。
    // SDK 接收到第一帧远端视频并成功解码时,会触发该回调。
    // 可以在该回调中调用 setupRemoteVideo 方法设置远端视图。
    func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid:UInt, size:CGSize, elapsed:Int) {
            isRemoteVideoRender = true
            let videoCanvas = AgoraRtcVideoCanvas()
            videoCanvas.uid = uid
            videoCanvas.view = remoteVideo
            videoCanvas.renderMode = .hidden
            // 设置远端视图
            agoraKit.setupRemoteVideo(videoCanvas)
        }
    

    7. 离开频道

    根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel 离开当前通话频道。

    // Objective-C
    - (void)leaveChannel {
        // 离开频道。
        [self.agoraKit leaveChannel:^(AgoraChannelStats *stat)
    }
    // Swift
    func leaveChannel() {
    // 离开频道
     AgoraKit.leaveChannel(nil)
     AgoraKit.setupLocalVideo(nil)
     remoteVideo.removeFromSuperview()
     localVideo.removeFromSuperview()
     delegate?.VideoChatNeedClose(self)
     AgoraKit = nil
     view.window!.close()
     }
    

    示例代码

    你可以在 Agora-macOS-Tutorial-Objective-C-1to1/Agora-macOS-Tutorial-Swift-1to1 示例项目的 VideoChatViewController.m/VideoChatViewController.swift 文件中查看完整的源码和代码逻辑。

    运行 /测试项目

    你可以在 macOS 设备中运行此项目。当成功开始视频通话时,你可以同时看到本地和远端的视图。


    如果遇到问题,可以在RTE 开发者社区 发帖提问。

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2411 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:59 · PVG 23:59 · LAX 07:59 · JFK 10:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.