前端如何實現整套視頻直播技術流程

NO IMAGE

目錄大綱:

  1. 直播技術的簡單介紹
  2. 前端搭建使用的技術
  3. 實踐效果
  4. 後續需要深入的地方

簡介:

首先說明,本篇文章是概念+實踐,對於希望瞭解和實踐一個簡單的攝像頭直播網頁功能的人會有幫助,由於篇幅和實踐深入度有限,目前demo效果只支持直播播放電腦端以及常用攝像頭的實時視頻流,其他複雜的功能(例如視頻信息實時處理,高併發,網絡分發等)尚未實現,還需要進一步探索。

正文:

下面按照目錄大綱來一個一個講解:

1. 直播技術的介紹

直播技術涵蓋很廣,現如今大家廣泛瞭解的就有視頻網站的個人直播、手機直播、安防方面的攝像頭監控等會使用到直播的技術;

下面先出一張概念圖,介紹直播流程中的各個技術環節。可以理解分為採集端、流媒體服務器以及播放端;還需要了解什麼是推流,什麼是拉流。

前端如何實現整套視頻直播技術流程

  • 採集端:顧名思義是視頻的源頭,視頻的採集一般都是從真實的攝像頭中得到的。例如移動端設別、PC端設備的攝像頭以及一些攝像頭設備
  • 流媒體服務器:流媒體服務器是整個直播技術框架的非常重要的一環,它需要接收從採集端推上來的視頻流,然後將該視頻流再推送到播放端
  • 播放端:播放端就是各種app,網頁中的播放器,拉取流媒體服務器上的視頻流,然後進行轉碼,最終播放出來
  • 推流:把採集階段收集的數據封裝好傳輸到服務器的過程
  • 拉流:服務器已有直播內容,用指定地址進行拉去的過程

既然需要推流和拉流, 就必然涉及到視頻流的傳輸,所以接下來介紹常用的流媒體傳輸協議
常用的流媒體傳輸協議有RTMP,RTSP,HLS,HTTP-FLV

  • RTMP:(可用於推流端和拉流端)
    Real Time Messaging Protocol 實時消息傳輸協議,RTMP協議中,視頻必須是H264編碼,音頻必須是AAC或MP3編碼,且多以flv格式封包。因為RTMP協議傳輸的基本是FLV格式的流文件,必須使用flash播放器才能播放.

  • RTSP:(用於推流端)
    Real-Time Stream Protocol,RTSP 實時效果非常好,適合視頻聊天、視頻監控等方向

  • HLS(用於拉流端)
    Http Live Streaming,由Apple公司定義的基於HTTP的流媒體實時傳輸協議。傳輸內容包括兩部分:1.M3U8描述文件,2.TS媒體文件。TS媒體文件中的視頻必須是H264編碼,音頻必須是AAC或MP3編碼。數據通過HTTP協議傳輸。目前video.js庫支持該格式文件的播放

  • HTTP-FLV(用於拉流端)
    本協議就是http+flv,將音視頻數據封裝成FLV格式,然後通過http協議傳輸到客戶端,這個協議大大方便了瀏覽器客戶端播放直播視頻流.目前flv.js庫支持該格式的文件播放

有了以上基本概念之後,我們就大致知道要搭建一個擁有直播功能的頁面需要哪些東西了,下面就基於這個架構進行各個部分的實現

