c# 基於RTMP推流 PC+移動端 拉流播放


網上關於直播相關的文章很多,但是講解還是不夠系統,對於剛剛接觸直播開發的朋友實施起來會浪費不少時間。下面結合我自己的經驗,

介紹一下直播方面的實戰經驗。

分成兩個部分

第一部分是標題中介紹的基於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 ,但是需要注意的是

如果要推送攝像頭到服務器並在手機端顯示,要參考下面的指令和代碼:

推送指令:

 ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -pix_fmt yuv420p  -f flv rtmp://192.168.1.253:32782/demo/stream-1 
-pix_fmt yuv420p 這個參數很關鍵,是把攝像頭或者是桌面的RGB編碼轉成H264轉成YUV格式,最終轉化成H264編碼
 
Html界面代碼:
<!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的移動端直播

 


免責聲明!

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



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