https://www.qcloud.com/document/product/454/7886
基礎知識
RTMP SDK 包含推流和播放兩方面功能,推流為主播端功能,播放(分為直播和點播)為觀眾端功能。對接之前,我們先列表如下一些基本知識會大有裨益:
-
直播和點播
直播 的視頻源是實時生成的,有人推流直播才有意義。所以,一旦主播停播,直播URL也就失效了,而且由於是實時直播,所以播放器在播直播視頻的時候是沒有進度條的。點播 的視頻源是雲端的一個文件,文件只要沒有被提供方刪除,就隨時可以播放, 而且由於整個視頻都在服務器上,所以播放的時候是有進度條的哦。
-
協議的支持
通常使用的直播協議如下,APP端推薦使用 FLV 協議的直播地址(以“http”打頭,以“.flv”結尾):
通常使用的點播協議如下,現在比較流行的是HLS(以“http”打頭,以“.m3u8”結尾)的點播地址:

特別說明
SDK 不會對 播放地址的來源做限制,即您可以用它來播放騰訊雲或非騰訊雲的播放地址。但 SDK 中的播放器只支持 FLV 、RTMP 和 HLS(m3u8)三種格式的直播地址,以及 MP4、 HLS(m3u8)和 FLV 三種格式的點播地址。
對接攻略
step 1: 添加View
為了能夠展示播放器的視頻畫面,我們第一步要做的就是在布局xml文件里加入如下一段代碼:
<com.tencent.rtmp.ui.TXCloudVideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:visibility="gone"/>
step 2: 創建Player
接下來創建一個TXLivePlayer的對象,並使用 setPlayerView 接口將這它與我們剛剛添加到界面上的video_view控件進行關聯。
//mPlayerView即step1中添加的界面view TXCloudVideoView mPlayerView = (TXCloudVideoView) view.findViewById(R.id.video_view); //創建player對象 TXLivePlayer mLivePlayer = new TXLivePlayer(getActivity()); //關鍵player對象與界面view mLivePlayer.setPlayerView(mPlayerView);
step 3: 啟動播放器
String flvUrl = "http://2157.liveplay.myqcloud.com/live/2157_xxxx.flv"; mLivePlayer.startPlay(flvUrl, TXLivePlayer.PLAY_TYPE_LIVE_FLV); //推薦FLV
type 參數支持如下幾種選項,有很多客戶反饋 播放有快進現象,那是因為把 LIVE_FLV 和 VOD_FLV 弄混了導致的。
| 可選值 | 枚舉值 | 含義 |
|---|---|---|
| PLAY_TYPE_LIVE_RTMP | 0 | 傳入的URL為RTMP直播地址 |
| PLAY_TYPE_LIVE_FLV | 1 | 傳入的URL為FLV直播地址 |
| PLAY_TYPE_VOD_FLV | 2 | 傳入的URL為FLV點播地址 |
| PLAY_TYPE_VOD_HLS | 3 | 傳入的URL為HLS(m3u8)點播地址 |
| PLAY_TYPE_VOD_MP4 | 4 | 傳入的URL為MP4點播地址 |
| PLAY_TYPE_LIVE_RTMP_ACC | 5 | 低延遲連麥鏈路直播地址(僅適合於連麥場景) |
| PLAY_TYPE_LOCAL_VIDEO | 6 | 手機本地視頻文件 |
step 4: 畫面調整
-
view:大小和位置
如需修改畫面的大小及位置,直接調整 step1中添加的 “video_view” 控件的大小和位置即可。 -
setRenderMode:鋪滿or適應
| 可選值 | 含義 |
|---|---|
| RENDER_MODE_FILL_SCREEN | 將圖像等比例鋪滿整個屏幕,多余部分裁剪掉,此模式下畫面不會留黑邊,但可能因為部分區域被裁剪而顯示不全。 |
| RENDER_MODE_ADJUST_RESOLUTION | 將圖像等比例縮放,適配最長邊,縮放后的寬和高都不會超過顯示區域,居中顯示,畫面可能會留有黑邊。 |
- setRenderRotation:畫面旋轉
| 可選值 | 含義 |
|---|---|
| RENDER_ROTATION_PORTRAIT | 正常播放(Home鍵在畫面正下方) |
| RENDER_ROTATION_LANDSCAPE | 畫面順時針旋轉270度(Home鍵在畫面正左方) |

