rtsp+rtmp多路流媒體播放


一、前言

  之前博主有寫過 一篇博文,講的是使用videojs在谷歌瀏覽器網頁上播放rtmp流媒體,具體可參考我之前的博客:https://www.cnblogs.com/FHC1994/p/9981440.html

  最近又開始研究了一下網頁播放流媒體,在這里我主要補充一些播放rtmp、rtsp流媒體的其他方法

二、rtsp和rtmp流媒體

2.1 視頻傳輸原理

  從網絡上接收視頻時首先需要解協議(RTSP/RTMP/HTTP),然后是解格式(MKV,RMVB),之后才是將視頻(H264)和音頻(AAC)格式數據分別解碼為圖像(RGB/YUV)和聲音(PCM),再根據時間戳同步播放

2.2 RTSP和RTMP介紹

  

  RTSP(Real Time Streaming Protocol),RFC2326,實時流傳輸協議,是TCP/IP協議體系中的一個應用層協議,由哥倫比亞大學、網景和RealNetworks公司提交的IETF RFC標准。該協議定義了一對多應用程序如何有效地通過IP網絡傳送多媒體數據。RTSP在體系結構上位於RTP和RTCP之上,它使用TCP或UDP完成數據傳輸。目前多數網絡攝像機支持RTSP、ONVIF等通用的協議,而支持RTMP比較少

  RTMP是Real Time Messaging Protocol(實時消息傳輸協議)的首字母縮寫。該協議基於TCP,是一個協議族,包括RTMP基本協議及RTMPT/RTMPS/RTMPE等多種變種。RTMP是一種設計用來進行實時數據通信的網絡協議,主要用來在Flash/AIR平台和支持RTMP協議的流媒體/交互服務器之間進行音視頻和數據通信。支持該協議的軟件包括Adobe Media Server/Ultrant Media Server/red5等。使用RTMP技術的流媒體系統有一個非常明顯的特點:使用 Flash Player 作為播放器客戶端,而Flash Player 現在已經安裝在了全世界將近99%的PC上,因此一般情況下收看RTMP流媒體系統的視音頻是不需要安裝插件的。用戶只需要打開網頁,就可以直接收看流媒體,十分方便。直播服務普遍采用了RTMP作為流媒體協議,FLV作為封裝格式,H.264作為視頻編碼格式,AAC作為音頻編碼格式。FLV是RTMP使用的封裝格式,H.264是當今實際應用中編碼效率最高的視頻編碼標准,AAC則是當今實際應用中編碼效率最高的音頻編碼標准。

  RTSP和RTMP是2種不同的網絡傳輸協議,RTSP(Real Time Streaming Protocol)是實時流傳輸協議,而RTMP是Real Time Messaging Protocol(實時消息傳輸協議)。RTSP主要用於IPTV,原因是傳輸數據使用的是UDP,在網絡環境比較穩定的情況下,傳輸效率是比較高的。RTMP主要用於互聯網音視頻傳輸,它使用的是TCP傳輸,因為互聯網環境相對較差,采用RTMP保證了視頻的傳輸質量,但是其傳輸延遲相對較高,傳輸效率相對較低

 

  參考:https://blog.csdn.net/liujiayu2/article/details/80658395

                  https://blog.csdn.net/leixiaohua1020/article/details/18893769 (視音頻編解碼技術,推薦)

2.3 補充 

  RTSP直播源地址:

    rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov

三、rtsp、rtmp播放方法

3.1 videojs播放rtmp流媒體——videojs不支持rtsp——僅支持在Hbuilder等自帶服務器環境下打開才可以播放rtmp

代碼如下:

