nginx搭建直播rtmp推流,httpflv拉流环境

    技术2026-02-02  7

    背景

    工作中发现挺多直播CDN在实现httpflv拉流时都没有使用http chunk编码,而是直接使用no-content-length的做法。所以想自己搭建一个直播CDN支持 http chunk编码。

    环境搭建

    系统环境 Ubuntu 18.04.4 LTS 软件 nginx-1.18.0 nginx扩展模块 nginx-http-flv-module

    nginx-http-flv-modulex下载

    git clone https://github.com/winshining/nginx-http-flv-module.git

    nginx配置安装

    ./configure --add-module=/home/wanghao/worker/opensourcecode/nginx_module/nginx-http-flv-module make -j 4 && make install cd /usr/local/nginx/

    nginx.conf配置文件

    #user nobody; worker_processes 1; events { worker_connections 1024; } http { // http拉流的配置 include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name www.wawa.com; location /live { flv_live on; } } } rtmp { // rtmp推流的配置 server { listen 1935; application myapp{ live on; record off; } } }

    对于不知道文件长度的情况下(例如直播),nginx默认使用chunked_transfer_encoding来传输。 所以,配置文件中不用显示的去设置

    Syntax: chunked_transfer_encoding on | off; Default:chunked_transfer_encoding on; Context: http, server, location

    官方连接请点击

    ffmepg推送本地文件到直播服务器

    ffmpeg -re -i q00307z84wz.321002.1.ts -f flv rtmp://192.168.116.130:1935/myapp/123

    q00307z84wz.321002.1.ts是一个5分钟的文件,则ffmpeg大概在5分钟后退出。

    real 5m0.382s user 0m22.750s sys 0m8.141s

    httpflv拉流

    填写正确的IP地址端口和流ID后进行拉流

    # curl -L -v "http://192.168.116.130/live?port=1935&app=myapp&stream=123" -o 1.flv * Trying 192.168.116.130... * TCP_NODELAY set % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 192.168.116.130 (192.168.116.130) port 80 (#0) > GET /live?port=1935&app=myapp&stream=123 HTTP/1.1 > Host: 192.168.116.130 > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.18.0 < Date: Fri, 03 Jul 2020 13:49:52 GMT < Content-Type: video/x-flv < Transfer-Encoding: chunked < Connection: keep-alive < Expires: -1 < { [449 bytes data] 100 1068k 0 1068k 0 0 97k 0 --:--:-- 0:00:10 --:--:-- 117k

    可以在响应头中看到使用了http chunk协议,且没有content-length

    < Transfer-Encoding: chunked

    继续修改nginx.conf,关闭http chunk编码

    location /live { flv_live on; chunked_transfer_encoding off; }

    使用curl拉流测试

    # curl -L -v "http://192.168.116.130/live?port=1935&app=myapp&stream=123" -o 1.flv * Trying 192.168.116.130... * TCP_NODELAY set % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 192.168.116.130 (192.168.116.130) port 80 (#0) > GET /live?port=1935&app=myapp&stream=123 HTTP/1.1 > Host: 192.168.116.130 > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.18.0 < Date: Fri, 03 Jul 2020 13:59:43 GMT < Content-Type: video/x-flv < Connection: keep-alive < Expires: -1 * no chunk, no close, no size. Assume close to signal end < { [1504 bytes data] 100 668k 0 668k 0 0 98k 0 --:--:-- 0:00:06 --:--:-- 112k

    可以看到已经没有 "Transfer-Encoding: chunked" 的响应头部了,仔细观察,输出了一行英文

    * no chunk, no close, no size. Assume close to signal end

    no size 就是没有content-length no chunk 就是没有 Transfer-Encoding: chunked Assume close to signal end 可以理解为直播服务器主动关闭socket就代表直播流结束了 但是HTTP协议标准是content-length和Transfer-Encodinge二选一,所以no-centent-length的方案是非标准的。

    测试其他直播APP

    通过adb logcat抓取快手,斗鱼,虎牙等头部直播APP的日志后,找到拉流地址,自己本地用curl拉流也是发现有挺多流都是 no-content-length,Google下得知,使用这种非标准的no-centengt-length的原因是实现简单。

    未完成事项

    在拉流http chunk流的时候,使用tcpdump抓包,wireshark分析后,均没有看到http chunk协议,与网上其他教程不符合。还需要再探索下。

    tcpdump -i lo host 192.168.116.130 -nnvv -w live2.pcap

    因为拉流端和nginx服务器同一台机器,则从本地环回口拉取(lo)抓包,192.168.116.130是本地的内网IP。

    作者:feelc 链接:https://juejin.im/post/5eff33f3f265da22ee7fa1d2

    Processed: 0.020, SQL: 9