如何打造在線直播間(技術貼)

背景

當下視頻直播如此紅火,打造一個在線直播間涉及到哪些技術呢?css

視頻直播由主播的直播端以及觀衆的觀看端組成。一個簡單的觀看端最起碼應包含播放器以及聊天室。下面就圍繞這兩大模塊來說述相關技術。web

視頻直播小程序

視頻直播,能夠分爲視頻採集、前處理、編碼和封裝、傳輸、解封裝和解碼、播放這幾個環節。segmentfault

直播端經過硬件設備採集音視頻數據,通過前處理以及編碼、封裝後,還要傳輸到觀看端。這一步通常交由CDN接力完成。推流端會把視頻流推到源站,CDN從源站拉流,拉流成功後編碼封裝成不一樣的格式提供各觀看端播放。簡單示意圖以下:
網絡引用圖片瀏覽器

接下來說一下觀看端的基本要求:緩存

  • 多終端觀看
  • 觀看穩定、不卡頓
  • 延遲低、高併發

多終端觀看服務器

首先明確須要支持的終端,有移動端APP(iOS、Android)、移動端瀏覽器、小程序、PC瀏覽器、PC 客戶端。對於PC瀏覽器,通常支持到IE8。而且,因爲Chrome瀏覽器默認屏蔽Flash,因此在PC瀏覽器中採用的策略爲:優先在兼容H5的瀏覽器使用H5播放,不然降級使用Flash播放。二者支持的直播播放視頻格式差別以下:websocket

  • Flash支持rtmp或 http-flv 直播播放。延時~3秒。
  • H5支持M3u8直播播放。延時~15秒。

觀看穩定、不卡頓網絡

形成視頻直播卡頓的緣由多是多方面的,涉及到直播端、網絡、觀看端。多線程

直播端

主要問題有硬件配置過低、推流參數配置問題、音視頻時間戳不一樣步。能夠經過如下措施解決:

  • 升級硬件、軟件設置,提升兼容性和容錯率 ( 這部分是硬裝,必須有好的裝備纔能有好的推流質量啊 )。
  • 使用硬編硬解方案,充分利用GPU加速。
  • 下降視頻碼率,選擇流暢、標清畫質或者使用動態碼率推流。

網絡

主要問題有網絡抖動、拉流服務器與觀看端鏈路過長,能夠經過如下措施解決:

  • 選用穩定的運營商網絡併合理佈局CDN節點。
  • 使用充足的網絡帶寬。

觀看端

在網絡上觀看視頻,緩衝區就是在你看視頻時提早儲存部分視頻數據,當數據到達必定的量後再播放畫面,使得播放更流暢。若設置得太小,在網絡不穩定時就沒法流暢地連續播放;若設置過大則會累積時延。因此要設置一個適中的緩衝區。

// Flash
netStream.bufferTime = 1 // 單位:秒
// FLV.js
flvjs.createPlayer({
  type: 'flv',
  isLive: true,
  url: 'video.flv'
},{
  stashInitialSize: 120 // 默認:384KB
})

延時低、高併發

咱們知道,視頻實際上是由一幀一幀的圖像構成的,RTMP基於TCP不會丟包,因此當網絡狀態差時,服務器會將包緩存起來。等網絡情況好了,就一塊兒發給觀看端,致使觀看端累積太多視頻幀數據,延時隨時間增加而增長。對於這個問題,除了上文說起的設置適當的緩衝區長度外,還能夠增長追幀和丟幀操做實現播放追趕。

Flash代碼:

// Flash實現追幀:定時器輪詢檢測當前緩衝區長度大於30秒時重連,從新拉取直播流
netStream.bufferTimeMax = 0.1 // 設置bufferTimeMax主動追幀
​
if(netStream.bufferLength > 30) { 
  // 緩衝區長度大於30,從新鏈接  
  reconnectStream() 
}

H5代碼:

// H5實現追幀,判斷當前緩衝區結束時間與當前時間相差超過5秒,則追幀
if (video.buffered.length > 0 && video.buffered.end(0) - video.currentTime > 5) {
  // 直播流時間接近緩衝時間的話畫面容易卡死,因此保險起見-1秒
  
  video.currentTime = video.buffered.end(0) - 1;

}

另外,若是用到FLV.js播放視頻,能夠開啓它的Worker特性,多線程解析優化延遲 ,並減小buffer。

// FLV.js
flvjs.createPlayer({
  type: 'flv',
  isLive: true,
  url: 'video.flv'
},{
  enableWorker: true,
  enableStashBuffer: false,
  stashInitialSize: 120 // 默認:384KB
})

聊天室

即時聊天IM服務既要保證明時性,可靠性,又要抗住高併發。在實現過程當中咱們使用如下方法解決。

一、傳輸模式優先選擇 WebSocket,若不支持則降級爲輪詢。

const io = require('socket.io')({ "transports":['websocket', 'polling']})

二、Node.js 服務器因消息併發大致使性能低下。

經過如下方案極大的優化了聊天室的穩定性和可靠性。

(1)使用命名空間的功能

命名空間的做用就是把消息限定在必定範圍內傳播。對於一些不須要全局接收的消息就加上命名空間,能夠極大的節約資源的傳輸。

// 建立命名空間
const io = require('socket.io')()
const adminNamespace = io.of('/admin')
​
adminNamespace.to('level1').emit('an event', { some: 'data' })

(2)聊天消息隊列

觀衆進入聊天室房間會廣播登陸消息,好比房間內同時有2W人,每一個人登陸要對房間內全部人廣播"我"登陸了,至關於發送了2W條消息。若併發量大,對服務器性能要求極高。使用聊天隊列消息分批顯示能夠防止同時處理大量消息,提升處理性能。

