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的移动端直播

原文地址:https://www.cnblogs.com/wanglg/p/11511468.html