<!-- 播放rtmp網絡視頻 -->
<!DOCTYPE html>
<html>
    <head>
        <title>播放器</title>
        <link href="./videolib/css/video-js.min.css" rel="stylesheet" type="text/css">
        <style>
            html,body{
                height: 100%;
                width: 100%;
                padding: 0;
                margin: 0;
            }
        </style>
    </head>
    <body>
        <div>
            <video id="myvideo1" width="350" height="250" class="video-js vjs-default-skin" muted controls>
                <!-- rtmp視頻流 -->
                <source src="rtmp://202.69.69.180:443/webcast/bshdlive-pc" type="rtmp/flv">
            </video>
            <br />
            <video id="myvideo2" width="350" height="250" class="video-js vjs-default-skin" muted controls>
                <!-- rtmp視頻流 -->
                <source src="rtmp://media3.sinovision.net:1935/live/livestream" type="rtmp/flv">
            </video>
        </div>
        <script src="./videolib/js/video.min.js"></script>
        <script src="./videolib/videojs-flash.min.js"> </script>
        <script>
            var player1 = videojs("myvideo1", {}, function() {
                console.log("videojs播放器初始化成功")
            })
            player1.play()
            var player2 = videojs("myvideo2", {}, function() {
                console.log("videojs播放器初始化成功")
            })
            player2.play()
        </script>
    </body>
</html>

效果:

3.2 flowplayerjs播放rtmp流媒體——flowplayerjs不支持rtsp——支持在本地直接打開播放rtmp

代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>rtmp直播</title>
    <link rel="stylesheet" href="./css/video-js.css">
    <link rel="stylesheet" href="./css/h5splayer.css">
    <script src="./js/flowplayer-3.2.13.min.js"></script>
</head>
<body>
    <div class="h5video" id="playerDiv1" style="float: left;"></div>    
    <div class="h5video" id="playerDiv2" style="float: left;"></div>
    <div class="h5video" id="playerDiv3" style="float: left;"></div>
    <script>
            
        // 播放地址
        var url_1 = 'rtmp://202.69.69.180:443/webcast/bshdlive-pc';
        var url_2 = 'rtmp://media3.sinovision.net:1935/live/livestream';
        var url_3 = 'rtmp://58.200.131.2:1935/livetv/hunantv';

        var oPlayerDiv1 = document.getElementById('playerDiv1');
        var    oPlayerDiv2 = document.getElementById('playerDiv2');
        var    oPlayerDiv3 = document.getElementById('playerDiv3');

        oPlayerDiv1.setAttribute("data-rtmp", url_1);
        oPlayerDiv1.setAttribute("href", url_1);

        oPlayerDiv2.setAttribute("data-rtmp", url_2);
        oPlayerDiv2.setAttribute("href", url_2);

        oPlayerDiv3.setAttribute("data-rtmp", url_3);
        oPlayerDiv3.setAttribute("href", url_3);

        var swfStr = "./swf/flowplayer-3.2.18.swf"
        var    obj_1 = {
                clip: {
                    provider: 'rtmp',
                    bufferLength: 0,
                    bufferTime: 0,
                    autoPlay: true,
                    live: true
                },
                plugins: {
                    rtmp: {
                        url: "flowplayer.rtmp-3.2.13.swf",
                        netConnectionUrl: url_1
                    }
                }
            };
            
        const obj_2 = JSON.parse(JSON.stringify(obj_1))   //js對象的深拷貝   // JSON.stringify() 方法將 JavaScript 對象轉換為字符串   JSON.parse() 方法將數據轉換為 JavaScript 對象
        obj_2.plugins.rtmp.netConnectionUrl = url_2;
        const obj_3 = JSON.parse(JSON.stringify(obj_1)) 
        obj_3.plugins.rtmp.netConnectionUrl = url_3;

        flowplayer('playerDiv1', swfStr, obj_1);
        flowplayer('playerDiv2', swfStr, obj_2);
        flowplayer('playerDiv3', swfStr, obj_3);
    </script>
</body>
</html>

