工作中发现挺多直播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.gitnginx配置安装
./configure --add-module=/home/wanghao/worker/opensourcecode/nginx_module/nginx-http-flv-module make -j 4 && make install cd /usr/local/nginx/对于不知道文件长度的情况下(例如直播),nginx默认使用chunked_transfer_encoding来传输。 所以,配置文件中不用显示的去设置
Syntax: chunked_transfer_encoding on | off; Default:chunked_transfer_encoding on; Context: http, server, location官方连接请点击
q00307z84wz.321002.1.ts是一个5分钟的文件,则ffmpeg大概在5分钟后退出。
real 5m0.382s user 0m22.750s sys 0m8.141s填写正确的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 endno size 就是没有content-length no chunk 就是没有 Transfer-Encoding: chunked Assume close to signal end 可以理解为直播服务器主动关闭socket就代表直播流结束了 但是HTTP协议标准是content-length和Transfer-Encodinge二选一,所以no-centent-length的方案是非标准的。
通过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
