本文中含有需要您注意的重要提示信息,忽略該信息可能對您的業務造成影響,請務必仔細閱讀。
阿里云視頻直播提供主播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 Demo配置。具體操作,請參見Demo試用。
本文介紹推流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;
AlivcLivePushConfig rtcPushConfig; rtcPushConfig.mLivePushMode = AlivcLivePushInteractiveMode; rtcPushConfig.mResolution = AlivcLivePushResolution540P; rtcPushConfig.frameRate = AlivcLivePushFPS20; rtcPushConfig.mPreviewOrientation = AlivcLivePushOrientationPortrait;
創建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];
if (!pusher_) { pusher_ = AlivcLivePusher::Create(""); } pusher_->init(config_); pusher_->setLivePushErrorListener(this); pusher_->setLivePushInfoListener(this); pusher_->setLivePushNetworkListener(this);
連麥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;
AlivcLivePushConfig rtcPushConfig; rtcPushConfig.mLivePushMode = AlivcLivePushInteractiveMode; rtcPushConfig.mResolution = AlivcLivePushResolution540P; rtcPushConfig.frameRate = AlivcLivePushFPS20; rtcPushConfig.mPreviewOrientation = AlivcLivePushOrientationPortrait;
創建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];
if (!pusher_) { pusher_ = AlivcLivePusher::Create(""); } pusher_->init(config_); pusher_->setLivePushErrorListener(this); pusher_->setLivePushInfoListener(this); pusher_->setLivePushNetworkListener(this);
連麥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);