以前博主有寫過 一篇博文,講的是使用videojs在谷歌瀏覽器網頁上播放rtmp流媒體,具體可參考我以前的博客:http://www.javashuo.com/article/p-ysvyelpd-cz.htmlcss
最近又開始研究了一下網頁播放流媒體,在這裏我要主要補充一些播放rtmp、rtsp流媒體的其餘方法html
從網絡上接收視頻時首先須要要解協議(RTSP/RTMP/HTTP),而後是解格式(MKV,RMVB),以後纔是將視頻(H264)和音頻(AAC)格式數據分別解碼爲圖像(RGB/YUV)和聲音(PCM),再根據時間戳同步播放python
RTSP(Real Time Streaming Protocol),RFC2326,實時流傳輸協議,是TCP/IP協議體系中的一個應用層協議,由哥倫比亞大學、網景和RealNetworks公司提交的IETF RFC標準。該協議定義了一對多應用程序如何有效地經過IP網絡傳送多媒體數據。RTSP在體系結構上位於RTP和RTCP之上,它使用TCP或UDP完成數據傳輸。目前多數網絡攝像機支持RTSP、ONVIF等通用的協議,而支持RTMP比較少c++
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則是當今實際應用中編碼效率最高的音頻編碼標準。git
RTSP和RTMP是2種不一樣的網絡傳輸協議,RTSP(Real Time Streaming Protocol)是實時流傳輸協議,而RTMP是Real Time Messaging Protocol(實時消息傳輸協議)。RTSP主要用於IPTV,緣由是傳輸數據使用的是UDP,在網絡環境比較穩定的狀況下,傳輸效率是比較高的。RTMP主要用於互聯網音視頻傳輸,它使用的是TCP傳輸,由於互聯網環境相對較差,採用RTMP保證了視頻的傳輸質量,可是其傳輸延遲相對較高,傳輸效率相對較低github
參考:https://blog.csdn.net/liujiayu2/article/details/80658395web
http://www.javashuo.com/article/p-siocwqky-bk.html (視音頻編解碼技術,推薦)flask
RTSP直播源地址:後端
rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.movapi
代碼以下:
<!-- 播放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>
效果:
代碼以下:
<!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流媒體
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流媒體的缺點就是沒辦法播放聲音,只有圖片!