阿里雲ApsaraVideo for Live提供主播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);