本文档将帮助开发者使用
AtomicXCore SDK 的 LiveListStore 和 LiveSeatStore 快速构建一个包含主播开播和观众进房功能的语聊房 App。核心概念
在开始集成之前,我们先通过下表了解一下
LiveSeatStore 相关的几个核心概念:核心概念 | 类型 | 核心职责与描述 |
LiveSeatStore | class | 麦位管理核心,负责管理房间内的所有麦位信息和麦位相关操作。 通过 liveSeatState.seatList 暴露实时的麦位列表数据流。 |
LiveSeatState | struct | 代表麦位的当前状态。 seatList :是一个[seatInfo]类型数组,存储了麦位列表的实时状态;speakingUsers :则代表当前正在说话的人和对应的音量。 |
| | |
SeatInfo | struct | 单个麦位的数据模型。 LiveSeatStore 所推送的麦位列表(seatList)就是由多个 SeatInfo 对象组成的。 关键字段: index:麦位的索引(位置)。isLocked :麦位是否被锁定。 userInfo: 麦位上的用户信息。如果麦位为空,此字段也为空对象。 |
SeatUserInfo | struct | 麦上用户的详细数据模型。 当一个用户成功上麦后, SeatInfo 中的 userInfo 字段就会被填充为此用户。 关键字段: userID: 用户的唯一 ID。 userName: 用户的昵称。 avatarURL: 用户的头像 URL。 microphoneStatus: 麦克风状态(开/关)。 cameraStatus: 摄像头状态(开/关)。 |
准备工作
步骤1:开通服务
步骤2:在当前项目中导入 AtomicXCore
1. 安装组件:请在您的 Podfile 文件中添加
pod 'AtomicXCore' 依赖,然后执行pod install。# Podfiletarget 'xxxx' dopod 'AtomicXCore'end
2. 配置工程权限: 请在应用的
Info.plist 文件中添加相机和麦克风的使用权限说明。<key>NSMicrophoneUsageDescription</key><string>TUILiveKit需要访问您的麦克风权限,开启后录制的视频才会有声音</string>

