本文介紹K歌房多人合唱模式Android SDK整合的程式碼範例及整合說明。
功能時序圖
使用自研播放器播放音樂

使用ARTC解碼和播放音樂
如果您需要使用即時音視頻ARTC解碼和播放音樂,請提交工單諮詢。關於如何提交工單,請參見聯絡我們。
主播建立房間
mAliRtcEngine.setChannelProfile(AliRTCSdkInteractiveLive);
mAliRtcEngine.setClientRole(AliRTCSdkInteractive);
/* 使用高音質和ktv情境 */
mAliRtcEngine.setAudioProfile(AliRtcEngineHighQualityMode, AliRtcSceneKtvMode);
//auto pub
mAliRtcEngine.publishLocalAudioStream(true);
/* 設定回調的監聽 */
mAliRtcEngine.setRtcEngineEventListener(this);
//auto sub
mAliRtcEngine.setDefaultSubscribeAllRemoteAudioStreams(true);
mAliRtcEngine.subscribeAllRemoteAudioStreams(true);
mAliRtcEngine.setAudioOnlyMode(true);
mAliRtcEngine.enableSpeakerphone(true);
JSONObject tokenv2 = new JSONObject();
tokenv2.put("appid", userInfo.appId);
tokenv2.put("channelid", userInfo.channelId);
tokenv2.put("userid", userInfo.userId);
tokenv2.put("nonce", userInfo.nonce);
tokenv2.put("timestamp", userInfo.timestamp);
tokenv2.put("gslb",userInfo.gslb);
tokenv2.put("token", userInfo.token);
String base64TokenV2 = Base64.encodeToString(JSON.toJSONBytes(tokenv2),Base64.NO_WRAP);
/* 入會 */
mAliRtcEngine.joinChannel(base64TokenV2, null, null, mUsername);
/* 開啟datachannel 用於接受歌曲進度 */
String param = "\"data\":{\"enablePubDataChannel\":true" + ",\"enableSubDataChannel\":true}";
param = "{" + param + "}";
mAliRtcEngine.setParameter(param);觀眾進入房間
mAliRtcEngine.setChannelProfile(AliRTCSdkInteractiveLive);
mAliRtcEngine.setClientRole(AliRTCSdkLive);
/* 使用高音質和ktv情境 */
mAliRtcEngine.setAudioProfile(AliRtcEngineHighQualityMode, AliRtcSceneKtvMode);
//auto pub
mAliRtcEngine.publishLocalAudioStream(true);
/* 設定回調的監聽 */
mAliRtcEngine.setRtcEngineEventListener(this);
//auto sub
mAliRtcEngine.setDefaultSubscribeAllRemoteAudioStreams(true);
mAliRtcEngine.subscribeAllRemoteAudioStreams(true);
/* 觀眾需要訂閱伴奏流 */
mAliRtcEngine.subscribeAllRemoteDualAudioStreams(true);
mAliRtcEngine.setAudioOnlyMode(true);
mAliRtcEngine.enableSpeakerphone(true);
JSONObject tokenv2 = new JSONObject();
tokenv2.put("appid", userInfo.appId);
tokenv2.put("channelid", userInfo.channelId);
tokenv2.put("userid", userInfo.userId);
tokenv2.put("nonce", userInfo.nonce);
tokenv2.put("timestamp", userInfo.timestamp);
tokenv2.put("gslb",userInfo.gslb);
tokenv2.put("token", userInfo.token);
String base64TokenV2 = Base64.encodeToString(JSON.toJSONBytes(tokenv2),Base64.NO_WRAP);
/* 入會 */
mAliRtcEngine.joinChannel(base64TokenV2, null, null, mUsername);
/* 開啟datachannel 用於接受歌曲進度 */
String param = "\"data\":{\"enablePubDataChannel\":true" + ",\"enableSubDataChannel\":true}";
param = "{" + param + "}";
mAliRtcEngine.setParameter(param);主播點歌
添加伴奏流並建立pcm輸入。
mAliRtcEngine.publishLocalDualAudioStream(true); AliRtcEngine.AliRtcExternalAudioStreamConfig config = new AliRtcEngine.AliRtcExternalAudioStreamConfig(); config.sampleRate = sampleRate; config.channels = channels; /* 伴奏音樂本地播放的音量,如果需要rtc sdk來實現播放,可以設定該值 */ config.playoutVolume = 60; config.publishVolume = 100; config.publishStream = 1; // 指定通過伴奏流推送 int externalAudioStreamId = aliRtcEngine.addExternalAudioStream(config);準備好物料檔案之後,持續解碼輸入pcm資料。
/* ... 持續送入pcm資料... */ AliRtcEngine.AliRtcAudioFrame sample = new AliRtcEngine.AliRtcAudioFrame(); sample.data = buffer; sample.numSamples = numSamples; sample.numChannels = channels; sample.sampleRate = sampleRate; sample.bytesPerSample = bytesPerSample; int ret = aliRtcEngine.pushExternalAudioStreamRawData(externalAudioStreamId, sample);輸入pcm資料的同時,更新進度。
AliRtcEngine.AliRtcDataChannelMsg msg = new AliRtcEngine.AliRtcDataChannelMsg(); msg.type = AliRtcEngine.AliRtcDataMsgType.AliEngineDataMsgMusicProgress; msg.networkTime = mAliRtcEngine.getNetworkTime(); msg.progress = progress; mAliRtcEngine.sendDataChannelMsg(msg);
觀眾擷取進度更新歌詞
public void onDataChannelMessage(String uid, AliRtcEngine.AliRtcDataChannelMsg controlMsg) {
super.onDataChannelMessage(uid, controlMsg);
Log.d(TAG, "datachannel type=" + controlMsg.type + ", time=" + controlMsg.networkTime + ", progress=" + controlMsg.progress);
/* 更新進度到controlMsg.progress */
}觀眾上麥成為參唱者
/* 參與演唱不需要訂閱伴奏流,本地播放 */
mAliRtcEngine.subscribeAllRemoteDualAudioStreams(false);
mAliRtcEngine.setClientRole(AliRTCSdkInteractive);參唱者接受進度更新播放位置
public void onDataChannelMessage(String uid, AliRtcEngine.AliRtcDataChannelMsg controlMsg) {
super.onDataChannelMessage(uid, controlMsg);
Log.d(TAG, "datachannel type=" + controlMsg.type + ", time=" + controlMsg.networkTime + ", progress=" + controlMsg.progress);
/* 進度需要加上 傳輸耗時,做到伴奏精準同步 */
long div = mAliRtcEngine.getNetworkTime() - controlMsg.networkTime;
long progress = controlMsg.progress + div;
/* 更新歌曲播放進度到progress */
}參唱者下麥成為觀眾
/* 觀眾需要訂閱遠端的流來播放伴奏 */
mAliRtcEngine.subscribeAllRemoteDualAudioStreams(true);
mAliRtcEngine.setClientRole(AliRTCSdkLive);主播切歌
mAliRtcEngine.removeExternalAudioStream(externalAudioStreamId);
/* 停止伴奏流 */
mAliRtcEngine.publishLocalDualAudioStream(true);
/* 停止歌曲解碼 、IM通知其他人 */