step 5: 進度調整
調整播放進度這個操作 僅對點播有效 ,因為直播的視頻源是實時的,沒有調整進度的可能。
// 調整進度 mLivePlayer.seek(seekBar.getProgress());
step 6: 暫停播放
-
點播
暫停對於點播的含義相信您不需要我再做贅述。 -
直播
在直播過程中調用pause,效果等同於暫時停止拉流,播放器不會被銷毀,但會顯示最后一幀畫面。
// 暫停 mLivePlayer.pause(); // 繼續 mLivePlayer.resume();
step 7: 結束播放
結束播放時 記得銷毀view控件 ,尤其是在下次startPlay之前,否則會產生大量的內存泄露以及閃屏問題。
同時,在退出播放界面時,記得一定要調用渲染View的onDestroy()函數,否則可能會產生內存泄露和 “Receiver not registered” 報警。
@Override public void onDestroy() { super.onDestroy(); mLivePlayer.stopPlay(true); // true代表清除最后一幀畫面 mPlayerView.onDestroy(); }
stopPlay 的布爾型參數含義為—— “是否清除最后一幀畫面”。早期版本的 RTMP SDK 的直播播放器沒有 pause 的概念,所以通過這個布爾值來控制最后一幀畫面的清除。
step 8: 硬件加速
對於藍光級別(1080p)的畫質,簡單采用軟件解碼的方式很難獲得較為流暢的播放體驗,所以如果您的場景是以游戲直播為主,一般都推薦開啟硬件加速。
軟解和硬解的切換需要在切換之前先stopPlay,切換之后再startPlay,否則會產生比較嚴重的花屏問題。
mLivePlayer.stopPlay(true); mLivePlayer.enableHardwareDecode(true); mLivePlayer.startPlay(flvUrl, type);
step 9: 截流錄制(僅直播)
截流錄制是直播播放場景下的一種擴展功能:觀眾在觀看直播時,可以通過點擊錄制按鈕把一段直播的內容錄制下來,並通過視頻分發平台(比如騰訊雲的點播系統)發布出去,這樣就可以在微信朋友圈等社交平台上以 UGC 消息的形式進行傳播。

//指定一個 ITXVideoRecordListener 用於同步錄制的進度和結果 mLivePlayer.setVideoRecordListener(recordListener); //啟動錄制,可放於錄制按鈕的響應函數里,目前只支持錄制視頻源,彈幕消息等等目前還不支持 mLivePlayer.startRecord(int recordType); // ... // ... //結束錄制,可放於結束按鈕的響應函數里 mLivePlayer.stopRecord();
- 錄制的進度以時間為單位,由 ITXVideoRecordListener 的 onRecordProgress 通知出來。
- 錄制好的文件以 MP4 文件的形式,由 ITXVideoRecordListener 的 onRecordComplete 通知出來。
- 視頻的上傳和發布由 TXUGCPublish 負責,具體使用方法可以參考 短視頻-文件發布。
step 10:視頻截圖
視頻截圖功能滿足了觀眾想將主播直播過程中的精彩畫面進行截圖保存的需求。視頻截圖只會截圖當前視頻流的一幀原始畫面,而不會截取整個屏幕內容。
mLivePlayer.snapshot(new ITXSnapshotListener() { @Override public void onSnapshot(Bitmap bmp) { if (null != bmp) { //獲取到截圖bitmap } } });
狀態監聽
騰訊雲 RTMP SDK 一直堅持白盒化設計原則,你可以為 TXLivePlayer 對象綁定一個 TXLivePlayListener,之后SDK 的內部狀態信息均會通過 onPlayEvent(事件通知) 和 onNetStatus(質量反饋)通知給您。
1. 播放事件
| 事件ID | 數值 | 含義說明 |
|---|---|---|
| PLAY_EVT_PLAY_BEGIN | 2004 | 視頻播放開始,如果有轉菊花什么的這個時候該停了 |
| PLAY_EVT_PLAY_PROGRESS | 2005 | 視頻播放進度,會通知當前進度和總體進度,僅在點播時有效 |
| PLAY_EVT_PLAY_LOADING | 2007 | 視頻播放loading,如果能夠恢復,之后會有BEGIN事件 |
-
不要在收到 PLAY_LOADING 后隱藏播放畫面
因為PLAY_LOADING -> PLAY_BEGIN 的時間長短是不確定的,可能是 5s 也可能是 5ms,有些客戶考慮在 LOADING 時隱藏畫面, BEGIN 時顯示畫面,會造成嚴重的畫面閃爍(尤其是直播場景下)。推薦的做法是在視頻播放畫面上疊加一個半透明的 loading 動畫。 -
LOADING 頻繁與否多是由cacheTime決定的
TXLivePlayConfig 中可以配置播放器的 cacheTime 屬性,如果 cacheTime 屬性被設置的很小,那么 LOADING 就會變得非常頻繁,如果你您發現有頻繁LOADING的情況出現,請參考卡頓&延遲 進行校調。 -
PLAY_PROGRESS 播放進度的處理
如果您對如何處理點播時的 PLAY_EVT_PLAY_PROGRESS 事件沒有思路,可以參考示例代碼-播放進度。
2. 結束事件
| 事件ID | 數值 | 含義說明 |
|---|---|---|
| PLAY_EVT_PLAY_END | 2006 | 視頻播放結束 |
| PLAY_ERR_NET_DISCONNECT | -2301 | 網絡斷連,且經多次重連搶救無效,可以放棄治療,更多重試請自行重啟播放 |
-
如何判斷直播已結束?
如果是點播,我們可以通過 PLAY_EVT_PLAY_END 事件判斷是否已經播放結束。如果是直播,僅靠 SDK 本身是無法獲知主播是否已經結束推流的。可預期的表現是:主播結束推流后,SDK 會很快發現數據流拉取失敗(WARNING_RECONNECT),然后開始重試,直至三次重試失敗后拋出 PLAY_ERR_NET_DISCONNECT 事件。
出現這個問題的原因是標准播放協議中本身沒有通用的 STOP 標准,所以推薦的做法是通過聊天室群發 “直播已結束” 這類系統消息來完成你的目標。
3. 警告事件
如下的這些事件您可以不用關心,我們只是基於白盒化的SDK設計理念,將事件信息同步出來
| 事件ID | 數值 | 含義說明 |
|---|---|---|
| PLAY_WARNING_VIDEO_DECODE_FAIL | 2101 | 當前視頻幀解碼失敗 |
| PLAY_WARNING_AUDIO_DECODE_FAIL | 2102 | 當前音頻幀解碼失敗 |
| PLAY_WARNING_RECONNECT | 2103 | 網絡斷連, 已啟動自動重連 (重連超過三次就直接拋送 PLAY_ERR_NET_DISCONNECT 了) |
| PLAY_WARNING_RECV_DATA_LAG | 2104 | 網絡來包不穩:可能是下行帶寬不足,或由於主播端出流不均勻 |
| PLAY_WARNING_VIDEO_PLAY_LAG | 2105 | 當前視頻播放出現卡頓 |
| PLAY_WARNING_HW_ACCELERATION_FAIL | 2106 | 硬解啟動失敗,采用軟解 |
| PLAY_WARNING_VIDEO_DISCONTINUITY | 2107 | 當前視頻幀不連續,可能丟幀 |
| PLAY_WARNING_DNS_FAIL | 3001 | RTMP-DNS解析失敗(僅播放RTMP地址時會拋送) |
| PLAY_WARNING_SEVER_CONN_FAIL | 3002 | RTMP服務器連接失敗(僅播放RTMP地址時會拋送) |
| PLAY_WARNING_SHAKE_FAIL | 3003 | RTMP服務器握手失敗(僅播放RTMP地址時會拋送) |
4. 連接事件
此外還有幾個連接服務器的事件,主要用於測定和統計服務器連接時間,您也無需關心:
| 事件ID | 數值 | 含義說明 |
|---|---|---|
| PLAY_EVT_CONNECT_SUCC | 2001 | 已經連接服務器 |
| PLAY_EVT_RTMP_STREAM_BEGIN | 2002 | 已經連接服務器,開始拉流(僅播放RTMP地址時會拋送) |
| PLAY_EVT_RCV_FIRST_I_FRAME | 2003 | 網絡接收到首個可渲染的視頻數據包(IDR) |
5. 狀態回調
onNetStatus 通知每秒都會被觸發一次,目的是實時反饋當前的推流器狀態,它就像汽車的儀表盤,可以告知您目前SDK內部的一些具體情況,以便您能對當前網絡狀況和視頻質量等有所了解。
| 評估參數 | 含義說明 |
|---|---|
| NET_STATUS_CPU_USAGE | 當前瞬時CPU使用率 |
| NET_STATUS_VIDEO_WIDTH | 視頻分辨率 - 寬 |
| NET_STATUS_VIDEO_HEIGHT | 視頻分辨率 - 高 |
| NET_STATUS_NET_SPEED | 當前的網絡數據接收速度 |
| NET_STATUS_NET_JITTER | 網絡抖動情況,抖動越大,網絡越不穩定 |
| NET_STATUS_VIDEO_FPS | 當前流媒體的視頻幀率 |
| NET_STATUS_VIDEO_BITRATE | 當前流媒體的視頻碼率,單位 kbps |
| NET_STATUS_AUDIO_BITRATE | 當前流媒體的音頻碼率,單位 kbps |
| NET_STATUS_CACHE_SIZE | 緩沖區(jitterbuffer)大小,緩沖區當前長度為 0,說明離卡頓就不遠了 |
| NET_STATUS_SERVER_IP | 連接的服務器IP |
卡頓&延遲
在直播場景下,能決定一款 APP 產品的用戶體驗好壞的關鍵指標就是:卡頓率的高低和延遲的高低。
播放器本身在其中起到了更為關鍵的決定性作用,同樣的網絡環境和播放地址,不同的播放器可能會表現出完全不同的延遲和卡頓率。(比如 PC 瀏覽器上主流的 flash 播放器會因為播放策略過於簡單粗暴,產生延遲越對越多的問題)
所以,在您完成本篇文檔前面部分羅列的功能代碼對接后,請務必閱讀 卡頓優化-播放端優化 來校調出最適合您的業務場景的播放模式。
- 三種模式的特性對比

- 三種模式的對接代碼
TXLivePlayConfig mPlayConfig = new TXLivePlayConfig(); //自動模式 mPlayConfig.setAutoAdjustCacheTime(true); mPlayConfig.setMinAutoAdjustCacheTime(1); mPlayConfig.setMaxAutoAdjustCacheTime(5); //極速模式 mPlayConfig.setAutoAdjustCacheTime(true); mPlayConfig.setMinAutoAdjustCacheTime(1); mPlayConfig.setMaxAutoAdjustCacheTime(1); //流暢模式 mPlayConfig.setAutoAdjustCacheTime(false); mPlayConfig.setCacheTime(5); mLivePlayer.setConfig(mPlayConfig); //設置完成之后再啟動播放
注意:各家雲商一般都會在CDN端引入 1.5s - 2s 左右的延遲,這是不可避免的,所以 總延遲 = CDN延遲 + CacheTime。
