暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

openresy+nginx-rtmp-module搭建点播直播服务器

        一般点播或者直播服务器都是使用nginx-rtmp-module作为服务器,然后使用ffmpeg或者obs来进行推流,客户端使用rtmp、http-flv、hls或者dash协议拉取转码后的数据,进行播放。

       网上很多编译nginx+nginx-rtmp-module的方法,但是很少有可用的openresy+nginx-rtmp-module的编译方法。本文就从模块编译开始介绍下如何搭建点播、直播服务器。

      首先下载openresty源码:https://github.com/openresty/openresty;如果仅仅编译nginx-rtmp-module,可以下载https://github.com/arut/nginx-rtmp-module,如果想额外支持http-flv协议,可以下载https://github.com/winshining/nginx-http-flv-module.git,后者包含了前者。

        接着我们编译openresty

    cd openresty/openresty-1.25.3.1 
    ./configure  --add-module=../../nginx-http-flv-module
    复制

            然后

      make
      sudo make install
      复制

              就完成了编译,不过实践过程中遇到了下面几个问题,值得分享下:

        openresty/openresty-1.25.3.1/../../nginx-http-flv-module/hls/ngx_rtmp_hls_module.c:2059:27: error: use of undeclared identifier 'NGX_RTMP_FRAME_IDR'
        frame.key = (ftype == NGX_RTMP_FRAME_IDR);
        ^
        10 errors generated.
        make[2]: *** [objs/addon/hls/ngx_rtmp_hls_module.o] Error 1
        make[1]: *** [build] Error 2
        make: *** [all] Error 2
        复制

        出现问题的原因是我们config错误了,nginx-http-flv-module 模块中包含nginx-rtmp-module模块的功能,只需安装nginx-http-flv-module 模块即可。也就是说,下面的配置方法是错误的。

          ./configure --add-module=../../nginx-rtmp-module --add-module=../../nginx-http-flv-module
          复制

          然后是make过程中的warning

            ld: warning: dylib (/usr/local/Cellar/gcc/11.2.0/lib/gcc/11/libstdc++.dylib) was built for newer macOS version (11.3) than being linked (11.1)
            复制

            设置下环境变量即可

              export MACOSX_DEPLOYMENT_TARGET=11.3
              复制

              然后是make install的时候遇到的

                 cp: /openresty/openresty-1.25.3.1/build/resty.index: No such file or directory
                make: *** [install] Error 1
                复制
                  build/pod: No such file or directory
                  make: *** [install] Error 1
                  复制

                  上述两个问题,在网上没有找到好的解决办法,目测这俩文件对安装没有大的影响,我的解决办法是在make install之前先创建它俩。

                    touch build/resty.index
                    touch build/pod
                    复制

                    然后问题就解决了。正确安装后展示如下:

                      mkdir -p usr/local/openresty/site/lualib usr/local/openresty/site/pod usr/local/openresty/site/manifest
                      ln -sf usr/local/openresty/nginx/sbin/nginx usr/local/openresty/bin/openresty
                      复制

                      然后我们运行下

                         /usr/local/openresty/bin/openresty
                        复制
                           ps aux |grep openresty
                          xiazemin 28175 0.0 0.0 4268424 732 s016 S+ 4:27下午 0:00.00 grep openresty
                          root 25010 0.0 0.0 4306592 584 ?? Ss 4:27下午 0:00.00 nginx: master process usr/local/openresty/bin/openresty
                          复制

                          没有报错,说明编译成功。

                                  接着我们安装ffmpeg来进行推流,直接brew install ffmpeg会慢到让你怀疑人生。果断放弃,直接采用docker 镜像安装。

                            docker pull jrottenberg/ffmpeg
                            Using default tag: latest
                            latest: Pulling from jrottenberg/ffmpeg
                            docker.io/jrottenberg/ffmpeg:latest
                            复制

                                   接着到网上下一个mp4格式的素材到本地。至此,我们的准备工作准备完毕。

                                      然后开始配置我们的rtmp服务器,配置文件如下:



                              #user nobody;
                              worker_processes 1;


                              #error_log logs/error.log;
                              #error_log logs/error.log notice;
                              #error_log logs/error.log info;


                              #pid logs/nginx.pid;




                              events {
                              worker_connections 1024;
                              }




                              rtmp {
                              server {
                              listen 1985; #not default port 1935
                              application myapp {
                              live on;
                              #为 rtmp 引擎设置最大连接数。默认为 off
                              max_connections 1024;
                              # 不开启录制
                              record off;
                              }


                              application hls{
                              live on;
                              hls on;
                              hls_path ./hls;
                              hls_fragment 1s;
                              }
                              }
                              }


                              http {
                              include mime.types;
                              default_type application/octet-stream;


                              #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                              # '$status $body_bytes_sent "$http_referer" '
                              # '"$http_user_agent" "$http_x_forwarded_for"';


                              #access_log logs/access.log main;


                              sendfile on;
                              #tcp_nopush on;


                              #keepalive_timeout 0;
                              keepalive_timeout 65;


                              #gzip on;


                              server {
                              listen 8080;
                              server_name localhost;


                              #charset koi8-r;


                              #access_log logs/host.access.log main;


                              location / {
                              root html;
                              index index.html index.htm;
                              }


                              #error_page 404 404.html;


                              # redirect server error pages to the static page 50x.html
                              #
                              error_page 500 502 503 504 50x.html;
                              location = /50x.html {
                              root html;
                              }


                              # proxy the PHP scripts to Apache listening on 127.0.0.1:80
                              #
                              #location ~ \.php$ {
                              # proxy_pass http://127.0.0.1;
                              #}


                              # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
                              #
                              #location ~ \.php$ {
                              # root html;
                              # fastcgi_pass 127.0.0.1:9000;
                              # fastcgi_index index.php;
                              # fastcgi_param SCRIPT_FILENAME scripts$fastcgi_script_name;
                              # include fastcgi_params;
                              #}


                              # deny access to .htaccess files, if Apache's document root
                              # concurs with nginx's one
                              #
                              #location ~ \.ht {
                              # deny all;
                              #}
                              location /live {
                              flv_live on;
                              }


                              location /hls {
                              #server hls fragments
                              types{
                              application/vnd.apple.mpegurl m3u8;
                              video/mp2t ts;
                              }
                              alias ./hls;
                              expires -1;
                              #跨域一定要放开
                              add_header Access-Control-Allow-Origin *;
                              add_header Access-Control-Allow-Headers X-Requested-With;
                              add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
                              }


                              # rtmp stat
                              location /stat {
                              rtmp_stat all;
                              #rtmp_stat_format json;
                              rtmp_stat_stylesheet stat.xsl;
                              }
                              location /stat.xsl {
                              root ./html/rtmp;
                              }


                              # rtmp control
                              location /control {
                              rtmp_control all;
                              add_header Access-Control-Allow-Origin *;
                              }
                              }


                              # another virtual host using mix of IP-, name-, and port-based configuration
                              #
                              #server {
                              # listen 8000;
                              # listen somename:8080;
                              # server_name somename alias another.alias;


                              # location {
                              # root html;
                              # index index.html index.htm;
                              # }
                              #}




                              # HTTPS server
                              #
                              #server {
                              # listen 443 ssl;
                              # server_name localhost;


                              # ssl_certificate cert.pem;
                              # ssl_certificate_key cert.key;


                              # ssl_session_cache shared:SSL:1m;
                              # ssl_session_timeout 5m;


                              # ssl_ciphers HIGH:!aNULL:!MD5;
                              # ssl_prefer_server_ciphers on;


                              # location / {
                              # root html;
                              # index index.html index.htm;
                              # }
                              #}


                              }


                              复制

                                      rtmp的配置和http的配置类似,包括rtmp、server、application三层。配置完毕后我们启动openresty

                                ps aux |grep -E "openresty|nginx" |grep -v grep |awk '{print $2}' |xargs sudo kill -9 && /usr/local/openresty/bin/openresty -p $PWD/ -c conf/nginx.conf 
                                复制

                                        接着我们启动ffmpeg进行推流

                                  docker run -v $(pwd):$(pwd) jrottenberg/ffmpeg:latest -re -i $(pwd)/demo.mp4 -vcodec copy -f flv rtmp://host.docker.internal:1985/hls/stream
                                  复制

                                  推流成功后展示如下:

                                    [flv @ 0xae7e00] Failed to update header with correct filesize.
                                    frame= 929 fps= 30 q=-1.0 Lsize= 7624kB time=00:00:30.93 bitrate=2018.7kbits/s speed= 1x
                                    video:7101kB audio:484kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.511305%
                                    复制

                                    推流过程中如果遇到下面错误

                                          Metadata:
                                      handler_name : Core Media Audio
                                      rtmp://host.docker.internal:1985/zbcs/room: Input/output error
                                      复制

                                      原因是推流路径不对,application hls 前缀匹配后,还需要加一层目录,对应着我们的推流密钥。也就是说下面的推流是不对的:

                                        docker run -v $(pwd):$(pwd) jrottenberg/ffmpeg:latest -re -i $(pwd)/demo.mp4 -vcodec copy -f flv rtmp://host.docker.internal:1985/hls
                                        复制

                                        推流成功后我们可以下载工具vlc来进行拉流,在vlc输入

                                          rtmp://localhost:1985/hls/stream
                                          复制

                                          就可以看到视频播放效果,为了防止推流早早结束了,影响我们测试,可以配置循环推流:

                                            docker run -v $(pwd):$(pwd) jrottenberg/ffmpeg:latest -stream_loop -1 -re -i $(pwd)/demo.mp4 -vcodec copy -f flv rtmp://host.docker.internal:1985/hls/stream
                                            复制

                                                       回过头来看下我们的hls目录,可以看到下面的文件列表:

                                              % ls ./hls 
                                              stream-20.ts stream-23.ts stream-26.ts stream-29.ts
                                              stream-18.ts stream-21.ts stream-24.ts stream-27.ts stream.m3u8
                                              stream-19.ts stream-22.ts stream-25.ts stream-28.ts


                                              复制

                                              一个stream.m3u8 和一批ts文件。转流成功后在我们之前配置的nginx rtmp模块的接收路径下(/hls)会生成m3u8索引文件,m3u8其实就是ts文件的索引,ffmpeg会把一个直播源的数据分割成很多个ts文件,访问m3u8可以获取ts文件的播放顺序,逐个播放,ts文件达到一定数量会自动删除前面无用的ts,并且如果ffmpeg停止转流,文件夹底下的文件也会自动清除。

                                                      至此我们完成了点播的推流和播放器拉流。如何进行直播的推流呢?其实很简单,我们把ffmpeg换成推流工具obs即可,和我们日常直播推流一样。obs设置推流服务器地址为

                                                rtmp://localhost:1985/hls/stream
                                                复制

                                                需要注意的是,服务器地址是

                                                   rtmp://127.0.0.1:1985/hls/
                                                  复制

                                                  密钥是

                                                    stream
                                                    复制

                                                    否则会出现推流失败。至此,简单的点播和直播服务器搭建流程介绍完毕。后面详细介绍如何实现网页版的播放端推流、看端拉流、以及播放控制,敬请期待。


                                                    文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                    评论