You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
实现音视频通话
iOS (Objective-C)
复制全文
下载 pdf
iOS (Objective-C)
集成 RTC SDK 后,你可以使用其中接口快速构建基础应用,实现基本实时音视频通话;你也能通过阅读代码,了解音视频通话的最佳实践。​
如果你想了解完整的项目实现,参看示例项目。​
前提条件​
  • Xcode 12.5 或以上版本(本文涉及编译器的指引及示例图均参考 Xcode 13.1 )​
  • 支持 iOS 11.0 或以上版本的设备​
  • 使用 Objective-C 作为开发语言​
  • 请确保您的项目已设置有效的开发者签名​
注意:​
面向 iOS 平台的 SDK 仅以 .xcframework 形式提供。如果需要使用 .framework 的 SDK,你可以使用以下脚本,将 .xcframework 转为 .framework:​
如果使用了 .framework,且需要将 App 上架 App Store,你必须在提交的工程中去除模拟器。可以使用以下脚本:​
集成 SDK​
步骤 1:(可选)创建项目​
本步骤为如何创建一个新项目,如集成到已有项目,请直接查看步骤 2。​
  1. 打开 Xcode,点击 File > New > Project​
  1. 选择 iOS > App,点击 Next​
  • ​图片​​
  1. 输入项目名称、团队名称、选择开发语言(这里为 Objective-C ) ,点击 Next​
  • ​图片​​
  1. 选择项目存储位置,点击 Create​
  1. 签名设置:进入 TARGETS > Project Name > Signing & Capabilities ,查看 Automatically manage signing 是否勾选,若没有勾选请勾选 , 并在弹出菜单中选择 Enable Automatic​
  • ​图片​​
步骤2: 解压 SDK,并拷贝到项目目录下​
将下载的 VolcEngineRTC.xcframework 和 RealXBase.xcframework 拖入到工程中。注意选择 Copy files to destination。​
步骤3:配置项目属性​
  1. 配置音视频权限​
  1. 找到项目中的 info.plist 文件​
  1. 点击 “+” 添加音频和视频设备权限:​
  1. Privacy - Microphone Usage Description ,并填入使用麦克风的原因(Value)​
  1. Privacy - Camera Usage Description ,并填入使用摄像头的原因(Value)​
  • ​图片​​
  1. 关闭 Bitcode (如有)​
  1. 进入 TARGETS > 项目名称 > Build Setting​
  1. 选择 All,搜索 bitcode​
  1. Enable Bitcode 选择 NO​
  • ​图片​​
  1. SDK 配置​
  1. 进入 TARGETS > 项目名称 > General​
  1. 选择 Frameworks, Libraries, and Embedded Content​
  1. 将 VolcEngineRTC.xcframework、 RealXBase.xcframework 和 RTCFFmpeg 设置为 Embed & Sign​
  • ​图片​​
步骤4:添加隐私清单文件​
应苹果公司的要求,你的 iOS App 如需要上线 App Store,必须准确描述 App 本身和集成的第三方 SDK 使用指定范围内系统接口的原因。自 2024 年 5 月 1 日起,如果你未提供相关描述,你的 App 将无法通过 App Store Connect 的审核。详见 Describing use of required reason API。​
如果你在 App 中集成了 3.58 及之前版本的 RTC SDK,你必须添加相关说明:​
  • 如果你的 App 中没有隐私清单文件,你可以直接将 RTC SDK 的隐私清单文件添加项目根目录下。如图:​
  • ​图片​​
  • 如果你的 App 中已有隐私清单文件,请将 RTC SDK 的隐私清单文件中的内容添加到 App 的隐私清单文件中。​
获取 RTC SDK 的隐私清单文件:​
实现音视频通话​
基础音视频通话 API 时序图​
​图片​​
实现流程​
1. (可选)创建用户界面​
根据场景需要,为你的项目创建音视频通话的用户界面。若已有用户界面,请直接进入下一步。​
如果你想实现基本的音视频通话,我们建议你在项目中添加如下元素:​
  • 房间ID​
  • 用户 ID​
  • 本地视频窗口​
  • 远端视频窗口​
  • 打开麦克风按钮​
  • 打开摄像头按钮​
  • 结束通话按钮​
