最近我做了一个关于直播的项目,直播功能不太复杂,主要是给我们内部的主播和嘉宾使用,其中包括音频直播和视频直播,不需要上线。但是在集成腾讯云视频SDK的时候,遇到了比较多的坑,在和腾讯云的工程师进行深入的交流和连环夺命催之后,也算是解决了问题,现在记录一下,给有需要的朋友做使用。
腾讯云视频官方文档地址为:腾讯云官方文档,官方SDk下载地址,我这里使用的是比较轻量级的直播精简版,如果是专门主打直播App的童鞋可以下载直播专业版。
直播的主要思路是:在用户登录成功之后,会出现已经配置好的直播间,直播间设置有密码,主播和嘉宾分别使用不能的密码进入直播间,当主播点击了对应的直播间之后:
1.创建liveRoom
liveRoom = [[LiveRoom alloc]init];
_liveRoom.delegate = self;
2.请求服务器接口获取此次登陆的loginInfo信息
3.liveRoom登陆
[weakSelf.liveRoom login:kHttpServerAddrDomain loginInfo:loginInfo withCompletion:^(int errCode, NSString *errMsg) {
//在此处获取成功的回调之后,push出直播间的类,我这里是分成两个类,主播和嘉宾各用一个,分别是腾讯LiveRoom组件中的
LiveRoomPusherViewController 和 LiveRoomPlayerViewController。
}];
4.成功跳转到直播界面LiveRoomPusherViewController 和 LiveRoomPlayerViewController之后,就可以按照自己公司的需求对这两个界面进行优化和调整了
5.在LiveRoom类中,更换获取推流地址的方法,liveRoom类提供了一个方法,这这里面获取我们自己后台的推流地址
- (void)getUrlAndPushing:(IGetUrlAndPushingCompletionHandler)completion {
// 请求自己公司的推流地址并保存回调
// 获取成功之后,启动推流
dispatch_async(dispatch_get_main_queue(), ^{
[_livePusher startPush:_pushUrl];
});
}
6.上面的这个方法,会在主播和嘉宾对应的方法中进行调用,启动推流
主播的:
- (void)createRoom:(NSString *)roomID roomInfo:(NSString *)roomInfo withCompletion:(ICreateRoomCompletionHandler)completion {
[self asyncRun:^{
_roomID = roomID;
_roomInfo.roomInfo = roomInfo;
_createRoomCompletion = completion;
[self getUrlAndPushing:completion];
}];
}
嘉宾的:
- (void)joinPusher:(IJoinPusherCompletionHandler)completion {
//对应操作
}
7.在嘉宾退出房间之后,调用exitRoom方法
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if (_liveRoom) {
[_liveRoom exitRoom:^(int errCode, NSString *errMsg) {
NSLog(@"exitRoom: errCode[%d] errMsg[%@]", errCode, errMsg);
}];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
8.在主播退出房间之后,调用exitRoom并且调用登出
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if (_liveRoom) {
if (_pkStatus == PKStatus_BEING) {
for (id userID in _playerViewDic) {
[_liveRoom sendPKFinishRequest:userID];
}
}
[_liveRoom exitRoom:^(int errCode, NSString *errMsg) {
NSLog(@"exitRoom: errCode[%d] errMsg[%@]", errCode, errMsg);
}];
[_liveRoom logout:nil];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
至此,直播就已经可以跑通了,下面说一下直播过程之中遇到的坑。
二、关于音频直播的坑
我们项目中有音频直播的需求,就是主播创建房间,嘉宾连入之后进行音频直播,不需要视频直播。
1.纯音频推流
官方文档给的纯音频推流的方法是,给推流配置设置属性
TXLivePushConfig * config = _livePusher.config;
config.enablePureAudioPush = YES;
但是我们测试过程中,如果这样总是音频直播会自动断开,去到TXLivePushListener类中的监听方法,回调一个Disconnect的事件。
-(void) onPushEvent:(int)EvtID withParam:(NSDictionary*)param {
if (EvtID == PUSH_ERR_NET_DISCONNECT) {
}
}
这个过程是SDk自动进行的,我们没法修改,所以这个问题困扰我们了很久都没有找到解决的方法,最后经过连环夺命催和腾讯云的SDK开发人员反映之后,才知道需要设置一个他们文档上没有写的一个属性。
config.customModeType = CUSTOM_MODE_VIDEO_CAPTURE;
这个属性是一个枚举值
#define CUSTOM_MODE_AUDIO_CAPTURE 0X001 //客户自定义音频采集
#define CUSTOM_MODE_VIDEO_CAPTURE 0X002 //客户自定义视频采集
#define CUSTOM_MODE_AUDIO_PREPROCESS 0X004 //客户自定义音频预处理逻辑
#define CUSTOM_MODE_VIDEO_PREPROCESS 0X008 //客户自定义视频预处理逻辑
注意在_liveRoom中有好几个处相关的配置,都需要一一更改。
2.关闭总提醒是调用相机的权限的提示
在LiveRoomPlayerViewController中取消开启摄像头预览的功能,就不会调取摄像头权限了。
[_liveRoom startLocalPreview:_pusherView];
2.主播创建房间成功之后获取roomID
需要注意的是,LiveRoom类中提供的主播创建LiveRoom的CreatRoom方法,是没有创建成果的RoomID的回调的,需要自己在LiveRoom中定义一个RoomID属性进行赋值。
- (void)createRoom:(NSString *)roomID roomInfo:(NSString *)roomInfo withCompletion:(ICreateRoomCompletionHandler)completion {
[self asyncRun:^{
_roomID = roomID;
_roomInfo.roomInfo = roomInfo;
_createRoomCompletion = completion;
[self getUrlAndPushing:completion];
}];
}
这样,就可以在createRoom成功之后,通过_liveRoom.roomID拿到创建成功的RoomID去做一些操作了,比如书提交给后台进行保存,在嘉宾进入之后避免重复创建。
3.退出的时候logout 和 置nil
如果你像腾讯云的demo中一样,用到了 _liveRoom = nil;
那么,请务必保证,你是在调用了ExitRoom和Logout方法之后,才将 _liveRoom 置为nil的,否则LiveRoom将不能正常的退出和释放,会造成内存泄漏。
二、关于安卓端音频直播的坑
我们的安卓端在进行此项目的时候,出现了带耳机直播不成功的BUG,带上耳机后,不能正常使用麦克风,经我们的研究和排查,最后发现是TypeC接口的耳机的BUG,腾讯官方也确定了他们的SDK确实存在这个BUG,会在2周左右的下一个安卓版本修复。
三、关于视频直播遇到的坑
在进行视频直播时候,使用到了嘉宾端进行美颜的功能,当时咨询腾讯云的工程师,他们回复说嘉宾端不具有美颜的功能。但是当我把主播端用到的美颜组件复制到嘉宾端的时候,其实是可以进行美颜的,嘉宾端和主播端都可以,这里只需要把LiveRoomPusherViewController中相关BeautySettingPanel组件的代码复制到LiveRoomPlayerViewController中就可以了,就不给大家展示了。