步骤3:实现登录逻辑
在项目中调用
LoginStore.shared.login 完成登录,这是使用 AtomicXCore 所有功能的关键前提。重要:
推荐在您 App 自身的用户账户登录成功后,再调用 LoginStore.shared.login,以确保登录业务逻辑的清晰和一致。
import AtomicXCore// AppDelegate.swiftfunc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {LoginStore.shared.login(sdkAppID: 1400000001, // 替换为您的 SDKAppIDuserID: "test_001", // 替换为您的 UserIDuserSig: "xxxxxxxxxxx") { result in // 替换为您的 UserSigswitch result {case .success(let info):debugPrint("login success")case .failure(let error):debugPrint("login failed code:\\(error.code), message:\\(error.message)")}}return true}
登录接口参数说明:
参数 | 类型 | 说明 |
sdkAppId | Int32 | |
userID | String | 当前用户的唯一 ID,仅包含英文字母、数字、连字符和下划线。为避免多端登录冲突,请勿使用 1、123 等简单 ID。 |
userSig | String | 用于腾讯云鉴权的票据。请注意: 开发环境:您可以采用本地 GenerateTestUserSig.genTestSig 函数生成 userSig 或者通过 UserSig 辅助工具 生成临时的 UserSig。生产环境:为了防止密钥泄露,请务必采用服务端生成 UserSig 的方式。详细信息请参考 服务端生成 UserSig。 |
搭建基础语聊房
步骤1:实现房主创建语聊房
房主开播流程如下,您只需执行以下几步操作,即可快速搭建一个语聊房。
1. 初始化麦位 Store
在您的房主
ViewController 中,创建一个 LiveSeatStore 实例。您需要使用 Combine 框架监听 liveSeatStore.state 的变化,以实时获取麦位数据来渲染您的 UI。import UIKitimport AtomicXCoreimport Combine // 导入 Combine 框架// YourAnchorViewController 代表您的房主 ViewControllerclass YourAnchorViewController: UIViewController {private let liveListStore = LiveListStore.sharedprivate let deviceStore = DeviceStore.shared// 使用 liveID 初始化 LiveSeatStoreprivate let liveID = "test_voice_room_001"private lazy var liveSeatStore = LiveSeatStore.create(liveID: liveID)// 用于管理订阅生命周期private var cancellables = Set<AnyCancellable>()override func viewDidLoad() {super.viewDidLoad()// 假设您有自己的布局// setupUI()// 2. 监听麦位列表变化observeSeatList()}private func observeSeatList() {// 监听 state.seatList 的变化,并更新您的麦位 UIliveSeatStore.state.subscribe(StatePublisherSelector(keyPath: \\LiveSeatState.seatList)) // 仅关心麦位列表.removeDuplicates().receive(on: DispatchQueue.main) // 确保在主线程更新 UI.sink { [weak self] seatInfoList in// 在这里根据 seatInfoList 渲染您的麦位 UI// 例如:self?.updateMicSeatView(seatInfoList)print("Seat list updated: \\(seatInfoList.count) seats")}.store(in: &cancellables) // 管理订阅}}
2. 打开麦克风
通过调用
DeviceStore 的 openLocalMicrophone 接口打开麦克风,示例代码如下:import UIKitimport AtomicXCoreclass YourAnchorViewController: UIViewController {// ... 其他代码 ...private func openDevices() {// 1. 打开麦克风DeviceStore.shared.openLocalMicrophone(completion: nil)}}
3. 开始语聊
通过调用
LiveListStore 的 createLive 接口开始语聊房直播,完整示例代码如下:import UIKitimport AtomicXCoreclass YourAnchorViewController: UIViewController {// ... 其他代码 ...private let liveID = "test_voice_room_001"override func viewDidLoad() {super.viewDidLoad()// ... 其他代码 ...// 开始语聊startLive()}private func startLive() {// 1. 准备 LiveInfo 对象var liveInfo = LiveInfo()// 2. 设置房间 idliveInfo.liveID = liveID// 3. 设置房间名称liveInfo.liveName = "test 语聊房"// 4. 配置为语聊房(启用麦位)liveInfo.isSeatEnabled = true// 5. 房主默认上麦liveInfo.keepOwnerOnSeat = true// 6. 设置麦位布局模板(例如 70 为 10 麦位模板)// 重要:请根据产品规范传入正确的 IDliveInfo.seatLayoutTemplateID = 70// 7. 设置上麦模式,例如申请上麦liveInfo.seatMode = .apply// 8. 设置最大麦位数liveInfo.maxSeatCount = 10// 9. 调用 createLive 开始直播liveListStore.createLive(liveInfo) { [weak self] result inguard let self = self else { return }switch result {case .success(let liveInfo):print("Response startLive onSuccess")// 房主创建成功后,默认会上麦,此时您可以调用 unmuteMicrophoneliveSeatStore.unmuteMicrophone(completion: nil)case .failure(let errorInfo):print("Response startLive onError: \\(errorInfo.message)")}}}}
LiveInfo参数说明:参数名 | 类型 | 属性 | 描述 |
liveID | String | 必填 | 直播间的唯一标识符 |
liveName | String | 选填 | 直播间的标题 |
notice | String | 选填 | 直播间的公告信息 |
isMessageDisable | Bool | 选填 | 是否禁言( true:是,false:否) |
isPublicVisible | Bool | 选填 | 是否公开可见( true:是,false:否) |
isSeatEnabled | Bool | 选填 | 是否启用麦位功能( true:是,false:否) |
keepOwnerOnSeat | Bool | 选填 | 是否保持房主在麦位上 |
maxSeatCount | Int | 必填 | 最大麦位数量 |
seatMode | TakeSeatMode | 选填 | 上麦模式( .free:自由上麦,.apply:申请上麦) |
seatLayoutTemplateID | UInt | 必填 | 麦位布局模板 ID |
coverURL | String | 选填 | 直播间的封面图片地址 |
backgroundURL | String | 选填 | 直播间的背景图片地址 |
categoryList | [NSNumber] | 选填 | 直播间的分类标签列表 |
activityStatus | Int | 选填 | 直播活动状态 |
isGiftEnabled | Bool | 选填 | 是否启用礼物功能( true:是,false:否) |
4. 构建麦位 UI 界面
提示:
通过
LiveSeatStore 实例,监听 state.seatList 的变化,以实时获取麦位数据来渲染您的 UI。您可以在 ViewController 中(例如 YourAnchorViewController 或 YourAudienceViewController)通过以下方式监听数据:import UIKitimport AtomicXCoreimport Combineclass YourAnchorViewController: UIViewController {// ... 其他代码 ...private var cancellables = Set<AnyCancellable>()private lazy var liveSeatStore = LiveSeatStore.create(liveID: "your_live_id")override func viewDidLoad() {super.viewDidLoad()// ... 其他代码 ...// 监听 seatList 变化observeSeatList()}private func observeSeatList() {// 监听 state.seatList 变化,并更新您的麦位 UIliveSeatStore.state.subscribe(StatePublisherSelector(keyPath: \\LiveSeatState.seatList)) // 仅关心麦位列表.removeDuplicates().receive(on: DispatchQueue.main) // 确保在主线程更新 UI.sink { [weak self] seatInfoList in// seatInfoList 即为最新的麦位列表 (List<SeatInfo>)// 在这里根据 seatInfoList 渲染您的麦位 UIprint("Seat list updated: \\(seatInfoList.count) seats")}.store(in: &cancellables)}}
5. 结束语聊
语聊结束后,房主可以调用
LiveListStore 的 endLive 接口结束语聊,SDK 会处理停止推流和销毁房间的逻辑。import UIKitimport AtomicXCoreimport RTCRoomEngine // 导入以获取 TUILiveStatisticsDataclass YourAnchorViewController: UIViewController {// ... 其他代码 ...// 结束语聊private func stopLive() {liveListStore.endLive { result inswitch result {case .success(let data):print("endLive success")case .failure(let errorInfo):print("endLive error: \\(errorInfo.message)")}}}}
步骤2:实现观众进入语聊房
观众进房流程如下,通过简单几步操作,即可实现观众进入语聊房。
1. 初始化麦位 Store
在您的观众
ViewController 中,创建 LiveSeatStore 实例,并监听 state.seatList 的变化,以渲染麦位 UI。import UIKitimport AtomicXCoreimport Combine// YourAudienceViewController 代表您的观众 ViewControllerclass YourAudienceViewController: UIViewController {private let liveListStore = LiveListStore.shared// 确保 liveID 与房主一致private let liveID = "test_voice_room_001"private lazy var liveSeatStore = LiveSeatStore.create(liveID: liveID)// 用于管理订阅生命周期private var cancellables = Set<AnyCancellable>()override func viewDidLoad() {super.viewDidLoad()// 假设您有自己的布局// setupUI()// 2. 监听麦位列表变化observeSeatList()}private func observeSeatList() {// 3. 监听 state.seatList 变化,并更新您的麦位 UIliveSeatStore.state.subscribe(StatePublisherSelector(keyPath: \\LiveSeatState.seatList)) // 仅关心麦位列表.removeDuplicates().receive(on: DispatchQueue.main) // 确保在主线程更新 UI.sink { [weak self] seatInfoList in// 在这里根据 seatInfoList 渲染您的麦位 UI// 例如:self?.updateMicSeatView(seatInfoList)print("AudienceVC Seat list updated: \\(seatInfoList.count) seats")}.store(in: &cancellables)}}
2. 进入语聊房
通过调用
LiveListStore 的 joinLive 接口加入语聊房,完整示例代码如下:import UIKitimport AtomicXCore// YourAudienceViewController 代表您的观众 ViewControllerclass YourAudienceViewController: UIViewController {// ... 其他代码 ...override func viewDidLoad() {super.viewDidLoad()// ... 其他代码 ...// 进入语聊房joinLive()}private func joinLive() {// 1. 调用 joinLive 进入语聊房liveListStore.joinLive(liveID: liveID) { result inDispatchQueue.main.async {switch result {case .success(let liveInfo):print("joinLive success")case .failure(let errorInfo):print("joinLive error: \\(errorInfo.message)")}}}}}
3. 构建麦位 UI 界面
4. 退出语聊房
观众退出语聊房时,需要调用
LiveListStore 的 leaveLive 接口来退出。import UIKitimport AtomicXCore// YourAudienceViewController 代表您的观众 ViewControllerclass YourAudienceViewController: UIViewController {// ... 其他代码 ...private func leaveLive() {liveListStore.leaveLive { result inswitch result {case .success:print("leaveLive success")case .failure(let errorInfo):print("leaveLive error: \\(errorInfo.message)")}}}}
运行效果

功能进阶
实现麦上用户说话音浪
在语聊房场景中,一个常见的需求是当麦上用户说话时,在其头像上显示一个波浪动画,以提示全房间用户“谁在说话”,
LiveSeatStore 提供了 speakingUsers 数据流,专门用于实现此功能。实现效果

实现方式
提示:
在
YourAnchorViewController 或 YourAudienceViewController 中监听 speakingUsers 变化,并更新“正在说话”状态,代码示例如下:import UIKitimport AtomicXCoreimport Combine// 在 YourAnchorViewController 或 YourAudienceViewController 中class YourAnchorViewController: UIViewController {// ... (省略其他代码) ...private var cancellables = Set<AnyCancellable>()override func viewDidLoad() {super.viewDidLoad()// ... (省略其他代码) ...// 监听 speakingUsers 变化observeSpeakingUsersState()}private func observeSpeakingUsersState() {// 监听 state.speakingUsers 变化,并更新“正在说话”状态liveSeatStore.state.subscribe(StatePublisherSelector(keyPath: \\LiveSeatState.speakingUsers)) // 仅关心说话者 map.removeDuplicates().receive(on: DispatchQueue.main) // 确保在主线程更新 UI.sink { [weak self] speakingUserMap in// 将 "正在说话" 的用户 ID 集合 传递给 UI , 更新 UI 状态print("Speaking users updated: \\(speakingUserMap.count) users")}.store(in: &cancellables)}}
丰富语聊房场景
当您完成了基础的语聊房功能后,您可以参考以下功能指南来为语聊房添加丰富的互动玩法。
功能 | 功能介绍 | 功能 Stores | 实现指南 |
实现听众上麦 | 听众申请上麦,与房主进行实时语音互动。 | ||
实现房主跨房连线 PK | 两个不同房间的主播进行连线,实现互动或 PK。 | ||
添加弹幕聊天功能 | 房间内成员可以发送和接收实时文字消息。 | ||
构建礼物赠送系统 | 观众可以向主播赠送虚拟礼物,增加互动和趣味性。 |
API 文档
Store/Component | 功能描述 | API 文档 |
LiveListStore | 直播间全生命周期管理:创建 / 加入 / 离开 / 销毁房间,查询房间列表,修改直播信息(名称、公告等),监听直播状态(如被踢出、结束)。 | |
LiveSeatStore | 麦位管理核心:管理麦位列表、麦上用户状态、麦位相关操作(上麦、下麦、踢人、锁麦、开关麦克风/摄像头等),监听麦位事件。 | |
DeviceStore | 音视频设备控制:麦克风(开关 / 音量)、摄像头(开关 / 切换 / 画质)、屏幕共享,设备状态实时监听。 | |
CoGuestStore | 观众连麦管理:连麦申请 / 邀请 / 同意 / 拒绝,连麦成员权限控制(麦克风 / 摄像头),状态同步。 | |
CoHostStore | 主播跨房连线:支持多布局模板(动态网格等),发起 / 接受 / 拒绝连线,连麦主播互动管理。 | |
BattleStore | 主播 PK 对战:发起 PK(配置时长 / 对手),管理 PK 状态(开始 / 结束),同步分数,监听对战结果。 | |
GiftStore | 礼物互动:获取礼物列表,发送 / 接收礼物,监听礼物事件(含发送者、礼物详情)。 | |
BarrageStore | 弹幕功能:发送文本 / 自定义弹幕,维护弹幕列表,实时监听弹幕状态。 | |
LikeStore | 点赞互动:发送点赞,监听点赞事件,同步总点赞数。 | |
LiveAudienceStore | 观众管理:获取实时观众列表(ID / 名称 / 头像),统计观众数量,监听观众进出事件。 | |
AudioEffectStore | 音频特效:变声(童声 / 男声)、混响(KTV 等)、耳返调节,实时切换特效。 | |
BaseBeautyStore | 基础美颜:调节磨皮 / 美白 / 红润(0-100 级),重置美颜状态,同步效果参数。 |
常见问题
听众调用 joinLive 后为什么没有声音?
检查设备权限:请确保
App 已在 Info.plist 中声明并获得了麦克风的系统使用权限 (NSMicrophoneUsageDescription)。检查房主端:房主端是否正常调用
DeviceStore.shared.openLocalMicrophone(completion: nil) 打开了麦克风。检查网络:请检查设备网络连接是否正常。
为什么麦位列表没有显示或没有更新?
检查 Store 初始化:请确保您在
createLive 或 joinLive 之前,已经使用相同的 liveID 正确创建了 LiveSeatStore 实例 (LiveSeatStore.create(liveID: liveID))。检查数据监听:请检查您是否正确使用了
Combine 框架来订阅 liveSeatStore.state.seatList,并确保 cancellables (订阅管理器) 的生命周期与您的 ViewController 保持一致。检查接口调用:请确保
createLive (房主) 或 joinLive (听众) 接口已成功调用(在 switch result 的 .success 分支中确认)。