工做中發現挺多直播CDN在實現httpflv拉流時都沒有使用http chunk編碼,而是直接使用no-content-length的作法。因此想本身搭建一個直播CDN支持 http chunk編碼。html
系統環境 Ubuntu 18.04.4 LTS
軟件 nginx-1.18.0
nginx擴展模塊 nginx-http-flv-modulenginx
nginx-http-flv-modulex下載git
git clone https://github.com/winshining/nginx-http-flv-module.git
複製代碼
nginx配置安裝github
./configure --add-module=/home/wanghao/worker/opensourcecode/nginx_module/nginx-http-flv-module
make -j 4 && make install
cd /usr/local/nginx/
複製代碼
#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來傳輸。 因此,配置文件中不用顯示的去設置shell
Syntax: chunked_transfer_encoding on | off;
Default:chunked_transfer_encoding on;
Context: http, server, location
複製代碼
官方鏈接請點擊bash
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
複製代碼
填寫正確的IP地址端口和流ID後進行拉流app
# 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-lengthcurl
< Transfer-Encoding: chunked
複製代碼
繼續修改nginx.conf,關閉http chunk編碼socket
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的方案是非標準的。
經過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。