歡迎你們前往雲+社區,獲取更多騰訊海量技術實踐乾貨哦~web
做者:騰訊視頻雲json
進入2018年最火的新鮮事物無疑就是「直播答題」了,動輒上百萬的獎金更是吸引了大量用戶的參與。一場直播動輒幾百萬的獎金,每人能夠分到幾十元甚至百萬元,愈來愈多的人但願用本身的智商賺點零花錢。直播答題有多火?小程序
多個直播平臺服務器屢次遭到宕機。實際上,幾百萬人一同在線的確會帶給服務器不小的壓力,更況且是新上線的 App,他們或許尚未想到本身會火得這麼快。微信小程序
近期不少直播答題app出現了我的帳號上顯示獎金額數不對、在線用戶沒法進入遊戲、技術故障致使遊戲被迫臨時取消等狀況。某視頻平臺還出現了系統將正確答案斷定錯誤的狀況,致使百萬人被迫停止遊戲。隔幾天就來一次的數組
技術故障除了說明App準備不足外,也從側面反映了這類遊戲的火爆程度。爲了讓衆多公司及開發者儘快遇上風口浪尖,騰訊雲直播團隊也是第一時間上線了「在線知識競技解決方案」。緩存
iOS平臺(ipa) Android平臺(apk) Obs Studio 定製版本(exe)安全
iOS Android Obs Studio服務器
建立房間便可體驗主持人一端的效果;進入房間便可體驗觀衆端的效果。微信
iPhone 平臺的 Demo 採用了企業簽名方式,請先到「設置-通用-設備管理」裏,添加信任證書。websocket
Demo 僅做演示之用,用來展現騰訊雲的技術能力,不表明最終產品形態,接入請仔細閱讀文檔。
這種體驗方式是直接使用騰訊雲改造的 Obs Studio 進行推流:
// iOS 示例代碼 [_answerPusher sendMessage:[mesg dataUsingEncoding:NSUTF8StringEncoding]];
//Android 示例代碼 mTXLivePusher.sendMessage(questionInfo.getBytes("UTF-8"));
消息接收的接入方案能夠參考咱們的接入文檔(iOS平臺 | Android平臺)
總結一下:方案二跟方案一的最大區別就在於題目的擴散方式,方案二的核心思路是讓題目先經過IM通道快速送達觀衆端APP,在觀衆端先緩存下來,等待播放器通知了預期的 NTP 時間戳以後,再把題目顯示出來。
方案一和方案二均可以實現「音-話-題」完美同步,可是相比於這種體驗上的小優化,APP的擴散能力則是更加劇要的。小程序偏偏提供給了APP能夠病毒式傳播的能力。
騰訊雲 SDK 已經默認打包在微信版本中,並以 <live-player> 標籤的形式對外提供,若是:
那麼就能夠實現很是理想的播放延遲,並可以讓各觀衆之間的延遲偏差在1s之內,雖然沒法作到「音-話-題」分絕不差(在微信打包視頻雲 SDK 的時候,在線答題模式尚未興起,因此不支持在音視頻流中夾帶消息),但也能達到幾乎能夠媲美APP的體驗效果。
剩下的事情,就是經過小程序的 websocket 通道,或者咱們的 webim 解決方案,向小程序發題就能夠了。
聯繫咱們開通騰訊雲 直播服務,若是您時間比較急,能夠 400 客服電話咱們加急審覈。
想要簡單獲取一個推流URL,能夠參考文檔:快速得到地址。
想要了解推流地址和直播間ID的關係,能夠參考文檔:後臺自動拼裝。
想要了解若是保護本身的推流地址不被盜用,能夠參考文檔:防盜鏈簽名。
播放URL和推流URL是一一映射的,映射規則參考下面的圖示您就能明白了:
請務必使用 FLV 格式的播放地址,RTMP在高併發場景下容易出現卡頓問題。
若是您是使用APP進行推流,直接參考文檔(iOS | Android)。
若是您是使用Obs推流,請注意如下幾個重要設置項:
通常演播臺的接入方式有兩種:OBS Studio 推流或者編碼盒推流,這兩種推流工具均有比較成熟的設置接口。建議將 GOP(也叫關鍵幀間隔)設置爲 1s ,這樣可讓觀衆端的延遲差別很是小。
x264 的 gop 設置對編碼效率的影響不是很大,但對延遲的影響很是大:gop越大,服務器緩存越多。因爲 SDK 的延遲修正須要一個修正時間,若是 gop 太大,對於剛進入的觀衆會有很大的影響 。
以下是Obs Studio 設置關鍵幀間隔的圖示:
推薦推薦配置 |
分辨率 |
視頻比特率 |
幀率 |
聲道數 |
採樣率 |
音頻比特率 |
---|---|---|---|---|---|---|
優先畫質 |
540x960 |
1000kbps |
25 |
1 |
48k |
72kbps |
優先成本 |
360x640 |
600kbps |
20 |
1 |
48k |
72kbps |
//iOS源碼 TXLivePlayConfig *config = [[TXLivePlayConfig alloc] init]; TXLivePlayer *player = [[TXLivePlayer alloc] init]; // //開啓消息接受,收不到消息的話就是沒打開這個(默認:關) config.enableMessage = YES; // //設置延遲平衡點爲1s(考慮到雲端和推流端引入的延遲,實際延遲爲2s多,SDK推流:2s, obs推流:3-4秒) config.bAutoAdjustCacheTime = YES; config.maxAutoAdjustCacheTime = 1; config.minAutoAdjustCacheTime = 1; config.cacheTime = 1; config.connectRetryCount = 3; config.connectRetryInterval = 3; config.enableAEC = NO; //先setConfig再startPlay [player setConfig:config]; //Android源碼 mTXLivePlayConfig = new TXLivePlayConfig(); mTXLivePlayer = new TXLivePlayer(context); // //開啓消息接收,收不到消息的話就是沒打開這個(默認:關) mTXLivePlayConfig.setEnableMessage(true); // //設置延遲平衡點爲1s(考慮到雲端和推流端引入的延遲,實際延遲爲2s多,SDK推流:2s, obs推流:3-4秒) mTXLivePlayConfig.setAutoAdjustCacheTime(true); mTXLivePlayConfig.setCacheTime(1.0f); mTXLivePlayConfig.setMaxAutoAdjustCacheTime(1.0f); mTXLivePlayConfig.setMinAutoAdjustCacheTime(1.0f); // //先setConfig再startPlay mTXLivePlayer.setConfig(mTXLivePlayConfig);
請務必使用 FLV 格式的播放地址,RTMP在高併發場景下容易出現卡頓問題。
可靠性評估
有些客戶可能會擔憂:音視頻通道自己不太穩定,那麼萬一卡了或者視頻數據丟了,會不會致使觀衆端看不到題目。
因此,解決這個問題的辦法就是每秒鐘(gop設置爲1s的前提條件下)發送一次題目消息,相同的題號在觀衆端剔重,這樣就能夠避免偶爾的音視頻卡頓對題目到達可靠性的影響。
在咱們的推流 APP Demo 以及定製版本的 Obs Studio 中,咱們以 json 格式將題目組織成一段buffer,並將其夾在音視頻流中送出去。
獲取到這個buffer之後,您就能夠將其解析出來,並完成對應的 UI 展現。若是你須要調整json格式以支持更多的定製型,請修改源碼或者聯繫咱們。
// iOS 的代碼 -(void) onPlayEvent:(int)EvtID withParam:(NSDictionary *)param { [self asyncRun:^{ if (EvtID == PLAY_EVT_GET_MESSAGE) { dispatch_async(dispatch_get_main_queue(), ^{ //拋到主線程,避免線程安全問題 if ([_delegate respondsToSelector:@selector(onPlayerMessage:)]) { [_delegate onPlayerMessage:param[@"EVT_GET_MSG"]]; } }); } }]; } //Android 示例代碼 mTXLivePlayer.setPlayListener(new ITXLivePlayListener() { @Override public void onPlayEvent(int event, Bundle param) { if (event == TXLiveConstants.PLAY_ERR_NET_DISCONNECT) { roomListenerCallback.onDebugLog("[AnswerRoom] 拉流失敗:網絡斷開"); roomListenerCallback.onError(-1, "網絡斷開,拉流失敗"); } else if (event == TXLiveConstants.PLAY_EVT_GET_MESSAGE) { String msg = null; try { msg = new String(param.getByteArray(TXLiveConstants.EVT_GET_MSG), "UTF-8"); roomListenerCallback.onRecvAnswerMsg(msg); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } });
因爲騰訊雲 PAAS 的定位,因此對於跟客戶業務綁定比較緊密的答題和支付系統,咱們就不涉及了,須要您來參與開發。
這裏廣泛採用的方案是:將客戶的答案以 HTTP(S) 請求方式彙總到答題服務器上,只是實現過程須要注意解決瞬間高併發的請求壓力。
有客戶可能會問,IM系統是否適合用來答題,這裏目前看是不適合的,由於 IM 系統的主要能力在於消息擴散,而答題的主要目標是信息的收攏。
通常題目出來一段時間之後,就會進入閉題狀態。這時,答題系統會將結果進行統計彙總,並將彙總結果下發給觀衆。
若是是用咱們的定製版 Obs Studio 擴散結果,搭一個簡單的服務器,並提供一個 http 接口,而後按照咱們約定的 json 格式跟 Obs 進行題目、答案以及人數的通信。從而實現題目和答案的分發。
這部分協議因爲文檔篇幅限制,暫時不放在文檔中詳細列出,有須要的話請 400 電話聯繫咱們。
同方案一,再也不贅述。
參考方案一,與方案一不一樣之處在於,推流 URL 須要額外增長一個參數:
加註NTP時間戳
在推流 URL 以後添加參數 &txAddTimestamp=1 參數,服務器會每隔1s向您的直播流中打入一個帶有國際標準時間(偏差在 100ms 之內)的 SEI 時間戳。若是您使用咱們的播放器播放此視頻流,那麼就會每隔一秒鐘收到一次表明當前畫面 NTP 時間的消息通知。
同方案一,再也不贅述。
同方案一,再也不贅述。
參考方案一,與方案一不一樣之處在於,此時獲取的message再也不是一個json,而是一個8字節的64位時間戳。
long timeStamp = byteArrayToInt(param.getByteArray(TXLiveConstants.EVT_GET_MSG)); /** * 將8字節的byte數組轉成一個long值 */ public static long byteArrayToInt(byte[] byteArray) { byte[] a = new byte[8]; int i = a.length - 1, j = byteArray.length - 1; for (; i >= 0; i--, j--) {// 從b的尾部(即int值的低位)開始copy數據 if (j >= 0) a[i] = byteArray[j]; else a[i] = 0;// 若是b.length不足4,則將高位補0 } // 注意此處和byte數組轉換成int的區別在於,下面的轉換中要將先將數組中的元素轉換成long型再作移位操做, // 若直接作位移操做將得不到正確結果,由於Java默認操做數字時,若不加聲明會將數字做爲int型來對待,此處必須注意。 long v0 = (long) (a[0] & 0xff) << 56;// &0xff將byte值無差別轉成int,避免Java自動類型提高後,會保留高位的符號位 long v1 = (long) (a[1] & 0xff) << 48; long v2 = (long) (a[2] & 0xff) << 40; long v3 = (long) (a[3] & 0xff) << 32; long v4 = (long) (a[4] & 0xff) << 24; long v5 = (long) (a[5] & 0xff) << 16; long v6 = (long) (a[6] & 0xff) << 8; long v7 = (long) (a[7] & 0xff); return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7; }
若是您使用本身的 IM 系統下發題目,請忽略這一部分,若是想使用騰訊雲 IM 服務發題,請對接以下幾步:
2)以後,由您的業務服務器經過 v4/group_open_http_svc/send_group_msg,定時將人數經過羣消息下發給客戶端。定時頻率能夠設定爲 3-5s 一次。
特別注意:REST API 不支持客戶端調用,在客戶端調用會引起私鑰泄漏,進而致使您的雲服務被惡意盜用和扣費。
客戶端使用 IM SDK 完成消息的接收和彈幕消息的收發,這裏能夠按照以下步驟對接
成員函數 |
做用 |
---|---|
initIMCenter |
用於初始化,須要填寫您在騰訊雲的 IM 服務相關信息。 |
loginIMUser |
用於登陸,您能夠把 imSDK 當成一個無界面的 QQ,用QQ收發消息確定要登陸,只是將QQ號和登陸密碼換成了您的Userid和您的服務器簽發的UserSig。 |
joinIMGroup |
用於加入在步驟六中由您的後臺服務器經過 REST API 建立的 BChatRoom 和 AVChatRoom。 |
sendChatMessage |
用來發送彈幕評論消息 |
onRecvChatMessage |
用於接收來自 AVChatRoom 的彈幕消息,注意作一下渲染的頻率限制,不要收到一條彈幕消息就刷一次屏幕,手機性能可能扛不住,不少客戶都是在這裏疏忽了,由於測試期間消息很少不易發現。 |
onRecvIssueMessage |
用於接收來自 BChatRoom 的題目消息,按照方案二的設計,每道題目裏面都有它應該顯示的 NTP 國際時間。 |
因爲騰訊雲 PAAS 的定位,因此對於跟客戶業務綁定比較緊密的答題和支付系統,咱們就不涉及了,須要您來參與開發。
這裏廣泛採用的方案是:將客戶的答案以 HTTP(S) 請求方式彙總到答題服務器上,只是實現過程須要注意解決瞬間高併發的請求壓力。
有客戶可能會問,IM系統是否適合用來答題,這裏目前看是不適合的,由於 IM 系統的主要能力在於消息擴散,而答題的主要目標是信息的收攏。
通常題目出來一段時間之後,就會進入閉題狀態。這時,答題系統會將結果進行統計彙總,並將彙總結果下發給觀衆,結果下發能夠繼續使用 步驟六 中的題目擴散通道。
此文已由做者受權雲加社區發佈,轉載請註明原文出處