互动直播简介
TRTC低延时互动直播,单房间支持10万观众同时在线,50个主播同时连麦(Web端为20人)。主播与主播延时300ms,主播与观众端到端延时<1秒。观众可以无缝上下麦,平滑切换不等待。
适用场景
适用于大班课、语聊房、在线KTV、互动直播、狼人杀桌游、相亲约会等场景。
支持互动内容
- 主播创建新的直播间开播,观众进入直播间观看。
- 主播和观众进行视频连麦互动。
- 两个不同房间的主播 PK 互动。
- 支持发送各种文本消息和自定义消息,自定义消息可用于实现弹幕、点赞和礼物。
原理解析
TRTC 云服务由两种不同类型的服务器节点组成,分别是“接口机”和“代理机”:
- 接口机 该类节点都采用最优质的线路和高性能的机器,善于处理端到端的低延时连麦通话,单位时长计费较高。
- 代理机 该类节点都采用普通的线路和性能一般的机器,善于处理高并发的拉流观看需求,单位时长计费较低。
在直播模式下,TRTC 引入了角色的概念,用户被分成“主播”和“观众”两种角色,“主播”会被分配到接口机上,“观众”则被分配在代理机,同一个房间的观众人数上限为10万人。
如果“观众”要上麦,需要先切换角色(switchRole)为“主播”才能发言。切换角色的过程也伴随着用户从代理机到接口机的迁移,TRTC 特有的低延时观看技术和平滑上下麦切换技术,可以让整个切换时间变得非常短暂。
官方Demo文件夹
TRTCLiveRoomDemo 文件夹包含两个子文件夹 ui 和 model,model 文件夹中包含可重用的开源组件 TRTCLiveRoom,您可以在TRTCLiveRoom.swift
文件中看到该组件提供的接口函数,并使用对应接口实现自定义 UI 界面。
Demo文件夹功能描述
文件或文件夹 | 功能描述 |
---|---|
Anchor | 主播端相关 UI 的实现代码。 |
Audience | 观众端相关 UI 的实现代码。 |
ChatRoom | 文字聊天室以及弹幕消息的 UI 实现代码。 |
Common | 可复用的一些 UI 组件的实现代码。 |
StatusView | 状态浮层,会覆盖在视频画面上面,用于显示日志信息和视频加载动画。 |
LiveRoomMainViewController.swift | 视频互动直播主页面 UI。 |
集成依赖的SDK
TRTC SDK
IM SDK
通过Demo查看使用步骤API
主播端
Demo的主播端UI文件夹是Anchor,下面我们来查看主播端新建房间的流程。
主播端新建房间准备
新建房间是TCAnchorViewController控制器,在VC初始化后分别进行
- 初始化连麦窗口
- (void)initStatusInfoView: (int)index;
2. 初始化推流模块逻辑view(里面展示了消息列表,弹幕动画,观众列表,美颜,美白等UI)
代码语言:javascript复制_logicView = [[TCAnchorToolbarView alloc] initWithFrame:self.view.frame];
3. 推流模块逻辑view设置直播房间信息
代码语言:javascript复制[_logicView setLiveRoom:_liveRoom];
4. 初始化美颜模块,设置默认值
代码语言:objective-c复制_logicView.vBeauty.actionPerformer = [[BeautyPerformer alloc] initWithLiveRoom:_liveRoom];
[_logicView.vBeauty resetAndApplyValues];
_beauty_level = _logicView.vBeauty.beautyLevel;
_whitening_level = _logicView.vBeauty.whiteLevel;
_ruddiness_level = _logicView.vBeauty.ruddyLevel;
5. 开启本地摄像头预览
代码语言:objective-c复制[self startPreview];
6. 准备推送、添加底部按钮等
代码语言:objective-c复制[self initRoomPreview];
Demo提供的页面为(模拟器没有摄像头会提示Camera is not available on simulator)
需要我们先写一个直播间的名称、选择音质也可以提前设置好美颜效果(右下角)。
在填写ok,点击开始直播后我们查看下调用了组件和TRTC SDK的哪些API。
1. 创建房间
代码语言:objective-c复制/// 创建房间(主播调用),若房间不存在,系统将自动创建一个新房间。
/// 主播开播的正常调用流程是:
/// 1.【主播】调用 startCameraPreview() 打开摄像头预览,此时可以调整美颜参数。
/// 2.【主播】调用 createRoom() 创建直播间,房间创建成功与否会通过 callback 通知给主播。
/// 3.【主播】调用 startPublish() 开始推流。
/// - Parameters:
/// - roomID: 房间标识,需要由您分配并进行统一管理。多个 roomid 可以汇总成一个直播间列表,腾讯云暂不提供直播间列表的管理服务,请自行管理您的直播间列表。
/// - roomParam: TRTCCreateRoomParam | 房间信息,用于房间描述的信息,例如房间名称,封面信息等。如果房间列表和房间信息都由您自行管理,可忽略该参数。
/// - callback: 进入房间的结果回调,成功时 code 为0。
/// - Note:
/// - 主播开始直播的时候调用,可重复创建自己已创建过的房间。
- (void)createRoomWithRoomID:(UInt32)roomID
roomParam:(TRTCCreateRoomParam *)roomParam
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(createRoom(roomID:roomParam:callback:));
2. 房间创建成功(code 为0)后,为房间设置音质,以主播的身份进入房间、开始采集音频、向腾讯云CDN推流
设置音质(前面创建房间是选择的音质)
代码语言:objective-c复制[self.liveRoom setAudioQuality:2];
开始推流
代码语言:objective-c复制[self.liveRoom startPublishWithStreamID:streamID callback:^(int code, NSString * error) {
NSLog(@"%ld",(long)code);
}];
设置视频编码器相关参数 - 分辨率、码率、采集帧率
代码语言:objective-c复制TRTCVideoEncParam *videoParam = [[TRTCVideoEncParam alloc] init];
videoParam.videoResolution = TRTCVideoResolution_960_540;
videoParam.videoBitrate = 1200;
videoParam.videoFps = 15;
[[TRTCCloud sharedInstance] setVideoEncoderParam:videoParam];
以主播的身份进入房间
代码语言:objective-c复制[self enterRoomWithRoomID:self.roomId userId:self.userId role:TRTCRoleAnchor];
开始采集音频
代码语言:objective-c复制[[TRTCCloud sharedInstance] startLocalAudio];
向腾讯云CDN推流
代码语言:objective-c复制[[TRTCCloud sharedInstance] startPublishing:streamId type:TRTCVideoStreamTypeBig];
3. 直播间内的聊天信息、切换摄像头、主播连麦PK、美颜、音效设置
聊天信息
聊天信息、进入离开房间信息通过TCMsgListTableView来展示,弹幕通过TCMsgBarrageView来展示。
发送一条消息
在TCAnchorToolbarView的initUI中创建了一个聊天的按钮_btnChat,点击这个按钮调起键盘并呼出输入框,输入完成后点击发送,在发送前可选弹幕模式。点击发送后调用的API如下:
1. 组装消息模型
代码语言:objective-c复制TCMsgModel *msgModel = [[TCMsgModel alloc] init];
msgModel.userName = @"我";
msgModel.userMsg = textMsg;
msgModel.userHeadImageUrl = [[ProfileManager shared] curUserModel].avatar;
2. 判断是否开启了弹幕模式,如开启弹幕模式使用使用自定义消息方法,未开启在则使用普通消息方法。
代码语言:objective-c复制if (_bulletBtnIsOn) {
msgModel.msgType = TCMsgModelType_DanmaMsg;
[_liveRoom sendRoomCustomMsgWithCommand:[@(TCMsgModelType_DanmaMsg) stringValue] message:textMsg callback:^(int code, NSString * error) {
}];
}else{
msgModel.msgType = TCMsgModelType_NormalMsg;
[_liveRoom sendRoomTextMsg:textMsg callback:^(int code, NSString * error) {
}];
}
两种方法最终都会使用在IMSDK上封装的组件TRTCLiveRoomIMAction发送出去。
自定义消息(弹幕)
代码语言:objective-c复制 (void)sendRoomCustomMsgWithRoomID:(NSString *)roomID command:(NSString *)command message:(NSString *)message callback:(LRIMCallback)callback {
NSDictionary *data = @{
@"action": @(TRTCLiveRoomIMActionTypeRoomCustomMsg),
@"command": command,
@"message": message,
@"version": trtcLiveRoomProtocolVersion,
};
ConversationParams *params = [[ConversationParams alloc] init];
params.type = ConvTypeGroup;
params.gourpID = roomID;
params.text = nil;
params.priority = V2TIM_PRIORITY_LOW;
[TRTCLiveRoomIMAction sendMessage:data convType:params callback:callback];
}
普通消息
代码语言:javascript复制 (void)sendRoomTextMsgWithRoomID:(NSString *)roomID message:(NSString *)message callback:(LRIMCallback)callback {
NSDictionary *data = @{
@"action": @(TRTCLiveRoomIMActionTypeRoomTextMsg),
@"version": trtcLiveRoomProtocolVersion,
};
ConversationParams *params = [[ConversationParams alloc] init];
params.type = ConvTypeGroup;
params.gourpID = roomID;
params.text = message;
params.priority = V2TIM_PRIORITY_LOW;
[TRTCLiveRoomIMAction sendMessage:data convType:params callback:callback];
}
接收一条消息
用户在在直播间内群发一条消息后,每个用户和主播都会受到这条消息,消息响应的类为TRTCLiveRoom,会调用
代码语言:objective-c复制- (void)handleActionMessage:(TRTCLiveRoomIMActionType)action elem:(V2TIMElem *)elem message:(V2TIMMessage *)message json:(NSDictionary<NSString *, id> *)json;
在此方法中处理IM回调回来的消息,找到对应的消息类型后,会调用普通消息
代码语言:objective-c复制(trtcLiveRoom:onRecvRoomTextMsg:fromUser:)
[self.delegate trtcLiveRoom:self onRecvRoomTextMsg:text fromUser:liveUser]
和自定义消息
代码语言:javascript复制(trtcLiveRoom:onRecvRoomCustomMsgWithCommand:message:fromUser:)
[self.delegate trtcLiveRoom:self onRecvRoomCustomMsgWithCommand:command message:message fromUser:liveUser]
的代理方法通过TCAnchorViewController
代码语言:objective-c复制 public func trtcLiveRoom(_ trtcLiveRoom: TRTCLiveRoom, onRecvRoomTextMsg message: String, fromUser user: TRTCLiveUserInfo) {
let info = IMUserAble()
info.imUserId = user.userId
info.imUserName = user.userName
info.imUserIconUrl = user.avatarURL
info.cmdType = TCMsgModelType.normalMsg.rawValue
logicView.handleIMMessage(info, msgText: message)
}
通知到TCAnchorToolbarView的
代码语言:javascript复制- (void)handleIMMessage:(IMUserAble *)info msgText:(NSString *)msgText;
在TCAnchorToolbarView内根据消息类型将消息模型添加进数组内部并刷新列表。
切换摄像头
代码语言:javascript复制[[TRTCCloud sharedInstance] switchCamera];
主播与主播连麦PK
主播和主播之间可以跨房间 PK,两个正在直播中的主播 A 和 B,他们之间的跨房 PK 流程如下:
1. 【主播 A】调用 requestRoomPK() 向主播 B 发起连麦请求。
2. 【主播 B】会收到 TRTCLiveRoomDelegate onRequestRoomPK 回调通知。
3. 【主播 B】调用 responseRoomPK() 确定是否接受主播 A 的 PK 请求。
4. 【主播 B】如果接受了主播 A 的要求,等待 TRTCLiveRoomDelegate onAnchorEnter 通知,然后调用 startPlay() 来显示主播 A 的视频画面。
5. 【主播 A】会收到 responseCallback 回调通知,可以得知请求是否被同意。
6. 【主播 A】如果请求被同意,等待 TRTCLiveRoomDelegate onAnchorEnter 通知,然后调用 startPlay() 来显示主播 B 的视频画面
发起PK请求
发起PK前需要先获取正在直播中的主播房间信息,再从信息中选则一个主播来进行连麦PK。
获取房间信息(此方法与观众获取主播房间列表一至)
代码语言:objective-c复制 [_logicView.vPKPanel loadRoomsInfo];
在选中主播后发起PK请求会使用TRTCLiveRoom调用
代码语言:javascript复制/**
* 请求跨房 PK
*
/// 主播请求跨房 PK
/// - Parameters:
/// - roomID: 被邀约房间 ID。
/// - userID: 被邀约主播 ID。
/// - responseCallback: 请求跨房 PK 的结果回调。
/// - Note: 发起请求后,对方主播会收到 `onRequestRoomPK` 回调
- (void)requestRoomPKWithRoomID:(UInt32)roomID
userID:(NSString *)userID
responseCallback:(ResponseCallback _Nullable)responseCallback
NS_SWIFT_NAME(requestRoomPK(roomID:userID:responseCallback:));
发起PK请求。
接受/拒绝PK请求
主播在收到PK邀请时候会收到 TRTCLiveRoomDelegate onRequestRoomPK 回调通知
代码语言:objective-c复制/// 主播收到其他主播的跨房PK申请
- (void)trtcLiveRoom:(TRTCLiveRoom *)trtcLiveRoom
onRequestRoomPK:(TRTCLiveUserInfo *)user
timeout:(double)timeout
NS_SWIFT_NAME(trtcLiveRoom(_:onRequestRoomPK:timeout:));
TRTCLiveRoom实例方法接受或拒绝PK请求
代码语言:objective-c复制/// 响应跨房 PK 请求
/// 主播响应其他房间主播的 PK 请求。
/// - Parameters:
/// - user: 发起 PK 请求的主播 ID
/// - agree: true:同意;false:拒绝
/// - reason: 同意/拒绝 PK 的原因描述
/// - Note: 主播回复后,对方主播会收到 `requestRoomPK` 传入的 `responseCallback` 回调
- (void)responseRoomPKWithUserID:(NSString *)userID
agree:(BOOL)agree
reason:(NSString *)reason
NS_SWIFT_NAME(responseRoomPK(userID:agree:reason:));
停止直播
主播客通过调用以下方法停止直播销毁房间。停止直播还需要关闭本地视频预览、停止直播推流
代码语言:objective-c复制/// 销毁房间(主播调用)
/// 主播在创建房间后,可以调用这个函数来销毁房间。
/// - Parameter callback: 销毁房间的结果回调,成功时 code 为0。
/// - Note:
/// - 主播在创建房间后,可以调用该函数来销毁房间。
- (void)destroyRoom:(Callback _Nullable)callback
代码语言:javascript复制/// 停止直播(推流),适用于如下两种场景:
/// 1. 主播结束直播时调用
/// 2. 观众结束连麦时调用
/// - Parameter callback: 操作回调。
- (void)stopPublish:(Callback _Nullable)callback
观众端
加入直播间
在直播间列表选择直播间后,拿到直播间信息开始加入直播间
代码语言:objective-c复制/// 进入房间(观众调用)
/// 观众观看直播的正常调用流程是:
/// 1.【观众】向您的服务端获取最新的直播间列表,其中有多个直播间的 roomid 和房间信息。
/// 2.【观众】观众选择一个直播间以后,调用 enterRoom() 进入该房间。
/// 3.【观众】如果您的服务器所管理的房间列表中包含每一个房间的主播 userId,则可以直接在 enterRoom() 成功后调用 startPlay(userId) 即可播放主播的画面。
/// 如果您管理的房间列表只有 roomid 也没有关系,观众在 enterRoom() 成功后很快会收到来自 TRTCLiveRoomDelegate 中的 onAnchorEnter(userId) 回调。
/// 此时使用回调中的 userId 调用 startPlay(userId) 即可播放主播的画面。
/// - Parameters:
/// - roomID: 房间标识。
/// - callback: 进入房间的结果回调,成功时 code 为0。
/// - Note:
/// - 观众进入直播房间的时候调用
/// - 主播不可调用这个接口进入自己已创建的房间,而要用createRoom
- (void)enterRoomWithRoomID:(UInt32)roomID
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(enterRoom(roomID:callback:));
与主播连麦
主播和观众的连麦流程可以简单描述为如下几个步骤:
1. 【观众】调用 requestJoinAnchor() 向主播发起连麦请求。
2. 【主播】会收到 TRTCLiveRoomDelegate onRequestJoinAnchor 的回调通知。
3. 【主播】调用 responseJoinAnchor() 确定是否接受观众的连麦请求。
4. 【观众】会收到 responseCallback 回调通知,可以得知请求是否被同意。
5. 【观众】如果请求被同意,则调用 startCameraPreview() 开启本地摄像头。
6. 【观众】然后调用 startPublish() 正式进入推流状态。
7. 【主播】一旦观众进入连麦状态,主播就会收到 TRTCLiveRoomDelegate onAnchorEnter 通知。
8. 【主播】主播调用 startPlay() 就可以看到连麦观众的视频画面。
9. 【观众】如果直播间里已经有其他观众正在跟主播进行连麦,那么新加入的这位连麦观众也会收到 onAnchorEnter() 通知,调用 startPlay() 播放其他连麦者的视频画面。
发起连麦请求
代码语言:objective-c复制/// 观众端请求连麦
/// - Parameters:
/// - reason: 连麦请求原因。
/// - responseCallback: 请求连麦的回调。
/// - Note: 观众发起请求后,主播端会收到`onRequestJoinAnchor`回调
- (void)requestJoinAnchor:(NSString *)reason
responseCallback:(ResponseCallback _Nullable)responseCallback
NS_SWIFT_NAME(requestJoinAnchor(reason:responseCallback:));
主播端收到观众连麦请求后会回调TRTCLiveRoomDelegate的代理方法
代码语言:objective-c复制/// 主播收到观众的连麦申请
- (void)trtcLiveRoom:(TRTCLiveRoom *)trtcLiveRoom
onRequestJoinAnchor:(TRTCLiveUserInfo *)user
reason:(NSString * _Nullable)reason
timeout:(double)timeout
NS_SWIFT_NAME(trtcLiveRoom(_:onRequestJoinAnchor:reason:timeout:));
主播调用responseJoinAnchor回复观众
代码语言:javascript复制/// 主播回复观众连麦请求
/// - Parameters:
/// - user: 观众 ID。
/// - agree: true:同意;false:拒绝。
/// - reason: 同意/拒绝连麦的原因描述。
/// - Note: 主播回复后,观众端会收到`requestJoinAnchor`传入的`responseCallback`回调
- (void)responseJoinAnchor:(NSString *)userID
agree:(BOOL)agree
reason:(NSString *)reason
NS_SWIFT_NAME(responseJoinAnchor(userID:agree:reason:));
当主播同意或拒绝连麦后,观众端会在发起连麦的回调中得知请求是否被同意,如果被同意观众端则需要调用
代码语言:javascript复制/// 开启本地视频的预览画面
/// - Parameters:
/// - frontCamera: true:前置摄像头;false:后置摄像头。
/// - view: 承载视频画面的控件。
/// - callback: 操作回调。
- (void)startCameraPreviewWithFrontCamera:(BOOL)frontCamera
view:(UIView *)view
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(startCameraPreview(frontCamera:view:callback:));
开启本视频预览及推流,在开始推流前通过TRTCCloudAnction将观众的身份切换为主播
代码语言:objective-c复制[self.trtcAction switchRole:TRTCRoleAnchor];
代码语言:objective-c复制/// 开始直播(推流),适用于如下两种场景:
/// 1. 主播开播的时候调用
/// 2. 观众开始连麦时调用
/// - Parameters:
/// - streamID: 用于绑定直播 CDN 的 streamId,如果您希望您的观众通过直播 CDN 进行观看,需要指定当前主播的直播 streamId。
/// - callback: 操作回调
- (void)startPublishWithStreamID:(NSString *)streamID
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(startPublish(streamID:callback:));
当观众进入连麦状态后,主播和正在连麦的观众都会会收到TRTCLiveRoomDelegate onAnchorEnter 通知。
代码语言:objective-c复制/// 主播进房回调(观众已切换为主播身份)
/// - Note: 主播包括房间大主播、连麦观众和跨房PK主播
- (void)trtcLiveRoom:(TRTCLiveRoom *)trtcLiveRoom
onAnchorEnter:(NSString *)userID
NS_SWIFT_NAME(trtcLiveRoom(_:onAnchorEnter:));
主播此时调用以下方法来观看观众的视频
代码语言:objective-c复制// 播放远端视频画面,可以在普通观看和连麦场景中调用
/// 【普通观看场景】
/// 1. 如果您的服务器所管理的房间列表中包含每一个房间的主播 userId,则可以直接在 enterRoom() 成功后调用 startPlay(userId) 即可播放主播的画面。
/// 2. 如果您管理的房间列表只有 roomid 也没有关系,观众在 enterRoom() 成功后很快会收到来自 TRTCLiveRoomDelegate 中的 onAnchorEnter(userId) 回调。
/// 此时使用回调中的 userId 调用 startPlay(userId) 即可播放主播的画面。
/// 【直播连麦场景】
/// 发起连麦后,主播会收到来自 TRTCLiveRoomDelegate 中的 onAnchorEnter(userId) 回调,此时使用回调中的 userId 调用 startPlay(userId) 即可播放连麦画面。
/// - Parameters:
/// - userID: 需要观看的用户 ID。
/// - view: 承载视频画面的 view 控件。
/// - callback: 操作回调。
- (void)startPlayWithUserID:(NSString *)userID
view:(UIView *)view
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(startPlay(userID:view:callback:));
观众停止连麦
观众只需要将本地摄像头预览、停止推流即可。
主播踢出连麦观众
代码语言:objective-c复制/// 主播踢除连麦观众
/// - Parameters:
/// - userID: 连麦观众 ID。
/// - callback: 操作回调。
/// - Note: 主播调用此接口踢除连麦观众后,被踢连麦观众会收到 trtcLiveRoomOnKickoutJoinAnchor() 回调通知
- (void)kickoutJoinAnchor:(NSString *)userID
callback:(Callback _Nullable)callback
NS_SWIFT_NAME(kickoutJoinAnchor(userID:callback:));
以上如有错误,欢迎指正!