網上關於直播相關的文章很多,但是講解還是不夠系統,對於剛剛接觸直播開發的朋友實施起來會浪費不少時間。下面結合我自己的經驗,
介紹一下直播方面的實戰經驗。
分成兩個部分
第一部分是標題中介紹的基於RTMP推送文件流與視頻流,PC端拉流RTMP,移動端拉流m3u8也就是hls
下一篇介紹基於websocket+canvas,進行拉流播放。
一 准備工作
1.准備RTMP服務器,我是在win10下開發,我是安裝了docker for windows,然后下載鏡像nginx-rtmp-server,(使用linux的朋友就更方便了,docker pull antongulenko/rtmp-nginx-server),點擊Create后自動安裝
安裝完成后,保存當前的端口號,為了防止每次重啟容器端口號自動分配,點擊保存按鈕 如圖:
1935是本機RTMP對應的端口,外部映射的是 32781,稍候我們會用到這個端口號進行推流。
此時nginx還沒有進行配置,我們需要配置,首先找到nginx.conf,
首先進入容器,具體的操作我只記錄docker for windows的,linux就更簡潔了,docker exec 容器id。
可以查看容器的目錄結構
nginx的路徑是etc/nginx/nginx.conf
首先拷貝下來,修改后,再覆蓋回去,覆蓋后要重啟nginx,才能生效。
下面的指令是分別從容器上把配置文件拷貝到D盤,修改后 將文件覆蓋回容器內
具體conf內容如下:
worker_processes auto; rtmp_auto_push on; events {} rtmp { server { listen 1935; listen [::]:1935 ipv6only=on; application vod { play /opt/rtmp/vod; } application mirror_cache { play /opt/rtmp/vod_mirror; } application live{ # enable live streaming live on; max_connections 1024; } application hls{ live on; hls on; hls_path /usr/local/hls; hls_fragment 5s; } # Application names cannot contain patterns, and play_local_path fails for cached files # that contain slashes (error dir not found). Therefore, list every path of interest as a separate # application, so that only files without directory prefix are cached. application mirror/720 { play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/720/; play_local_path /opt/rtmp/vod_mirror; } application mirror/480 { play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/480/; play_local_path /opt/rtmp/vod_mirror; } application mirror/360 { play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/360/; play_local_path /opt/rtmp/vod_mirror; } application mirror/240 { play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/240/; play_local_path /opt/rtmp/vod_mirror; } } } http { server { listen 8080; # This URL provides RTMP statistics in XML location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { root /opt/rtmp/http/; } location /hls{ types{ application/vnd.apple.mpegurl m3u8; video/mp2t ts; } alias /usr/local/hls; add_header Cache-Control no-cache; } location /vod { autoindex on; alias /opt/rtmp/vod; } location /mirror_cache { autoindex on; alias /opt/rtmp/vod_mirror; } location /mirror/ { proxy_pass http://www.sample-videos.com/video/; } } }
配置文件中的 application live 與 application hls就是分別推送rtmp與hls協議的路由地址
而http節點就是用於手機端使用m3u8播放的時候(http://ip+port/hls/秘鑰.m3u8)的配置。
然后重啟容器就可以了。
2.github下載https://github.com/BoonyaCSharp-ASP/VedioFFmpegPushRTMP
基於c#封裝的FFMPEG的推流方法,使用的時候需要下載FFMPEG的相關文件,
我這里提供一下連接,直接解壓覆蓋,注意link類型為shared
https://ffmpeg.zeranoe.com/builds/
這個c#工程可以直接運行,配置使用也是很難得,不過我為了測試方便還是直接用命令行的方式進行推流
命令行進入x64文件夾下,直接使用ffmpeg.exe進行推流,ffplay.exe以直接進行播放。
下面開始推流:
1.推送文件流,我在x64下面放置了1.MP4的文件
推流指令如下
ffmpeg.exe -re -i 1.mp4 -f flv rtmp://192.168.1.253:32781/rtmp/test
192.168.1.253是我的rtmp服務器ip 32781是docker中rtmp的外部端口 (如果不使用docker自然就是1935了)
rtmp 是nginx.conf 配置的rtmp的路由節點名稱 test類似於房間號的概念,拉流的時候也指定這個房間號,就可以對應到自己要看的直播流
推流如下:
如果有異常信息就是相關參數的配置,具體問題留言討論。
拉取文件流
可以下載vlc播放器,然后配置拉流地址 rtmp://192.168.1.253:32781/rtmp/test 就可以點擊播放
PC端播放rtmp代碼如下,建議使用Chrome,並且設置flash允許
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用video.js實現rtmp流的直播播放</title> <!--引入播放器樣式--> <link href="http://vjs.zencdn.net/5.19/video-js.min.css" rel="stylesheet"> <!--引入播放器js--> <script src="http://vjs.zencdn.net/5.19/video.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs- flash.min.js"></script> </head> <body> <!--vjs-big-play-centered 播放按鈕居中--> <!--poster默認的顯示界面,就是還沒點播放,給你顯示的界面--> <!--controls 規定瀏覽器應該為視頻提供播放控件--> <!--preload="auto" 是否提前加載--> <!--autoplay 自動播放--> <!--loop=true 自動循環--> <!--data-setup='{"example_option":true}' 可以把一些屬性寫到這個里面來,如data-setup= {"autoplay":true}--> <video id="my-player" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" autoplay="autoplay" poster="//vjs.zencdn.net/v/oceans.png" width="500" height="400" data- setup='{}'> <!--src: 規定媒體文件的 URL type:規定媒體資源的類型--> <source src='rtmp://192.168.1.253:32781/live/test' type='rtmp/flv'/> </video> <script type="text/javascript"> // 設置flash路徑,用於在videojs發現瀏覽器不支持HTML5播放器的時候自動喚起flash播放器 videojs.options.flash.swf = 'https://cdn.bootcss.com/videojs-swf/5.4.1/video- js.swf'; var player = videojs('my-player'); //my-player為頁面video元素的id player.play(); //播放 // 1. 播放 player.play() // 2. 停止 player.pause() // 3. 暫停 player.pause() </script> </body> </html>
2.推送視頻流
如果直接按照如下命令推送
ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -acodec aac -f flv rtmp://192.168.1.253:32781/live/test
很有可能vlc ffplay可以正常拉流播放,但是網頁播放不了,推薦一個網址測試對應的rtmp協議流是否能通過flash播放
https://blog.csdn.net/liuzehn/article/details/81036195
可用的RTMP源:http://www.mamicode.com/info-detail-2539819.html
如果測試過程中能夠接受到流,但是不能播放就是視頻格式的問題,
這時候使用如下的指令進行播放:
ffmpeg.exe -f dshow -i video="Integrated Camera" -vcodec libx264 -pix_fmt yuv420p -f flv rtmp://192.168.1.253:32781/live/test
其中 Integrated Camera 是攝像頭的名字,如果是USB的則填寫對應的名字
具體的獲得攝像頭名稱的操作方式參考:
https://www.jianshu.com/p/c141fc7881e7
3.推送視頻流,hls播放
推流指令如下:
ffmpeg.exe -f dshow -i video="Integrated Camera" -vcodec libx264 -pix_fmt yuv420p -f flv rtmp://192.168.1.253:32781/hls/test
移動端拉流代碼:
<!DOCTYPE html> <html lang="en"> <head> <title>Video.js | HTML5 Video Player</title> <!-- <link href="video-js-6.2.0/video-js.css" rel="stylesheet"> <script src="video-js-6.2.0/videojs-ie8.min.js"></script> --> <link href="http://vjs.zencdn.net/5.20.1/video-js.css" rel="stylesheet"> <script src="http://vjs.zencdn.net/5.20.1/videojs-ie8.min.js"></script> </head> <body> <video id="example_video_1" class="video-js vjs-default-skin" controls preload="auto" width="1280" height="720" poster="http://vjs.zencdn.net/v/oceans.png" data-setup="{}"> <!-- <source src="1.mp4" type="video/mp4"> rtmp://192.168.1.253:32781/live/test --> <source src="http://192.168.1.253:32780/hls/test.m3u8" type="application/x- mpegURL" > <p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p> </video> <object height="900px" width="100%" classid="clsid:D27CDB6E-AE6D-11cf-96B8- 444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#versio n=9,0,28,0" id="abcdef"> <param value="index.swf(flash路徑)" name="movie"> <param value="high" name="quality"> <param value="transparent" name="wmode"> <embed height="900px" width="100%" name="abcdef" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/shockwave/download/download.cgi? P1_Prod_Version=ShockwaveFlash" quality="high" src="rtmp://192.168.1.253:32781/live/test"> </object> <script src="http://vjs.zencdn.net/5.20.1/video.js"></script> </body> </html>
rtmp如果有vlc會有延遲,是vlc本身的緩存原因,ffplay幾乎0延遲,PC版本的一秒左右延遲,m3u8分片的方式處理,所以延遲會比較明顯。
flv的直播 可參考連接https://hub.docker.com/r/mugennsou/nginx-http-flv ,但是需要注意的是
如果要推送攝像頭到服務器並在手機端顯示,要參考下面的指令和代碼:
推送指令:
<!DOCTYPE html> <html lang="en"> <head> <title>video</title> <!-- Video.js --> <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet"> <script src="https://unpkg.com/video.js/dist/video.min.js"></script> <script src="https://unpkg.com/flv.js/dist/flv.min.js"></script> <script src="https://unpkg.com/videojs-flvjs/dist/videojs-flvjs.min.js"></script> </head> <body>qwer <div> <video id="videojs-flvjs-player" class="video-js vjs-default-skin vjs-big-play-centered" width="1024" height="768"> </video> </div> </body> </html> <script> var flvUrl = "http://192.168.1.253:32783/live?app=demo&stream=stream-1"; //flvUrl="https://mister-ben.github.io/videojs-flvjs/bbb.flv" var player = videojs('videojs-flvjs-player', { techOrder: ['html5', 'flvjs'], flvjs: { mediaDataSource: { isLive: true, cors: true, withCredentials: false, }, }, sources: [{ src: flvUrl, type: 'video/mp4' }], controls: true, preload: "none" }, function onPlayerReady() { console.log('player ready') player.on('error', (err) => { console.log('first source load fail') player.src({ src: flvUrl, type: 'video/x-flv' }); player.ready(function() { console.log('player ready') player.load(); player.play(); }); }) }); </script>
html文件最好是放到服務器中運行,本地打開的html頁可能無法正常顯示。
下一篇再介紹基於websocket的移動端直播