// 消息隊列
let scoektMsgArr = [{
   EVENT: 'SPEAK',
   uid: socketId,
   content: '這是第一條聊天消息' 
},...]
let minCount = 0
​
setInterval(()=>{
    const maxCount = minCount + 100
    const newScoektMsgArr = scoektMsgArr.slice(minCount, maxCount)
    newScoektMsgArr.forEach((item) => {
       socket.emit('message', JSON.stringify(item))
    })
}, 1000)

(3)服務器彈性伸縮

祭出最後的大招,能優化的已經極力優化了,那剩下的事情就是配置服務器彈(jia)性(fu)伸(wu)縮(qi)。

三、掉線重連機制。

掉線會觸發disconcent 事件,監聽它再建立socket鏈接便可。心跳檢查即定時發送一次消息,保持鏈接狀態。

// 保持心跳
setInterval(()=>{
    socket.emit('message', JSON.stringify({
      EVENT: 'HEARTBEAT',
      uid: socketId
    }))
}, 30 * 60 * 1000)

// 斷開重連
socket.on('disconnect', () => {
    this.connect()
})

connect() {
  socket.on('connect', () => {
     //TODO
  })
}

POLYV SDK 快速搭建在線直播間

按前文所述,搭建直播間有很是多的細節須要考慮,包括採集推流、CDN分發、播放體驗優化、聊天室性能調優等。別擔憂,調用POLYV SDK能夠快速搭建直播間。

(使用POLYV視頻直播服務須要先免費註冊帳號

STEP1 嵌入播放器:

<script src="https://player.polyv.net/livescript/liveplayer.js"></script>
<div id='player'></div>
<script>
    var player = polyvObject('#player').livePlayer({
        'width':'498',
        'height':'409',
        'uid':'e3wx706i3v',
        'vid':'268682' // polyv直播頻道號
    });
</script>

STEP2 嵌入聊天室:

// 默認樣式
<link rel="stylesheet" href="https://player.polyv.net/jssdk/polyv-chatroom.min.css">
​
<script src="https://player.polyv.net/jssdk/polyv-chatroom.min.js"></script>
<div id="wrap"></div>
var chatroom = new PolyvChatRoom({
    roomId: 268682,
    userId: 153075602311,
    nick: '遊客',
    pic: 'http://livestatic.videocc.net/assets/wimages/missing_face.png',
    token: token,
    container: '#wrap',
    width: 300,
    height: 600,
    userType: '',
    roomMessage: function(data) {
        // TODO
        // data爲聊天室socket消息,當有聊天室消息時會觸發此方法
        console.log(data);
    }
});

直播聊天室

如上圖所示,嵌入直播播放SDK + 聊天室SDK便可建立直播間。聊天室SDK中有自帶默認皮膚、發送表情、點贊、送花、在線列表、提問等功能。另外針對直播教育場景需用到的其餘功能,如答題卡、簽到等,可監聽聊天室socket消息自定義實現:

1.答題卡

// 監聽答題內容
var chatroom = new PolyvChatRoom({
    roomId: 268682,
    userId: 153075602313,
    nick: '學員_1',
    pic: 'http://livestatic.videocc.net/assets/wimages/missing_face.png',
    token: token,
    container: '#wrap',
    width: 300,
    height: 600,
    userType: '',
    roomMessage: function(data) {
        // 監聽聊天室消息
        switch(data.EVENT){
            case 'GET_TEST_QUESTION_RESULT':
                // 獲取答題卡內容,顯示答題卡
              break;
            case 'GET_TEST_QUESTION_RESULT': 
              // 獲取答題卡結果, 顯示答題結果
              break;  
        }
    }
});
​```
// 發送答題結果
chatroom.socket.emit('message', JSON.stringify({
    EVENT: 'ANSWER_TEST_QUESTION',
    roomId: channelId,
    nick: nick,
    userId: userId,
    option: result,
    questionId: questionId
}));

答題卡

2.簽到

// 直播端發起簽到
roomMessage: function(data) {
    // 監聽聊天室消息
    switch(data.EVENT){
        case 'SIGN_IN':
            // 發起簽到
            break;
        case 'STOP_SIGN_IN': 
            // 中止簽到
            break;  
    }
}
​
// 觀衆端簽到
chatroom.socket.emit('message', JSON.stringify({
    EVENT: 'TO_SIGN_IN',
    roomId: roomId,
    checkinId: checkinId,
    user: {
        userId: 123456,
        nick: 'polyv'
    }
}));

圖片描述

小程序

除了在瀏覽器端,咱們在小程序端也提供了對應的SDK。

下載小程序SDK後,調用組件快速生成包含播放器、聊天室等功能的直播間。

// 嵌入polyv頁面組件
<view>
  <polyv />
</view>

// 初始化數據
import plv from '*/polyv-sdk/index';
// onLoad
onLoad() {
   const options = {
     channelId: '', // 頻道ID
     openId: '', // 用戶openId
     userName: '', // 用戶名
     avatarUrl: '' // 用戶頭像
   };
   plv.init(options);
}
// onUnload
onUnload() {
  plv.destory();
}

圖片描述

總結:

若是以徹底自研的方式實現教育直播的基礎功能,至少須要10人的技術團隊,5人的產品運營團隊,才能在3個月內完成產品的上線。算下來至少須要幾十萬甚至上百萬。POLYV爲各企業提供了全面的解決方案以及相關文檔,實現快速接入,輕鬆開啓線上教育直播。

資料:

使用flv.js作直播 https://segmentfault.com/a/11...

視頻直播秒開背後的技術與優化經驗 https://juejin.im/post/58eaf4...

socket.io https://socket.io/docs/

相關文章
相關標籤/搜索