2. 前端搭建使用的技術

  • 搭建流媒體服務

    提到流媒體服務器,其實作為開發前端的人來說,本人一開始也是無所適從的,不知道這個東西該怎麼實現或者要用什麼語言去寫.首先想到的肯定是搜索現有的實現技術,看看是否能夠通過純前端去實現,純JS技術的話,肯定首先想到了node.js,於是就使用node.js+視頻流媒體技術實現方案的關鍵詞去搜索,獲得了一個看著比較靠譜的結果:NodeMediaServer,然後去看介紹發現是基於node去實現的一個開源的流媒體服務器,雖然最新版本已經使用go去重構了,但是畢竟歷史上它是由node來開發的,所以決定看文檔試一試搭建一個這樣的服務器.NodeMediaServer官網: 鏈接

    NodeMediaServer支持:以rtmp,rtsp,hls協議拉進行推流,支持http-flv,ws-flv來進行拉流,也就是支持瀏覽器端使用http或websocket傳輸flv格式的視頻流進行播放

    開始搭建流媒體服務器:

    • 下載對應的安裝包,使用的Linux環境

      下載:

      wget https://cdn.nodemedia.cn/nms/3.2.12/nms-linux-amd64-20200222.tar.gz
      

      解壓:

      tar -zxvf nms-linux-amd64-20200222.tar.gz
      

      到解壓後的目錄下,執行命令,啟動服務

      • 在控制檯輸入 ./nms運行
      • 在當前程序目錄下執行 sudo ./service.sh install 安裝服務並自動運行
      • 在當前程序目錄下執行 sudo ./service.sh uninstall 停止並卸載服務
    • 服務成功啟動之後,可以在8000端口(默認端口)訪問流媒體服務的後臺系統,這裡面大概長下面這個樣子:

      前端如何實現整套視頻直播技術流程

      首頁dashboard展示了服務器cpu的使用情況以及網絡帶寬狀況

  • 服務啟動之後,接下來要做的是推流

    怎麼推流?這裡涉及到一個很強大的東西ffmpeg,它是可以用來記錄、轉換數字音視頻,並將其轉化為流的開源軟件,通過它可以進行視頻的採集封裝成流,並推送到流媒體服務器,例如在mac上面安裝了這個軟件之後,可以通過它調用攝像頭,並將攝像頭數據封裝成流後推送到流媒體服務器,這個過程就是推流.ffmpeg還可以推送本地的視頻文件到流媒體服務器.

    使用ffmpeg進行mac本地攝像頭實時推流到nodeMediaServer:

    ffmpeg -f avfoundation -video_size 1280x720 -framerate 30 -i 0:0 -vcodec libx264 -preset veryfast -f flv http://ip:8000/live/stream.flv
    

    這裡涉及到ffmpeg工具,上面的參數不逐一解釋,只是最重要的幾個:

    • -vide_size 表示要輸出的視頻畫面的分辨率尺寸
    • -f 後面的參數 flv表述輸出的格式,再後面的地址 http://ip:8000/live/stream.flv 表示想要輸出的地址,這個地址的stream.flv可以按照自己需求隨意修改,保持後綴是你需要的flv格式即可

    另外一種常用的場景是直接拉去攝像頭設備中的視頻流數據,這種方式,nodeMediaServer也支持,只需要在管理後臺配置對應的攝像頭的配置信息,就可以進行推流操作了.這些配置信息包括ip,登錄用戶名和密碼等,配置界面如下所示:

    預設配置:

    前端如何實現整套視頻直播技術流程

    還可以自定義設定配置,如果使用的是自定義的攝像頭,具備rtsp傳輸功能的,就可以使用西面的配置方式進行攝像頭信息的配置,指定輸出流地址,這樣直接從瀏覽器端就可以通過這個輸出流地址進行視頻的播放:

    前端如何實現整套視頻直播技術流程

  • 前端頁面支持播放視頻流

    前端頁面部分,首要目標是找到支持http-flv和ws-flv協議格式的前端播放器,首先去觀察了B站的直播,發現他們的直播頁面是使用的video標籤,後來進一步發掘,才知道他們用的是自己開源的flv.js庫,這是一個支持在瀏覽器端進行http-flv及ws-flv格式的視頻流進行播放的播放器,正好是播放直播視頻流需要的

    視頻流有了,那麼就可以使用flv.js來搭建頁面demo,查看實際效果了

