阿里雲ApsaraVideo for Live支援Web端主播與觀眾的連麥互動,使用者無需安裝額外的應用程式即可直接在Web頁面上與他人進行連麥互動。本文為您介紹Web端連麥互動的操作步驟和相關範例程式碼,協助使用者快速接入連麥互動情境。
接入RTC連麥互動方案介紹
直播SDK基於即時音視頻RTC來實現連麥方案,協助客戶實現超低延時、更多人數的直播即時互動,一般流程如下:
連麥前:主播使用RTC連麥推流地址進行推流,觀眾拉取CDN流進行觀看。
連麥中:觀眾從一般觀眾切換為連麥觀眾,使用RTC連麥推流地址進行推流,使用RTC連麥拉流地址拉取主播的超低延時流;主播使用RTC連麥拉流地址進行拉取連麥觀眾的超低延時流。
結束連麥:連麥觀眾切換為一般觀眾,停止RTC推流和RTC拉流,切換為拉取CDN流進行觀看。
注意事項
步驟一:開通直播連麥服務
使用直播連麥功能時,您需要先建立連麥應用,並配置觀眾播放網域名稱。具體操作方法,請參見直播連麥快速入門。
步驟二:產生連麥互動推拉流地址
您可以通過控制台產生或通過自訂拼接主播和連麥觀眾的推拉流地址,及一般觀眾(非連麥觀眾)的CDN播放地址。
方法一:控制台產生
若您希望快速產生主播和連麥觀眾的推拉流地址,及一般觀眾(非連麥觀眾)的CDN播放地址進行體驗,可以藉助控制台工具進行產生。具體操作,請參見連麥地址產生器。
方法二:自訂拼接
通過控制台產生主播和連麥觀眾的推拉流地址URL中,Token為臨時Token,一般用於測試使用。如果需要正式使用,為了安全起見,請使用自訂拼接的推拉流地址。自訂拼接地址中Token是基於您的SdkAppID、 AppKey、房間ID、UserID和Timestamp通過SHA256密碼編譯演算法計算得到,攻擊者很難通過偽造Token盜用您的雲端服務流量。自訂拼接詳情請參見連麥互動情境主播端和連麥觀眾端推拉流地址和一般觀眾的CDN播放地址。
步驟三:建立推流對象
主播端和連麥觀眾端都需要執行該操作。
建立AlivcLivePusher推流對象
建立推流引擎對象 AlivcLivePusher,設定相應的回調:
const pusher = new window.AlivcLivePush.AlivcLivePusher();
await pusher.init({
resolution: window.AlivcLivePush.AlivcResolutionEnum.RESOLUTION_540P,
fps: window.AlivcLivePush.AlivcFpsEnum.FPS_30,
// audioOnly: true, 針對純音頻推流情境,非純音頻推流情境不需要。
});
pusher.info.on('pushstatistics', _stat => {
// TODO... 推流統計資訊處理
// console.log(_stat);
});
pusher.error.on('system', error => {
console.log(error);
});
pusher.network.on('connectionlost', () => {
console.log('connectionlost');
});
連麥互動模式下推流
使用連麥互動模式下推流地址URL進行推流。
await pusher.startPreview(videoElement);
await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); //主播或連麥觀眾的推流地址
startPreview和startPush均為非同步方法呼叫,為了保證調用順序,需要通過await執行,或通過Promise處理。
如果使用情境為Native與Web連麥互連,則Native端(Android/iOS)必須使用H5相容模式。否則,Web使用者查看Native使用者將是黑屏。請在Native端調用AlivcLivePushConfig#setH5CompatibleMode介面,介面詳細說明請參考Native SDK API文檔。
步驟四:建立AliPlayer CDN播放
一般觀眾端(非連麥觀眾)需要執行該操作。
如果播放端需要使用AliPlayer進行CDN播放,需要先擷取一般觀眾(非連麥觀眾)的CDN播放地址。具體操作,請參見步驟二:產生連麥互動推拉流地址。
建議將下述RTMP格式的播放地址換成HTTP-FLV格式的形式。在阿里雲ApsaraVideo for Live控制台產生地址時,會同時產生RTMP與HTTP-FLV的地址,這兩個協議裡包含的資料內容是一致的,只是網路通訊協定通道不一樣。HTTP協議是互連網主要協議,CDN、電訊廠商、中間網路裝置等鏈路中都對HTTP有很長時間的網路最佳化,HTTP的預設80/443連接埠號碼也是常見白名單連接埠,不容易被禁用,而RTMP協議比較老,其預設連接埠號碼是1935有可能被防火牆等裝置禁用,導致異常。因此在綜合網路環境下,HTTP-FLV的穩定性、效能(卡頓、延時)會比RTMP更好。
const player = new window.Aliplayer(
{
id: videoId, // video element ID
source: url, //播放地址,可以是第三方直播地址,或阿里雲直播服務中的拉流地址。
isLive: true, //是否為直播播放。
},
function (player: any) {
console.log('The player is created.', player);
}
);
步驟五:觀眾連麥
主播A RTC推流
主播A開始推流,調用AlivcLivePusher推流引擎開始主播A的推流。程式碼範例:
await pusher.startPreview(videoElement); // videoElement 可以通過 Document 相關 API 獲得
await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); //主播或連麥觀眾的推流地址
一般觀眾(非連麥觀眾)的CDN播放主播A的流
所有觀眾觀看主播A的直播,調用AliPlayer開始播放主播A的流。範例程式碼:
const player = new window.Aliplayer(
{
id: videoId, // video element ID
source: 'rtmp://test.alivecdn.com/live/streamId?auth_key=XXX', //播放地址,可以是第三方直播地址,或阿里雲直播服務中的拉流地址。
isLive: true, //是否為直播播放。
},
function (player: any) {
console.log('The player is created.', player);
}
);
觀眾D發起連麥
觀眾D建立AlivcLivePusher對象,使用D的互動推流地址開始推流。範例程式碼:
const pusher = new window.AlivcLivePush.AlivcLivePusher(); pusher.init({ resolution: window.AlivcLivePush.AlivcResolutionEnum.RESOLUTION_540P, fps: window.AlivcLivePush.AlivcFpsEnum.FPS_30, // audioOnly: true, 針對純音頻推流情境,非純音頻推流情境不需要。 }); pusher.info.on('pushstatistics', _stat => { // TODO... 推流統計資訊處理 // console.log(_stat); }); pusher.error.on('system', error => { console.log(error); }); pusher.network.on('connectionlost', () => { console.log('connectionlost'); }); await pusher.startPreview(videoElement); // videoElement 可以通過 Document 相關 API 獲得 await pusher.startPush("artc://live.aliyun.com/push/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX"); //主播或連麥觀眾的推流地址
主播A擷取連麥觀眾D的互動模式直播拉流地址,建立AlivcLivePlayer對象拉取連麥觀眾D的即時資料流。範例程式碼:
const player = new window.AlivcLivePush.AlivcLivePlayer(); // artc:// 連結為觀眾D的直播拉流地址 const playInfo = await player.startPlay("artc://live.aliyun.com/play/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX", videoElement); playInfo.on('userleft', () => { // 處理觀眾D離開的事件 }); playInfo.on('canplay', () => { // 處理視頻可播放事件 }
同時,連麥觀眾D擷取主播A的互動模式直播拉流地址建立AlivcLivePlayer對象拉取主播A的即時資料流。範例程式碼:
const player = new window.AlivcLivePush.AlivcLivePlayer(); // artc:// 連結為主播A的直播拉流地址 const playInfo = await player.startPlay("artc://live.aliyun.com/play/6375?timestamp=1661596947&token=XXX&userId=7135&sdkAppId=XXX", videoElement); playInfo.on('userleft', () => { // 處理主播A離開的事件 }); playInfo.on('canplay', () => { // 處理視頻可播放事件 }
連麥成功後更新混流
為了保證一般觀眾B和C(非連麥觀眾)可以看到連麥觀眾D的畫面,主播A此時需要發起一次混流操作,即將主播A和連麥觀眾D的畫面,混合成一路流給到CDN觀眾播放。
主播A調用setLiveMixTranscodingConfig介面啟動雲端混流(轉碼)任務,設定需要混流的對象。混流出來的視頻畫面的解析度、幀率等使用的是主播A建立AlivcLivePusher引擎時指定的AlivcLivePushConfig中的配置。即如果主播A建立AlivcLivePusher引擎時AlivcLivePushConfig中配置解析度為720P,則混流出來的視頻畫面的解析度也是720P。
const resolution = pusher.getResolution();
const width = window.AlivcLivePush.AlivcResolution.GetResolutionWidth(resolution);
const height = window.AlivcLivePush.AlivcResolution.GetResolutionHeight(resolution);
const mixStreams = [];
const transcodingConfig = new window.AlivcLivePush.AlivcLiveTranscodingConfig();
const anchorMixStream = new window.AlivcLivePush.AlivcLiveMixStream(
userA, // 修改為主播A的使用者ID
0,
0,
width,
height,
1
);
// 將主播A的流添加到混流列表
mixStreams.push(anchorMixStream);
const audienceMixStream = new window.AlivcLivePush.AlivcLiveMixStream(
userD, // 修改為連麥觀眾D的使用者ID
100,
200,
200,
300,
2
);
// 將連麥觀眾D的流添加到混流列表
mixStreams.push(audienceMixStream);
transcodingConfig.mixStreams = mixStreams;
await pusher.setLiveMixTranscodingConfig(transcodingConfig);
這樣,一般觀眾就可以看到主播A和連麥觀眾D的連麥互動。
連麥觀眾D結束連麥
連麥觀眾D結束連麥,需要調用AlivcLivePusher推流引擎的結束推流介面,並將AlivcLivePusher推流引擎銷毀。範例程式碼:
await pusher.destroy(); pusher = null;
同時,連麥觀眾D需要調用AlivcLivePlayer拉流引擎的結束播放介面,並將AlivcLivePlayer拉流引擎銷毀。範例程式碼:
await player.destroy(); player = null;
連麥觀眾D切換為一般觀眾,通過步驟四:建立AliPlayer CDN播放進行CDN播放。
主播A需要調用AlivcLivePlayer拉流引擎的結束播放介面,並將AlivcLivePlayer拉流引擎銷毀。範例程式碼:
await player.destroy(); player = null;
同時,當主播A不再需要混流,一般觀眾只需觀看主播A的畫面時,可以調用setLiveMixTranscodingConfig介面,將參數傳入空值,即可切換為旁路模式。
警告若主播還在房間中但不再需要混流,請務必傳入空值進行取消。因為當發起混流後,雲端混流模組就會開始工作,不及時取消混流可能會引起不必要的計費損失。
pusher.setLiveMixTranscodingConfig();