阿里云视频直播提供主播PK互动功能,该功能允许两位或多位主播在直播中展开PK,增强观众的观看体验。本文为您介绍主播PK互动的操作步骤和相关示例代码,帮助用户快速接入主播PK互动场景。
主播PK互动方案介绍
直播SDK基于实时音视频RTC来实现主播跨房间PK,帮助客户实现超低延时、更多人数的直播实时互动,主播PK一般流程如下:
PK前:主播们各自用RTC推流地址进行推流,观众拉取CDN流进行观看。
PK中:主播们使用RTC拉流地址进行相互播放对方的超低延时流。
PK后:主播们停止播放对方的超低延时流。
如上图,主播A有普通观众C,主播B有普通观众D,主播A和主播B进行跨房间PK,需要做以下事情:
主播A:主播A使用主播B的拉流地址播放主播B的超低延时流,同时,主播A发起混流操作,将自己和主播B的内容混成一路,供普通观众C观看。
主播B:主播B使用主播A的拉流地址播放主播A的超低延时流,同时,主播B发起混流操作,将自己和主播A的内容混成一路,供普通观众D观看。
观众C和观众D不需要任何额外操作,观看画面自动从单主播画面切换成混流画面。
注意事项
本文介绍推流SDK互动版的主播PK功能使用。
推流SDK互动版的集成,请参见:
步骤一:开通直播连麦服务
具体开通直播连麦功能方式,请参见直播连麦快速入门。
步骤二:生成主播PK互动推拉流地址
您可以通过自定义拼接主播PK互动场景下不同主播端的推拉流地址,以及普通观众(非连麦观众)的CDN播放地址,详细操作,请参见主播PK互动场景不同主播端的推拉流地址和普通观众的CDN播放地址。
步骤三:主播A开始推流
创建AlivcLivePushConfig 推流配置对象
创建AlivcLivePushConfig 推流配置对象,指定当前推流模式livePushMode为AlivcLivePushInteractiveMode,设置分辨率、帧率、码率等配置信息。
重要如果使用场景为Native与Web连麦互通,则Native端(Android/iOS)必须使用H5兼容模式。否则,Web用户查看Native用户将是黑屏。请在Native端调用AlivcLivePushConfig#setH5CompatibleMode接口,接口详细说明请参考Native SDK API文档。
Android示例代码:
// 初始化推流配置类 mAlivcLivePushConfig = new AlivcLivePushConfig(); // 设置推流模式,默认普通推流模式 mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveInteractiveMode); // 设置分辨率,默认540P mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_540P); // 设置帧率,默认20fps mAlivcLivePushConfig.setFps(AlivcFpsEnum.FPS_25); // 设置视频编码Gop,单位秒,默认2秒 mAlivcLivePushConfig.setVideoEncodeGop(AlivcVideoEncodeGopEnum.GOP_TWO); // 打开码率自适应,默认为true mAlivcLivePushConfig.setEnableBitrateControl(true); // 设置横竖屏,默认为竖屏,可设置home键向左或向右横屏 mAlivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT); // 设置音频编码模式,默认AAC-LC mAlivcLivePushConfig.setAudioProfile(AlivcAudioAACProfileEnum.AAC_LC); // 设置视频编码模式,默认硬编 mAlivcLivePushConfig.setVideoEncodeMode(AlivcEncodeModeEnum.Encode_MODE_HARD); // 设置音频编码模式,默认软编 mAlivcLivePushConfig.setAudioEncodeMode(AlivcEncodeModeEnum.Encode_MODE_SOFT); // 设置摄像头前后置,默认前置 mAlivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT); // 设置App推后台或暂停时推图片 mAlivcLivePushConfig.setPausePushImage("TODO: Image Path"); // 设置弱网推图片 mAlivcLivePushConfig.setNetworkPoorPushImage("TODO: Image Path");
iOS示例代码:
AlivcLivePushConfig *rtcPushConfig = [[AlivcLivePushConfig alloc] init]; rtcPushConfig.livePushMode = AlivcLivePushInteractiveMode; rtcPushConfig.resolution = AlivcLivePushResolution540P; rtcPushConfig.fps = AlivcLivePushFPS20; rtcPushConfig.enableAutoBitrate = true; rtcPushConfig.orientation = AlivcLivePushOrientationPortrait; rtcPushConfig.enableAutoResolution = YES;
创建AlivcLivePusher推流对象
创建推流引擎对象AlivcLivePusher,传入上一步创建的AlivcLivePushConfig对象,设置相应的Delegate回调。
Android示例代码:
AlivcLivePusher alivcLivePusher = new AlivcLivePusher(); alivcLivePusher.init(context, alivcLivePushConfig); alivcLivePusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {}); alivcLivePusher.setLivePushInfoListener(new AlivcLivePushInfoListener() {}); alivcLivePusher.setLivePushNetworkListener(new AlivcLivePushNetworkListener() {});
iOS示例代码:
AlivcLivePusher *rtcPusher = [[AlivcLivePusher alloc] initWithConfig:rtcPushConfig]; [rtcPusher setInfoDelegate:self]; [rtcPusher setErrorDelegate:self]; [rtcPusher setNetworkDelegate:self];
连麦PK互动模式下推流
使用连麦PK互动模式下推流地址URL进行推流,推流地址获取方式请参见步骤二:生成主播PK互动推拉流地址。
Android示例代码:
alivcLivePusher.startPreview(context, frameLayout, isAnchor); alivcLivePusher.startPushAysnc("artc://live.aliyun.com/push/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX"); //主播A的推流地址
iOS示例代码:
[rtcPusher startPushWithURL:@"artc://live.aliyun.com/push/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX"]; //主播A的推流地址
windows示例代码:
pusher_->startPush("artc://live.aliyun.com/push/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX");
步骤四:主播B开始推流
创建AlivcLivePushConfig 推流配置对象
创建AlivcLivePushConfig 推流配置对象,指定当前推流模式livePushMode为AlivcLivePushInteractiveMode,设置分辨率、帧率、码率等配置信息。
重要如果使用场景为Native与Web连麦互通,则Native端(Android/iOS)必须使用H5兼容模式。否则,Web用户查看Native用户将是黑屏。请在Native端调用AlivcLivePushConfig#setH5CompatibleMode接口,接口详细说明请参考Native SDK API文档。
Android示例代码:
// 初始化推流配置类 mAlivcLivePushConfig = new AlivcLivePushConfig(); // 设置推流模式,默认普通推流模式 mAlivcLivePushConfig.setLivePushMode(AlivcLiveMode.AlivcLiveInteractiveMode); // 设置分辨率,默认540P mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_540P); // 设置帧率,默认20fps mAlivcLivePushConfig.setFps(AlivcFpsEnum.FPS_25); // 设置视频编码Gop,单位秒,默认2秒 mAlivcLivePushConfig.setVideoEncodeGop(AlivcVideoEncodeGopEnum.GOP_TWO); // 打开码率自适应,默认为true mAlivcLivePushConfig.setEnableBitrateControl(true); // 设置横竖屏,默认为竖屏,可设置home键向左或向右横屏 mAlivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT); // 设置音频编码模式,默认AAC-LC mAlivcLivePushConfig.setAudioProfile(AlivcAudioAACProfileEnum.AAC_LC); // 设置视频编码模式,默认硬编 mAlivcLivePushConfig.setVideoEncodeMode(AlivcEncodeModeEnum.Encode_MODE_HARD); // 设置音频编码模式,默认软编 mAlivcLivePushConfig.setAudioEncodeMode(AlivcEncodeModeEnum.Encode_MODE_SOFT); // 设置摄像头前后置,默认前置 mAlivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_FRONT); // 设置App推后台或暂停时推图片 mAlivcLivePushConfig.setPausePushImage("TODO: Image Path"); // 设置弱网推图片 mAlivcLivePushConfig.setNetworkPoorPushImage("TODO: Image Path");
iOS示例代码:
AlivcLivePushConfig *rtcPushConfig = [[AlivcLivePushConfig alloc] init]; rtcPushConfig.livePushMode = AlivcLivePushInteractiveMode; rtcPushConfig.resolution = AlivcLivePushResolution540P; rtcPushConfig.fps = AlivcLivePushFPS20; rtcPushConfig.enableAutoBitrate = true; rtcPushConfig.orientation = AlivcLivePushOrientationPortrait; rtcPushConfig.enableAutoResolution = YES;
创建AlivcLivePusher推流对象
创建推流引擎对象AlivcLivePusher,传入上一步创建的AlivcLivePushConfig对象,设置相应的Delegate回调。
Android示例代码:
AlivcLivePusher alivcLivePusher = new AlivcLivePusher(); alivcLivePusher.init(context, alivcLivePushConfig); alivcLivePusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {}); alivcLivePusher.setLivePushInfoListener(new AlivcLivePushInfoListener() {}); alivcLivePusher.setLivePushNetworkListener(new AlivcLivePushNetworkListener() {});
iOS示例代码:
AlivcLivePusher *rtcPusher = [[AlivcLivePusher alloc] initWithConfig:rtcPushConfig]; [rtcPusher setInfoDelegate:self]; [rtcPusher setErrorDelegate:self]; [rtcPusher setNetworkDelegate:self];
连麦PK互动模式下推流
使用连麦PK互动模式下推流地址URL进行推流,推流地址获取方式请参见步骤二:生成主播PK互动推拉流地址。
Android示例代码:
alivcLivePusher.startPreview(context, frameLayout, isAnchor); alivcLivePusher.startPushAysnc("artc://live.aliyun.com/push/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX"); //主播B的推流地址
iOS示例代码:
[rtcPusher startPushWithURL:@"artc://live.aliyun.com/push/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX"]; //主播B的推流地址
windows示例代码:
pusher_->startPush("artc://live.aliyun.com/push/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX");
步骤五:开始PK
主播A调用AlivcLivePlayer播放主播B的流;同时,主播B调用AlivcLivePlayer播放主播A的流。
此时,主播A和主播B可以播放对方的实时流,开始进入PK场景。
主播A示例代码:
Android示例代码:
AlivcLivePlayConfig config = new AlivcLivePlayConfig(); config.isFullScreen = isAnchor; AlivcLivePlayer alivcLivePlayer = new AlivcLivePlayerImpl(context, AlivcLiveMode.AlivcLiveInteractiveMode); alivcLivePlayer.setPlayInfoListener(new AlivcLivePlayInfoListener() {}); mAlivcLivePlayer.setupWithConfig(config); mAlivcLivePlayer.setPlayView(frameLayout); alivcLivePlayer.startPlay("artc://live.aliyun.com/play/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX"); //主播B的拉流地址
iOS示例代码:
AlivcLivePlayer *rtcPlayer = [[AlivcLivePlayer alloc] init]; [rtcPlayer setLivePlayerDelegate:self]; [rtcPlayer setPlayView:self.playerView playCofig:self.rtcPlayConfig]; [rtcPlayer startPlayWithURL:@"artc://live.aliyun.com/play/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX"]; //主播B的拉流地址
windows示例代码:
player_ = AlivcLivePlayer::Create(""); if (player_) { AlivcLivePlayConfig config; player_->setupWithConfig(config); player_->startPlay("artc://live.aliyun.com/play/456?timestamp=1661596947&token=XXX&userId=456&sdkAppId=XXX"); player_->setPlayView(hwnd, width, height); }
主播B示例代码:
Android示例代码:
AlivcLivePlayConfig config = new AlivcLivePlayConfig(); config.isFullScreen = isAnchor; AlivcLivePlayer alivcLivePlayer = new AlivcLivePlayerImpl(context, AlivcLiveMode.AlivcLiveInteractiveMode); alivcLivePlayer.setPlayInfoListener(new AlivcLivePlayInfoListener() {}); mAlivcLivePlayer.setupWithConfig(config); mAlivcLivePlayer.setPlayView(frameLayout); alivcLivePlayer.startPlay("artc://live.aliyun.com/play/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX"); //主播A的拉流地址
iOS示例代码:
AlivcLivePlayer *rtcPlayer = [[AlivcLivePlayer alloc] init]; [rtcPlayer setLivePlayerDelegate:self]; [rtcPlayer setPlayView:self.playerView playCofig:self.rtcPlayConfig]; [rtcPlayer startPlayWithURL:@"artc://live.aliyun.com/play/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX"]; //主播A的拉流地址
windows示例代码:
player_ = AlivcLivePlayer::Create(""); if (player_) { AlivcLivePlayConfig config; player_->setupWithConfig(config); player_->startPlay("artc://live.aliyun.com/play/123?timestamp=1661596947&token=XXX&userId=123&sdkAppId=XXX"); player_->setPlayView(hwnd, width, height); }
主播A和主播B分别更新混流。
为了保证普通观众C和观众D可以看到主播A和主播B的PK的画面,主播A和主播B此时需要分别发起一次混流操作,即将主播A和主播B的画面,混合成一路流给到CDN观众播放。
主播A和主播B分别调用setLiveMixTranscodingConfig接口启动云端混流(转码)任务,设置需要混流的对象。混流出来的视频画面的分辨率、帧率等使用的是主播A创建AlivcLivePusher引擎时指定的AlivcLivePushConfig中的配置。即如果主播A创建AlivcLivePusher引擎时AlivcLivePushConfig中配置分辨率为720P,则混流出来的视频画面的分辨率也是720P。
Android示例代码:
AlivcLiveTranscodingConfig transcodingConfig = new AlivcLiveTranscodingConfig(); AlivcLiveMixStream anchorMixStream = new AlivcLiveMixStream(); anchorMixStream.setUserId(123); anchorMixStream.setX(0); anchorMixStream.setY(0); anchorMixStream.setWidth(mAlivcLivePushConfig.getWidth()); anchorMixStream.setHeight(mAlivcLivePushConfig.getHeight()); anchorMixStream.setZOrder(1); AlivcLiveMixStream audienceMixStream = new AlivcLiveMixStream(); audienceMixStream.setUserId(456); audienceMixStream.setX((int) mAudienceFrameLayout.getX() / 3); audienceMixStream.setY((int) mAudienceFrameLayout.getY() / 3); audienceMixStream.setWidth(mAudienceFrameLayout.getWidth() / 2); audienceMixStream.setHeight(mAudienceFrameLayout.getHeight() / 2); audienceMixStream.setZOrder(2); ArrayList<AlivcLiveMixStream> mixStreams = new ArrayList<>(); mixStreams.add(anchorMixStream); mixStreams.add(audienceMixStream); transcodingConfig.setMixStreams(mixStreams); alivcLivePusher.setLiveMixTranscodingConfig(transcodingConfig);
iOS示例代码:
AlivcLiveTranscodingConfig *liveTranscodingConfig = [[AlivcLiveTranscodingConfig alloc] init]; AlivcLiveMixStream *anchorMixStream = [[AlivcLiveMixStream alloc] init]; anchorMixStream.userId = 123; anchorMixStream.x = 0; anchorMixStream.y = 0; anchorMixStream.width = [self.rtcPushConfig getPushResolution].width; anchorMixStream.height = [self.rtcPushConfig getPushResolution].height; anchorMixStream.zOrder = 1; AlivcLiveMixStream *audienceMixStream = [[AlivcLiveMixStream alloc] init]; audienceMixStream.userId = 456; audienceMixStream.x = 100; audienceMixStream.y = 200; audienceMixStream.width = 200; audienceMixStream.height = 300; audienceMixStream.zOrder = 2; liveTranscodingConfig.mixStreams = [NSArray arrayWithObjects:anchorMixStream, audienceMixStream, nil]; [self.rtcPusher setLiveMixTranscodingConfig:liveTranscodingConfig];
windows示例代码:
AlivcLiveTranscodingConfig liveTranscodingConfig; AlivcLiveMixStream anchorMixStream ; anchorMixStream.userId = userA; anchorMixStream.x = 0; anchorMixStream.y = 0; anchorMixStream.width = width; anchorMixStream.height = height; anchorMixStream.zOrder = 1; AlivcLiveMixStream audienceMixStream; audienceMixStream.userId = userD; audienceMixStream.x = 100; audienceMixStream.y = 200; audienceMixStream.width = 200; audienceMixStream.height = 300; audienceMixStream.zOrder = 2; liveTranscodingConfig.mixStreams.Add(anchorMixStream); liveTranscodingConfig.mixStreams.Add(audienceMixStream); pusher_->setLiveMixTranscodingConfig(&liveTranscodingConfig);
步骤六:结束PK
主播A和主播B分别结束播放对方的流
主播A和主播B分别结束播放对方实时流,结束PK场景,切换成单主播推流。
Android示例代码:
alivcLivePlayer.stopPlay(); alivcLivePlayer.destroy(); alivcLivePlayer = null;
iOS示例代码:
[self.rtcPlayer stopPlay]; self.rtcPlayer = nil;
windows示例代码:
if (player_) { player_->stopPlay(); player_->destroy(); player_ = nullptr; }
主播A和主播B分别更新混流
主播A和主播B结束PK后,需要更新混流画面,分别调用setLiveMixTranscodingConfig接口,参数传入空值,从混流切换为旁路模式。
当不再需要混流,普通观众只需要观看主播A或者主播B一个人画面时,可以调用setLiveMixTranscodingConfig接口,参数传入空值即可。
警告若主播还在房间中但不再需要混流,请务必传入空值进行取消。因为当发起混流后,云端混流模块就会开始工作,不及时取消混流可能会引起不必要的计费损失。
Android示例代码:
alivcLivePusher.setLiveMixTranscodingConfig(null);
iOS示例代码:
[self.rtcPusher setLiveMixTranscodingConfig:nil];
windows示例代码:
pusher_->setLiveMixTranscodingConfig(nullptr);