跳转至

flv: 基于 nginx-module-rtmp 的媒体流服务器

安装

您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9 和 10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-flv
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-flv

通过在 /etc/nginx/nginx.conf 的顶部添加以下内容来启用该模块:

load_module modules/ngx_http_flv_live_module.so;

本文档描述了 nginx-module-flv v1.2.12,于 2024 年 12 月 31 日发布。


nginx-http-flv-module workflow

基于 nginx-rtmp-module 的媒体流服务器。

中文说明

如果您喜欢这个模块,请捐赠。非常感谢您!

PayPal

功能

功能 nginx-http-flv-module nginx-rtmp-module 备注
HTTP-FLV(用于播放) x 支持 HTTPS-FLV 和分块响应
GOP 缓存 x
虚拟主机 x
省略 listen 指令 见备注 必须至少有一个 listen 指令
RTMP/HTTP-FLV 的音频支持 见备注 如果 wait_videowait_key 开启则无法工作
HLS 的单轨道支持 x
reuseport 支持 x
访问日志的计时器 x
JSON 风格统计 x
录制统计 x
与字节序无关 见备注 big-endian 分支中部分支持

支持的系统

  • Linux(推荐)/ FreeBSD / MacOS / Windows(有限)。

支持的播放器

注意

先决条件

  • GNU make,用于在类 Unix 系统上激活编译器以编译软件。

  • GCC 用于类 Unix 系统上的编译,或 MSVC 用于 Windows 上的编译。

  • GDB 用于在类 Unix 系统上的调试。

  • FFmpegOBS 用于发布媒体流。

  • VLC(推荐)或 flv.js(推荐)用于播放媒体流。

  • PCRE 用于 NGINX,如果需要正则表达式。

  • OpenSSL 用于 NGINX,如果需要加密访问。

  • zlib 用于 NGINX,如果需要压缩。

用法

有关 nginx-rtmp-module 的用法详细信息,请参阅 README.md

发布

为简单起见,不使用转码(因此使用 -c copy):

ffmpeg -re -i MEDIA_FILE_NAME -c copy -f flv rtmp://example.com[:port]/appname/streamname

注意

某些旧版本的 FFmpeg 不支持选项 -c copy,可以使用选项 -vcodec copy -acodec copy 代替。

appname 用于匹配 rtmp 块中的应用程序块(详见下文)。

streamname 可以随意指定,但 不能 省略。

RTMP 的默认端口1935,如果使用其他端口,必须指定 :port

播放

通过 HTTP-FLV

http://example.com[:port]/dir?[port=xxx&]app=appname&stream=streamname

注意

  • 如果在命令行中使用 ffplay 播放流,则上述 URL 必须 用引号括起来,否则 URL 中的参数将被丢弃(某些 shell 不够智能,会将 "&" 解释为“在后台运行”)。

  • 如果使用 flv.js 播放流,请确保发布的流已正确编码,因为 flv.js 仅支持 H.264 编码的视频和 AAC/MP3 编码的音频

dir 用于匹配 http 块中的位置块(详见下文)。

HTTP 的默认端口80,如果使用其他端口,必须指定 :port

RTMP 的默认端口1935,如果使用其他端口,必须指定 port=xxx

app(appname)的值用于匹配应用程序块,但如果请求的 app 出现在多个服务器块中,并且这些块具有相同的地址和端口配置,则将额外使用与 server_name 指令匹配的主机名来识别请求的应用程序块,否则匹配第一个。

stream(streamname)的值用于匹配发布流的名称。

示例

假设在 http 块中指定的 listen 指令为:

http {
    ...
    server {
        listen 8080; #不是默认端口 80
        ...

        location /live {
            flv_live on;
        }
    }
}

而在 rtmp 块中指定的 listen 指令为:

rtmp {
    ...
    server {
        listen 1985; #不是默认端口 1935
        ...

        application myapp {
            live on;
        }
    }
}

发布的流名称为 mystream,则基于 HTTP 的播放 URL 为:

http://example.com:8080/live?port=1985&app=myapp&stream=mystream

注意

由于某些播放器不支持 HTTP 分块传输,因此最好在指定 flv_live on; 的位置中指定 chunked_transfer_encoding off;,否则播放将失败。

通过 RTMP

rtmp://example.com[:port]/appname/streamname

通过 HLS

http://example.com[:port]/dir/streamname.m3u8

通过 DASH

http://example.com[:port]/dir/streamname.mpd

示例图片

RTMP (JW Player) & HTTP-FLV (VLC)

RTMP & HTTP-FLV

HTTP-FLV (flv.js)

HTTP-FLV

示例 nginx.conf

注意