​图片​​
可参考以下代码构建用户界面:​
​
- (void)buildUI{​
self.view.backgroundColor = [UIColor whiteColor];​
​
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;​
if (@available(iOS 11.0, *)) {​
edgeInsets = [UIApplication sharedApplication].keyWindow.safeAreaInsets;​
}​
​
[self.view addSubview:self.headerView];​
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.top.mas_equalTo(edgeInsets.top);​
make.left.right.equalTo(self.view);​
make.height.mas_equalTo(49);​
}];​
​
self.switchCameraBtn.frame = CGRectMake(22, 14, 26, 26);​
[self.headerView addSubview:self.switchCameraBtn];​
[self.switchCameraBtn mas_makeConstraints:^(MASConstraintMaker *make) {​
make.left.mas_equalTo(22);​
make.size.mas_equalTo(26);​
make.centerY.equalTo(self.headerView);​
}];​
​
[self.headerView addSubview:self.roomIdLabel];​
[self.roomIdLabel mas_makeConstraints:^(MASConstraintMaker *make) {​
make.center.equalTo(self.headerView);​
make.left.greaterThanOrEqualTo(self.switchCameraBtn.mas_right).mas_offset(22);​
}];​
self.roomIdLabel.text = [NSString stringWithFormat:@"RoomID: %@",self.roomID];​
​
[self.headerView addSubview:self.switchAudioRouteBtn];​
[self.switchAudioRouteBtn mas_makeConstraints:^(MASConstraintMaker *make) {​
make.right.mas_equalTo(-20);​
make.centerY.equalTo(self.headerView);​
}];​
​
[self.view addSubview: self.foooterView];​
[self.foooterView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.left.right.equalTo(self.view);​
make.bottom.equalTo(self.view).offset(-edgeInsets.bottom);​
make.height.mas_equalTo(49);​
}];​
​
[self.foooterView addSubview:self.localAudioBtn];​
[self.localAudioBtn mas_makeConstraints:^(MASConstraintMaker *make) {​
make.left.mas_equalTo(42);​
make.centerY.equalTo(self.foooterView);​
}];​
​
[self.foooterView addSubview:self.localVideoBtn];​
[self.localVideoBtn mas_makeConstraints:^(MASConstraintMaker *make) {​
make.right.mas_equalTo(-42);​
make.centerY.equalTo(self.foooterView);​
}];​
​
[self.foooterView addSubview:self.hangUpBtn];​
[self.hangUpBtn mas_makeConstraints:^(MASConstraintMaker *make) {​
make.center.equalTo(self.foooterView);​
}];​
​
[self.view addSubview:self.containerView];​
[self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.left.right.equalTo(self.view);​
make.top.equalTo(self.headerView.mas_bottom);​
make.bottom.equalTo(self.foooterView.mas_top);​
}];​
​
[self.containerView addSubview:self.localView];​
[self.localView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.top.left.equalTo(self.containerView);​
make.width.height.equalTo(self.containerView).multipliedBy(0.5);​
}];​
​
[self.containerView addSubview:self.firstRemoteView];​
[self.firstRemoteView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.top.right.equalTo(self.containerView);​
make.width.height.equalTo(self.containerView).multipliedBy(0.5);​
}];​
​
[self.containerView addSubview:self.secondRemoteView];​
[self.secondRemoteView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.bottom.left.equalTo(self.containerView);​
make.width.height.equalTo(self.containerView).multipliedBy(0.5);​
}];​
​
[self.containerView addSubview:self.thirdRemoteView];​
[self.thirdRemoteView mas_makeConstraints:^(MASConstraintMaker *make) {​
make.bottom.right.equalTo(self.containerView);​
make.width.height.equalTo(self.containerView).multipliedBy(0.5);​
}];​
}​
​
2. 引入头文件​
在用到 SDK API 的文件中引入头文件。​
​
#import <VolcEngineRTC/objc/ByteRTCEngine.h>​
#import <VolcEngineRTC/objc/ByteRTCRoom.h>​
​
3. 创建引擎 createRTCEngine​
​
+ (ByteRTCEngine * _Nullable) createRTCEngine:(ByteRTCEngineConfig * _Nonnull) config​
delegate:(id<ByteRTCEngineDelegate> _Nullable)delegate;​
​
首先你需要调用类 ByteRTCEngine 中的 createRTCEngine:delegate:parameters: 接口,创建一个引擎实例,以使用 RTC 提供的各种音视频能力。​
你需要在该方法中传入以下参数:​
​
参数名​
类型​
说明​
config​
ByteRTCEngineConfig*​
创建引擎参数配置,其中 appid 是每个应用的唯一标识符,由 RTC 控制台随机生成的。​
不同的 AppId 生成的实例在 RTC 中进行音视频通话完全独立,无法互通。​
delegate​
id<ByteRTCEngineDelegate>​
SDK 回调给应用层的 delegate,详见ByteRTCEngineDelegate​
​
4. 设置本地视图 setLocalVideoCanvas​
​
- (int)setLocalVideoCanvas:(ByteRTCVideoCanvas * _Nullable)canvas;​
​
加入房间前,你需要设置本地视图以在通话中看到本地图像。​
你需要在该方法中传入以下参数:​
​
参数名​
类型​
说明​
canvas​
ByteRTCVideoCanvas*​
视图信息和渲染模式,参看 ByteRTCVideoCanvas​
​
5. 开始视频采集 startVideoCapture​
​
- (void)startVideoCapture;​
​
创建引擎实例后,你需要开启视频采集,以在通话中使用视频功能。​
6. 开始音频采集 startAudioCapture​
​
- (void)startAudioCapture;​
​
创建引擎实例后,你需要开启音频采集,以在通话中使用音频功能。​
7. 创建房间实例 createRTCRoom​
​
- ( ByteRTCRoom * _Nullable)createRTCRoom:(NSString * _Nonnull)roomId;​
​
创建一个房间实例,以使用房间相关的功能。​
roomId 应符合正则表达式:[a-zA-Z0-9_@\-]{1,128}。​
8. 设置房间回调事件 handler setRTCRoomDelegate​
​
- (int)setRTCRoomDelegate:(id<ByteRTCRoomDelegate> _Nullable)roomDelegate;​
​
你需要在该方法中传入以下参数:​
​
参数名​
类型​
说明​
roomDelegate​
id<ByteRTCRoomDelegate>​
参看 ByteRTCRoomDelegate。​
​
此方法的返回值可能为:​
​
返回值​
意义​
0​
成功​
!0​
失败,参看 ByteRTCReturnStatus 在这里添加链接​
​
​
- (int)joinRoom:(NSString *_Nullable)token userInfo:(ByteRTCUserInfo *_Nonnull)userInfo userVisibility:(BOOL)userVisibility roomConfig:(ByteRTCRoomConfig *_Nonnull)roomConfig;​
​
创建房间实例后,你就可以调用 ByteRTCRoom 类中的 joinRoom:userInfo:roomConfig: 方法创建/加入房间。​
你需要在该方法中传入以下参数:​
​
参数名​
类型​
说明​
token​
NSString*​
动态密钥,用于对进房用户进行鉴权验证。​
进入房间需要携带 Token。测试时可使用控制台生成临时 Token,正式上线需要使用密钥 SDK 在你的服务端生成并下发 Token。​
使用不同 AppID 的 App 是不能互通的。​
请务必保证生成 Token 使用的 AppID 和创建引擎时使用的 AppID 相同,否则会导致加入房间失败。​
userInfo​
ByteRTCUserInfo*​
用户 ID。参看 ByteRTCUserInfo。​
userVisibility​
BOOL​
表示用户是否可见。建议在进入房间时将用户可见性设置为 false,然后在用户需要发送音视频流时通过 setUserVisibility 将其设置为 true。当 RTC 房间中的用户数量达到上限时,此操作将失败。一个 RTC 房间最多可容纳 50 个可见用户,并且可以同时发布 30 路媒体流。更多信息,请参见使用限制。​
roomConfig​
ByteRTCRoomConfig*​
房间参数配置,设置房间模式以及是否自动发布或订阅流。具体配置模式参看 ByteRTCRoomConfig。​
​
此方法的返回值可能为:​
​
返回值​
意义​
0​
成功​
1​
参数不合法​
2​
已经在房间内​
​
10. 处理房间状态改变回调 onRoomStateChanged​
​
- (void)rtcRoom:(ByteRTCRoom *_Nonnull)rtcRoom ​
onRoomStateChanged:(NSString *_Nonnull)roomId​
withUid:(nonnull NSString *)uid​
state:(NSInteger)state​
extraInfo:(NSString *_Nonnull)extraInfo;​
​
加入房间后,你需要在此回调中处理首次加入房间/重连加入房间的事件。​
回调参数说明:​
​
参数名​
类型​
说明​
rtcRoom​
ByteRTCRoom*​
ByteRTCRoom 对象。​
roomId​
NSString*​
房间 ID​
uid​
NSString*​
用户 ID​
state​
NSInteger​
房间状态码。​
• 0: 成功。​
• !0: 失败,具体原因参看 ByteRTCErrorCode 及 ByteRTCWarningCode。​
extraInfo​
NSString*​
额外信息,如 {"elapsed":1187,"join_type":0}。其中,​
joinType 表示加入房间的类型,0为首次进房,1为重连进房。​
elapsed 表示加入房间耗时,即本地用户从调用 joinRoom:userInfo:roomConfig: 到加入房间成功所经历的时间间隔,单位为 ms。​
​
11. 处理远端用户加入房间的回调 onUserJoined​
​
- (void)rtcRoom:( ByteRTCRoom *_Nonnull)rtcRoom onUserJoined:(ByteRTCUserInfo *_Nonnull)userInfo;​
​
加入房间后,你需要在此回调中处理远端用户加入房间的事件。​
回调参数说明:​
​
参数名​
类型​
说明​
rtcRoom​
ByteRTCRoom*​
ByteRTCRoom 对象。​
userInfo​
ByteRTCUserInfo*​
用户信息,参看 ByteRTCUserInfo。​
​
12. 处理远端视频首帧解码的回调 onFirstRemoteVideoFrameDecoded​
​
- (void)rtcEngine:(ByteRTCEngine * _Nonnull)engine onFirstRemoteVideoFrameDecoded:(NSString * _Nonnull)streamId info:(ByteRTCStreamInfo* _Nonnull)info withFrameInfo:(ByteRTCVideoFrameInfo * _Nonnull)frameInfo;​
​
加入房间后,你需要在此回调中处理第一帧远端视频流解码成功后的事件。​
回调参数说明:​
​
参数名​
类型​
说明​
engine​
ByteRTCEngine*​
ByteRTCVideo 对象​
streamId​
NSString*​
远端流ID​
info​
ByteRTCStreamInfo*​
远端流的信息,参看ByteRTCStreamInfo 添加链接​
frameInfo​
ByteRTCVideoFrameInfo*​
视频帧信息,参看 ByteRTCVideoFrameInfo​
​
13. 设置远端视图 setRemoteVideoCanvas:withCanvas:​
​
- (int)setRemoteVideoCanvas:(NSString* _Nonnull)streamId​
withCanvas:(ByteRTCVideoCanvas * _Nullable)canvas;​
​
在确认收到远端用户的第一帧视频解码回调后,你需要设置远端视图以在通话中查看远端图像。​
你需要在该方法中传入以下参数:​
​
参数名​
类型​
说明​
streamId​
NSString*​
远端流ID​
canvas​
ByteRTCVideoCanvas*​
视图信息和渲染模式,参看 ByteRTCVideoCanvas​
​
14. 处理远端用户离开房间的回调 onUserLeave​
​
- (void)rtcRoom:( ByteRTCRoom*_Nonnull)rtcRoom onUserLeave:(NSString*_Nonnull)uid reason:(ByteRTCUserOfflineReason)reason;​
​
加入房间后,你需要在此回调中处理远端用户离开房间的事件。​
回调参数说明:​
​
参数名​
类型​
说明​
uid​
NSString*​
离开房间的远端用户 ID 。​
reason​
ByteRTCUserOfflineReason​
用户离开房间的原因,参看 ByteRTCUserOfflineReason。​
​
15. 离开房间 leaveRoom​
​
- (int)leaveRoom;​
​
在结束通话等场景下,你需要调用 leaveRoom 离开房间,结束通话过程,释放所有通话相关的资源。​
此方法的返回值可能为:​
​
返回值​
意义​
0​
成功​
​
如果用户是主持人(host)的话,房间中的其他用户将收到 rtcRoom:onUserLeave:reason: 回调。流将会停止发布。房间中的其他用户将收到 rtcRoom:onVideoPublishStateChanged:Uid:state:reason:、rtcRoom:onAudioPublishStateChanged:Uid:state:reason:、rtcRoom:onScreenVideoPublishStateChanged:Uid:state:reason: 和/或 rtcRoom:onScreenAudioPublishStateChanged:Uid:state:reason: 回调通知。​
​
在用户离开房间后,其他用户将收到 rtcRoom:onUserLeave:reason: 回调通知。​
<0​
失败,参看 ByteRTCReturnStatus​
​
在用户离开房间后,本地客户端将收到 rtcRoom:onRoomStateChanged:withUid:state:extraInfo: 的回调。​
您需要调用 setUserVisibility: 来让自己变得可见。​
16. 销毁引擎实例 destroyRTCEngine​
​
+ (void)destroyRTCEngine;​
​
在 RTC 引擎实例相关的业务场景全部结束后,你可调用 destroyRTCEngine 销毁由 createRTCEngine:delegate: 所创建引擎实例,并释放所有相关资源。​
至此,我们实现了基本的音视频通话。​
后续步骤​
在实现音视频通话后,如遇无声音、无画面、视频卡顿等问题时,您可以使用诊断工具快速排查和定位异常房间及用户,并获取异常根因分析、处理建议、分析报告等。​
​
最近更新时间:2026.09.21 16:42:01
这个页面对您有帮助吗?
有用
有用
无用
无用