简介
移动直播 TXLiteAVSDK 有两个基本组件
- TXLivePusher 上行推流
- TXLivePlayer 下行拉流
您可以为 LivePusher 对象绑定一个 TXLivePushListener, 之后 SDK 的内部推流状态信息均会通过 onPushEvent(事件通知) 和 onNetStatus(状态反馈) 通知给您
为 TXLivePlayer 对象绑定一个 TXLivePlayListener, 之后 SDK 的内部播放状态信息均会通过 onPlayEvent(事件通知) 和 onNetStatus(状态反馈) 通知给您
场景
主播开启直播过程中, 可能会遇到以下情况, 如推流一直不成功, 因网络波动导致断流了. App 一般都会在 UI 上通过一些提示语来提示主播. 我们移动直播 SDK 有完整的事件回调, 开发者可以根据不同事件回调来提示主播.
解决方案
Android
1, 实现 ITXLivePushListener 接口 并实现 onPushEvent() 和 onNetStatus() 方法
2, 在 onPushEvent() 监听推流事件
- public class LivePublisherActivity extends Activity implements ITXLivePushListener{
- private TXLivePusher mLivePusher;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mLivePusher = new TXLivePusher(this);
- //TODO
- }
- // 点击开始推流, 推流组件绑定监听
- private boolean startPublishRtmp() {
- mLivePusher.setPushListener(this);
- //TODO
- mLivePusher.startPusher(url);
- }
- @Override
- public void onPushEvent(int event, Bundle param) {
- String msg = param.getString(TXLiveConstants.EVT_DESCRIPTION);
- String pushEventLog = "receive event:" + event + "," + msg;
- Log.d(TAG, pushEventLog);
- // 错误还是要明确的报一下
- if (event < 0) {
- Toast.makeText(getApplicationContext(), param.getString(TXLiveConstants.EVT_DESCRIPTION), Toast.LENGTH_SHORT).show();
- if(event == TXLiveConstants.PUSH_ERR_OPEN_CAMERA_FAIL || event == TXLiveConstants.PUSH_ERR_OPEN_MIC_FAIL){
- // 打开摄像头或麦克风失败, 停止推流
- stopPublishRtmp();
- }
- }
- if (event == TXLiveConstants.PUSH_ERR_NET_DISCONNECT || event == TXLiveConstants.PUSH_ERR_INVALID_ADDRESS) {
- // 推流请求被后台拒绝, 获取获取不到服务器地址, 停止推流
- stopPublishRtmp();
- }
- else if (event == TXLiveConstants.PUSH_WARNING_HW_ACCELERATION_FAIL) {
- // 提示使用硬件编码失败, 切换为软编
- Toast.makeText(getApplicationContext(), param.getString(TXLiveConstants.EVT_DESCRIPTION), Toast.LENGTH_SHORT).show();
- mLivePushConfig.setHardwareAcceleration(TXLiveConstants.ENCODE_VIDEO_SOFTWARE);
- mBtnHWEncode.setBackgroundResource(R.drawable.quick2);
- mLivePusher.setConfig(mLivePushConfig);
- mHWVideoEncode = false;
- }
- else if (event == TXLiveConstants.PUSH_ERR_SCREEN_CAPTURE_UNSURPORT) {
- // 该设置不支持录屏推流, 停止推流
- stopPublishRtmp();
- }
- else if (event == TXLiveConstants.PUSH_ERR_SCREEN_CAPTURE_START_FAILED) {
- // 获取屏幕画面失败, 停止录屏推流
- stopPublishRtmp();
- } else if (event == TXLiveConstants.PUSH_EVT_CHANGE_RESOLUTION) {
- // 分辨率改变 (开启动态分辨率才会收到)
- Log.d(TAG, "change resolution to" + param.getInt(TXLiveConstants.EVT_PARAM2) + ", bitrate to" + param.getInt(TXLiveConstants.EVT_PARAM1));
- } else if (event == TXLiveConstants.PUSH_EVT_CHANGE_BITRATE) {
- // 码率改变 (开启动态码率才会收到)
- Log.d(TAG, "change bitrate to" + param.getInt(TXLiveConstants.EVT_PARAM1));
- } else if (event == TXLiveConstants.PUSH_WARNING_NET_BUSY) {
- // 警告级别, 提示主播网络不给力
- } else if (event == TXLiveConstants.PUSH_EVT_START_VIDEO_ENCODER) {
- // 输出编码方式 (硬编还是软编)
- int encType = param.getInt(TXLiveConstants.EVT_PARAM1);
- mHWVideoEncode = (encType == 1);
- mBtnHWEncode.getBackground().setAlpha(mHWVideoEncode ? 255 : 100);
- }
- }
- @Override
- public void onNetStatus(Bundle status) {
- //TODO
- }
- }
- iOS
1, 实现 ITXLivePushListener 代理 并实现 onPushEvent() 和 onNetStatus() 方法
2, 在 onPushEvent() 监听推流事件
- // RTMP 推流事件通知
- #pragma - TXLivePushListener
- - (void)onPushEvent:(int)EvtID withParam:(NSDictionary *)param; {
- NSDictionary *dict = param;
- dispatch_async(dispatch_get_main_queue(), ^{
- if (EvtID == PUSH_ERR_NET_DISCONNECT || EvtID == PUSH_ERR_INVALID_ADDRESS) {
- [self clickPublish:_btnPublish];
- } else if (EvtID == PUSH_WARNING_HW_ACCELERATION_FAIL) {
- _txLivePublisher.config.enableHWAcceleration = false;
- [_btnHardware setImage:[UIImage imageNamed:@"quick2"] forState:UIControlStateNormal];
- } else if (EvtID == PUSH_ERR_OPEN_CAMERA_FAIL) {
- [self stopRtmp];
- [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];
- _publish_switch = NO;
- [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
- [self toastTip:@"获取摄像头权限失败, 请前往隐私 - 相机设置里面打开应用权限"];
- } else if (EvtID == PUSH_ERR_OPEN_MIC_FAIL) {
- [self stopRtmp];
- [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];
- _publish_switch = NO;
- [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
- [self toastTip:@"获取麦克风权限失败, 请前往隐私 - 麦克风设置里面打开应用权限"];
- } else if (EvtID == PUSH_EVT_CONNECT_SUCC) {
- BOOL isWifi = [AFNetworkReachabilityManager sharedManager].reachableViaWiFi;
- if (!isWifi) {
- __weak __typeof(self) weakSelf = self;
- [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
- if (weakSelf.pushUrl.length == 0) {
- return;
- }
- if (status == AFNetworkReachabilityStatusReachableViaWiFi) {
- UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"" message:@" 您要切换到 WiFi 再推流吗?"
- preferredStyle:UIAlertControllerStyleAlert];
- [alert addAction:[UIAlertAction actionWithTitle:@"是" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
- [alert dismissViewControllerAnimated:YES completion:nil];
- [weakSelf.txLivePublisher stopPush];
- [weakSelf.txLivePublisher startPush:weakSelf.pushUrl];
- }]];
- [alert addAction:[UIAlertAction actionWithTitle:@"否" style:UIAlertActionStyleCancel handler:^(UIAlertAction *_Nonnull action) {
- [alert dismissViewControllerAnimated:YES completion:nil];
- }]];
- [weakSelf presentViewController:alert animated:YES completion:nil];
- }
- }];
- }
- } else if (EvtID == PUSH_WARNING_NET_BUSY) {
- [_notification displayNotificationWithMessage:@"您当前的网络环境不佳, 请尽快更换网络保证正常直播" forDuration:5];
- }
- }
原理
使用移动直播 SDK 推流成功, SDK 回调事件如下:
使用移动直播 SDK 推流成功, 但是过段时间因网络波动, SDK 重连三次依然无法重新推流. SDK 回调事件如下:
移动直播 SDK 中推流对象 TXLivePusher 的内部原理, 如下图
其他
如果您想了解更多的事件处理, 见移动直播官网的事件处理文档
如果您想查看 SDK 中完整的事件回调, 见文档
来源: https://www.qcloud.com/developer/article/1399390