指令 rtmp_auto_pushrtmp_auto_push_reconnectrtmp_socket_dir 在 Windows 上无法正常工作,除非在 Windows 10 17063 及更高版本上,因为在多进程模式下的 relay 需要 Unix 域套接字的帮助,详情请参阅 Windows 10 上的 Unix 域套接字

最好将指令 worker_processes 指定为 1,因为在多进程模式下,ngx_rtmp_stat_module 可能无法从指定的工作进程获取统计信息,因为 HTTP 请求会随机分配给工作进程。ngx_rtmp_control_module 也存在同样的问题。可以通过此补丁 per-worker-listener 优化该问题。

此外,vhost 功能在单进程模式下可以正常工作,但在多进程模式下尚不完美,等待修复。例如,以下配置在多进程模式下是可以的:

rtmp {
    ...
    server {
        listen 1935;
        server_name domain_name;

        application myapp {
            ...
        }
    }
}

而以下配置在指向非发布工作进程的第二个 server 的播放请求中无法正常工作(无论端口是否为 1935):

rtmp {
    ...
    server {
        listen 1935;
        server_name 1st_domain_name;

        application myapp {
            ...
        }
    }

    server {
        listen 1945;
        server_name 2nd_domain_name;

        application myapp {
            ...
        }
    }
}

如果 NGINX 在多进程模式下运行,并且平台支持套接字选项 SO_REUSEPORT,则为 listen 指令添加选项 reuseport 将解决“惊群效应”问题。

rtmp {
    ...

    server {
        listen 1935 reuseport;
        ...
    }
}

示例配置

worker_processes  1; #在 Windows 上应为 1,因为它不支持 Unix 域套接字
#worker_processes  auto; #从版本 1.3.8 和 1.2.5 开始

#worker_cpu_affinity  0001 0010 0100 1000; #仅在 FreeBSD 和 Linux 上可用
#worker_cpu_affinity  auto; #从版本 1.9.10 开始

error_log logs/error.log error;

#如果模块被编译为动态模块并且需要与 RTMP 相关的功能,
#则下面的命令必须指定,并且必须位于事件指令之前,
#否则模块将无法加载或在 NGINX 启动时加载失败

#load_module modules/ngx_http_flv_live_module.so;

events {
    worker_connections  4096;
}

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

    keepalive_timeout  65;

    server {
        listen       80;

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

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        location /live {
            flv_live on; #开启 flv 实时流(订阅)
            chunked_transfer_encoding  on; #开启 'Transfer-Encoding: chunked' 响应

            add_header 'Access-Control-Allow-Origin' '*'; #添加额外的 HTTP 头
            add_header 'Access-Control-Allow-Credentials' 'true'; #添加额外的 HTTP 头
        }

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }

            root /tmp;
            add_header 'Cache-Control' 'no-cache';
        }

        location /dash {
            root /tmp;
            add_header 'Cache-Control' 'no-cache';
        }

        location /stat {
            #流媒体和录制统计的配置

            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root /var/www/rtmp; #指定 stat.xsl 的位置
        }

        #如果需要 JSON 风格的统计,则无需指定
        #stat.xsl,而是需要一个新的指令 rtmp_stat_format

        #location /stat {
        #    rtmp_stat all;
        #    rtmp_stat_format json;
        #}

        location /control {
            rtmp_control all; #rtmp 控制模块的配置
        }
    }
}

rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /tmp;

rtmp {
    out_queue           4096;
    out_cork            8;
    max_streams         128;
    timeout             15s;
    drop_idle_publisher 15s;

    log_interval 5s; #日志模块在 access.log 中记录的间隔,非常有助于调试
    log_size     1m; #日志模块在 access.log 中记录的缓冲区大小

    server {
        listen 1935;
        server_name www.test.*; #用于虚拟主机名的后缀通配符匹配

        application myapp {
            live on;
            gop_cache on; #开启 GOP 缓存以减少视频首帧的等待时间
        }

        application hls {
            live on;
            hls on;
            hls_path /tmp/hls;
        }

        application dash {
            live on;
            dash on;
            dash_path /tmp/dash;
        }
    }

    server {
        listen 1935;
        server_name *.test.com; #用于虚拟主机名的前缀通配符匹配

        application myapp {
            live on;
            gop_cache on; #开启 GOP 缓存以减少视频首帧的等待时间
        }
    }

    server {
        listen 1935;
        server_name www.test.com; #用于完全匹配虚拟主机名

        application myapp {
            live on;
            gop_cache on; #开启 GOP 缓存以减少视频首帧的等待时间
        }
    }
}

GitHub

您可以在 nginx-module-flv 的 GitHub 仓库中找到有关此模块的其他配置提示和文档。