3. 實踐效果

  • 首先搞定推流:

    分別實驗了直接從mac上推攝像頭的視頻流數據以及綁定攝像頭設備地址信息,通過nodeMediaServer進行推流和拉流服務.

  • 然後是前端頁面進行視頻流的播放,下面是播放器部分的核心代碼:

    live-demo.js

    import * as React from 'react';
    import { Button, Input, Row, Col } from 'react-x-component';
    import flv from 'flv.js';
    const { useState, useEffect } = React;
    interface LiveDemoProps {
    defaultUrl?: string,
    onUrlChange?: Function
    }
    export default function LiveDemo({ defaultUrl = 'http://ip:8000/live/stream.flv', onUrlChange }: LiveDemoProps) {
    let player = null;
    let playerDom = null;
    const [liveUrl, setLiveUrl] = useState(defaultUrl);
    useEffect(() => {
    if (flv.isSupported) {
    player = flv.createPlayer({
    type: 'flv',
    isLive: true,
    hasAudio: false,
    hasVideo: true,
    url: liveUrl,
    cors: true
    }, {
    enableWorker: false,
    lazyLoadMaxDuration: 3 * 60,
    seekType: 'range'
    });
    player.attachMediaElement(playerDom);
    player.load();
    } else {
    console.log('Your browser is not support flv.js');
    }
    }, []);
    function updatePlayer() {
    if (player) {
    player.unload();
    player.detachMediaElement();
    player.destroy();
    player = null;
    }
    player = flv.createPlayer({
    type: 'flv',
    isLive: true,
    hasAudio: false,
    hasVideo: true,
    url: liveUrl,
    cors: true
    }, {
    enableWorker: false,
    lazyLoadMaxDuration: 3 * 60,
    seekType: 'range'
    });
    player.attachMediaElement(playerDom);
    player.load();
    }
    return (
    <div className='live-demo'>
    <div className="modify-url">
    <Row>
    <Col md={6}>
    <Input
    value={liveUrl}
    onChange={(value) => {
    setLiveUrl(value);
    }}
    />
    </Col>
    <Col md={6}>
    <Button
    type={'primary'}
    onClick={() => {
    updatePlayer();
    onUrlChange && onUrlChange(liveUrl);
    }}
    >修改</Button>
    </Col>
    </Row>
    </div>
    <video
    style={{ width: '100%', height: '100%' }}
    controls
    className='video-demo'
    ref={(e) => playerDom = e}
    ></video>
    </div>
    );
    }
    
  • 播放攝像頭的視頻流效果,左邊是直接獲取的攝像頭數據流,右邊是通過mac電腦推的實時的攝像頭畫面:

    前端如何實現整套視頻直播技術流程

OK,這樣就搞定了一整套直播網頁需要的前後端技術服務的搭建了!

4. 後續需要繼續繼續實踐和探索的內容

上面的示例相對而言還過於簡單,只是藉助了第三方的技術和框架搭建了一個流媒體服務器,和前端支持播放視頻流的播放頁面,並通過攝像頭採集數據,推流,打通了整個流程,形成了一個閉環,但是還有很多內容需要進一步深入:

  • 視頻信息實時處理,如何添加更多的信息
  • 高併發場景是如何去實現的,流媒體服務器這塊的實現還是過於簡單,肯定還有需要分發處理的機制
  • 瀏覽器播放性能需要進行壓力測試

總結

本文通過概念學習和介紹,理解了常見視頻直播技術的整體架構流程,基於前端的角度去快速搭建了一套完整的直播網頁的功能,當然其中還有很多不足和需要深入的地方,需要進一步探索,後續如果有更深入的技術沉澱,會繼續形成文章進行分享!

相關文章

2020年你不能不知道的webpack基本配置

風物長宜放眼量,人間正道是滄桑一位北美IT技術人破局

領域驅動設計(DDD)實踐之路(一)

Java併發編程—併發流程控制與AQS原理及相關源碼解析