效果:

 注意!!!

  1. 由於RTMP協議是在 Flash 播放器上播放的,所以對於H5的video播放器是不能直接播放的,必須要讓所用瀏覽器支持flash,才可以播放rtmp流媒體。目前來說,谷歌瀏覽器是支持Flash的,但是在2020年12月后谷歌瀏覽器將不再支持Flash,所以以上兩種方法只能暫時使用,並不是長久之計!  

  

   2. flowplayerjs不支持rtsp流媒體,瀏覽器原生js只支持http,基於flash的播放器也只能支持到rtmp,如果要支持rtsp需要使用c/c++插件(npapi或者activex)。videojs同樣如此,不支持rtsp流媒體

3.3 python搭建flask服務器播放rtsp、rtmp流媒體

python代碼如下:

from flask import Flask, render_template, Response
import cv2

class VideoCamera():
    def __init__(self,vurl):
        # 通過opencv獲取實時視頻流
        self.video = cv2.VideoCapture(vurl)

    def __del__(self):
        self.video.release()

    def get_frame(self):
        success, image = self.video.read()
        ret, jpeg = cv2.imencode('.jpg', image)
        #轉化為字節流
        return jpeg.tobytes()

# app是Flask的實例,它接收包或者模塊的名字作為參數,但一般都是傳遞__name__
app = Flask(__name__)
@app.route('/')  # 主頁
def index():
    return render_template('index.html')

@app.route('/video1_feed')  # 這個地址返回rtsp視頻流響應
def video1_feed():
    return Response(gen1(VideoCamera("rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov")), mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/video2_feed')  # 這個地址返回rtmp視頻流響應
def video2_feed():
    return Response(gen2(VideoCamera("rtmp://202.69.69.180:443/webcast/bshdlive-pc")), mimetype='multipart/x-mixed-replace; boundary=frame')\

@app.route('/video3_feed')  # 這個地址返回rtmp視頻流響應
def video3_feed():
    return Response(gen3(VideoCamera("rtmp://media3.sinovision.net:1935/live/livestream")), mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/video4_feed')  # 這個地址返回rtmp視頻流響應
def video4_feed():
    return Response(gen4(VideoCamera("rtmp://58.200.131.2:1935/livetv/hunantv")), mimetype='multipart/x-mixed-replace; boundary=frame')

def gen1(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
def gen2(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
def gen3(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
def gen4(camera):
    while True:
        frame = camera.get_frame()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

if __name__ == '__main__':
    app.run(host='127.0.0.1', debug=True, port = 5000)

html代碼如下:

<html>
    <head>
        <title>多路視頻直播</title>
        <style>
            html, body {
                height: 100%;
                width: 100%;
                padding: 0;
                margin: 0;
            }
            .divbg{
                width:300px;
                height:200px;
            }
            .videostyle{
                min-height: 100%;
                min-width: 100%;
                max-height: 100%;
                max-width: 100%;
            }
        </style>
    </head>
    <body>
        <h2>rtsp流媒體</h2>
        <!-- 第一個rtsp視頻流 -->
        <div class="divbg">
            <img  class="videostyle" src="{{ url_for('video1_feed') }}">
        </div>
        <br>
        <h2>rtmp流媒體</h2>
        <!-- 第一個rtmp視頻流 -->
        <div class="divbg" style="float: left; margin-right: 5px;">
            <img class="videostyle" src="{{ url_for('video2_feed') }}">
        </div>
        <!-- 第二個rtmp視頻流 -->
        <div class="divbg" style="float: left; margin-right: 5px;">
            <img  class="videostyle" src="{{ url_for('video3_feed') }}">
        </div>
        <!-- 第三個rtmp視頻流 -->
        <div class="divbg" style="float: left;">
            <img class="videostyle" src="{{ url_for('video4_feed') }}">
        </div>
    </body>
</html>

 

效果:

python控制台:

 

 

 網頁效果:

 注意!!!

   python搭建一個flask服務器后,就可以播放任何格式的流媒體協議,因為flask后端直接將視頻流轉換為一幀一幀的圖片,然后推送到網頁上顯示即可!但是,python搭建flask服務器播放rtsp、rtmp流媒體的缺點就是沒辦法播放聲音,只有圖片!

 源程序可到博主github上下載:https://github.com/HuerFu/h5_rtmp_play


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM