Nginx создает живую среду push-потока rtmp, среду pull-потока httpflv

Nginx

задний план

В ходе работы я обнаружил, что многие живые CDN не используют кодирование фрагментов http при реализации потоковой передачи httpflv, а напрямую используют длину без содержимого. Поэтому я хочу создать живую поддержку CDN самостоятельно. Кодировка фрагмента http.

Строительство окружающей среды

системная средаUbuntu 18.04.4 LTS
программное обеспечениеnginx-1.18.0
модуль расширения nginxnginx-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

Официальная ссылка, пожалуйста, нажмите

ffmpeg отправляет локальные файлы на живой сервер

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-адреса и идентификатор потока, чтобы получить поток.

# 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 и длина содержимого отсутствует.

< Transfer-Encoding: chunked

ПродолжатьИзмените nginx.conf, чтобы отключить кодирование фрагментов http.

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

Видно, что нет заголовка отклика «Переводное кодирование: CoSunded». После тщательного наблюдения выводится линия английского языка.

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

NO размер не Content-Length
отсутствие фрагмента означает отсутствие кодирования передачи: фрагментирование
Предположим, что близко к концу сигнала можно понять, что живой сервер активно закрывает сокет, что означает, что живой поток закончился.
Но стандарт протокола HTTP — это длина содержимого и кодировка передачи, поэтому схема без цента длины являетсянестандартныйиз.

ПродолжатьУглубленное обнаружение «Connection: Keep-Alive», как правило, в живой сцене Connection is Close. HTTP1.1 использует Keep-alive по умолчанию, но клиент может указать, как использовать короткие ссылки HTTP в запрошенном заголовке.

root@PF1YTXHH-ZTB:/storage/log_live# curl -L -H "Connection:Close" -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: */*
> Connection:Close     # 客户端指定使用close的方式
>
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Tue, 07 Jul 2020 13:14:43 GMT
< Content-Type: video/x-flv
< Connection: close   # 服务端也返回了close
< Expires: -1
<
{ [1637 bytes data]
100  236k    0  236k    0     0  89583      0 --:--:--  0:00:02 --:--:-- 89583^C

Протестируйте другие приложения для потокового вещания

После захвата журналов Kuaishou, Douyu, Huya и других приложений для потоковой передачи в реальном времени через adb logcat я нашел адрес потока извлечения, и я использовал curl локально для извлечения потока и обнаружил, что существует довольно много потоков.
no-content-length, Google узнал, что причиной использования этой нестандартной длины no-centengt является простота реализации.

незаконченное дело

При извлечении потока фрагментов http используйте tcpdump для захвата пакетов, и после анализа wirehark протокол фрагмента http не виден, что несовместимо с другими онлайн-учебниками. Еще нужно изучить.

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

Потому что сторона вытягивания и сервер NGINX такая же машина, из локальной обработки обратной связи (LO) Capture, 192.168.116.130 - это локальная сеть IP.