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

  • 相关阅读:
    2020年. NET Core面试题
    java Context namespace element 'component-scan' and its parser class ComponentScanBeanDefinitionParser are only available on JDK 1.5 and higher 解决方法
    vue 淡入淡出组件
    java http的get、post、post json参数的方法
    vue 父子组件通讯案例
    Vue 生产环境解决跨域问题
    npm run ERR! code ELIFECYCLE
    Android Studio 生成apk 出现 :error_prone_annotations.jar (com.google.errorprone:error) 错误
    记忆解析者芜青【总集】
    LwIP应用开发笔记之十:LwIP带操作系统基本移植
  • 原文地址:https://www.cnblogs.com/wanglg/p/11511468.html
Copyright © 2020-2023  润新知