Страницы

Поиск по вопросам

Показаны сообщения с ярлыком rtmp. Показать все сообщения
Показаны сообщения с ярлыком rtmp. Показать все сообщения

воскресенье, 26 января 2020 г.

Как распределить нагрузку между серверами с nginx-rtmp-module?

#nginx #rtmp


Подскажите как правильно распределять зрителей между серверами с nginx-rtmp-module?
К примеру есть 3 сервера на каждом установлен nginx-rtmp-module, rtmp поток создается
на первом сервере, как отправить зрителей на 2 сервер если их больше чем может держать
первый и так же со второго на третий.
    


Ответы

Ответ 1



RTMP протокол поддерживает редирект. Т.е. при подключении к серверу, если он не сможет обслужить клиента, он может его перенаправить дальше. Плюс балансировщик на входе. Схематически это должно выглядеть так: в настройках application (терминология RTMP) добавляется http-колбек (терминология nginx-rtmp) on_connect. в обработчике этих сообщений нужно принять решение о редиректе и ответить согласно документации: If HTTP 2xx code is returned then RTMP session continues. The code of 3xx makes RTMP redirect to another application whose name is taken from Location HTTP response header. Otherwise connection is dropped. Ещё интересные колбеки: on_publish - вызывается при начале публикации стрима на сервер on_play - вызывается при начале проигрывания стрима с сервера. Он позволяет делать редирект только внутри тещкущего сервера или создавать remove-proxy к другому серверу, оставаясь сам на обслуживании данного клиента. Т.е. копать детально нужно в сторону on_connect. Как реализовать планирование... Тут вопрос сложный. Как минимум планировщик должен знать о нагрузке всех серверов и динамически принимать решение о перенаправлении. Можно, к примеру, мониторить нагрузку каждого сервера: CPU Память Число подключений Утилизация канала строить рейтинг. Если для текущего сервера какой-то параметр вышел за пределы нормы, то брать сервер с максимальным рейтингом и отправлять подключение туда. В качестве дополнительной, но более сложной меры, можно, со временем научить создавать дополнительные инстансы серверов, причём с учётом скорости роста (например при лавинном подключении при трансляции какого-то эвента) и гасить их по мере спада нагрузки. Ещё нюансом может стать то, что документация на on_connect не говорит явно, что будет, если в Location вернуть полный путь с rtmp://.... Нужно изучать исходники или спрашивать в рассылке или у автора в почте. Если такой редирект не поддерживается, то можно попытаться решить вопрос при помощи балансировщиков типа Balance NG или HAProxy. Подобный пример даже рассмотрет в официальном блоге: http://blog.haproxy.com/2012/09/21/high-available-rtmp-platform-with-haproxy-and-crtmpserver/. Единственно, нужно как-то привязать ваш супер-визор. Если мне не изменяет память, то HAProxy можно попросить использовать какой-то скрипт для принятия решения. Кстати, при живом стриминге, вам нужно будет обеспечить, что бы на тот сервер, на который вы перенаправляете клиента, этот поток тоже присутствовал, т.е. реализовывать релей: публицирует-то один человек и на один сервер.

Ответ 2



Модуль ngx_http_upstream_module позволяет описывать группы серверов, которые могут использоваться в директивах proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass

четверг, 23 января 2020 г.

Как организовать рестрим rtmp?

#php #python #потоки_данных #streaming #rtmp


У меня есть rtmp поток и rtmp сервер, на который нужно отправить этот поток с определенным
именем. Как лучше всего это можно организовать?(желательно на php или python, хотя
можно и со сторонними утилитами)
    


Ответы

Ответ 1



Cо сторонними утилитами Подобного проще всего достичь с помощью FFMpeg: /usr/bin/ffmpeg -re \ -i 'rtmp://src_stream:1935/play' \ -vcodec copy -acodec copy \ -f flv 'rtmp://dst_stream:1935/publish'; Например, эту командочку, можно было бы вызвать из любого удобного вам окружения. Более подробно про команды рассказано тут: FFmpeg Streaming Guide; FFmpeg for streaming; Онлайн вещание через Nginx-RTMP — несколько готовых рецептов; Про аргументы командной строки FFMpeg. Можно пойти немного дальше, и использовать nginx c nginx-rtmp-module. Streaming with nginx-rtmp-module Getting started with nginx RTMP Attempting to Stream a Webcam to an RTMP Server nginx-rtmp-module wiki: exec_push При этом nginx.conf всего скорее будет иметь вид: #user nobody; worker_processes 1; error_log logs/error.log debug; events { worker_connections 1024; } rtmp { server { listen 1935; ping 30s; notify_method get; application src { live on; exec_push ffmpeg -i 'rtmp://src_stream:1935/play' -vcodec copy -acodec copy -f flv 'rtmp://dst_stream:1935/publish' 2>> '/var/log/ffmpeg-$name.log'; } } } Hа python Решение на Python легко организовать через PyAV. Это питонячие биндинги к libav. О том что это такое и как это использовать можно почитать тут: Про обработку видео в Python. Про работу с RTMP в PyAV есть комментарий автора проекта: Can I use PyAV to built a RTMP retransmit-server?. Пример https://gist.github.com/w495/c4aa54e4783c2d3766407a5f4f7bc81d import av # Откроем ресурс на чтение input_resource = av.open( 'rtmp://src_stream:1935/play' ) # Откроем ресурс на запись. output_resource = av.open( 'rtmp://dst_stream:1935/publish', mode='w', format='flv' ) # Список потоков входного ресурса: видео и аудио input_streams = list() # Список потоков выходного ресурса: видео и аудио output_streams = list() # Для входного и выходного ресурсов возьмём поток видео. for stream in input_resource.streams: if stream.type == 'video': input_streams += [stream] # Создадим видео-поток для выходного ресурса. Кодек `h264`. output_streams += [output_resource.add_stream('h264')] break # Для входного и выходного ресурсов возьмём поток аудио. for stream in input_resource.streams: if stream.type == 'audio': input_streams += [stream] # Создадим аудио-поток для выходного ресурса. Кодек `aac`. output_streams += [output_resource.add_stream('aac')] break # В этом списке будем хранить пакеты выходного потока. output_packets = list() # Применим «инверсное мультиплексирование». Получим пакеты из потока. for packet in input_resource.demux(input_streams): # Получим все кадры пакета. for frame in packet.decode(): # Сбросим PTS для самостоятельного вычислении при кодировании. frame.pts = None # Закодируем соответствующие кадры для выходных потоков. for stream in output_streams: if packet.stream.type == stream.type: output_packets += [stream.encode(frame)] # Сбросим буфферы кодировщика. ??? Нужно ли ??? for stream in output_streams: output_packets += [stream.encode(None)] # Для каждого пакета применим «прямое мультиплексирование». for packet in output_packets: if packet: output_resource.mux(packet) output_resource.close() Это немного искусственный пример, и нужно помнить про некоторые особенности потокового видео. В частности, — оно потенциально бесконечно, и это означает, что вы не сможете использовать списки пакетов и кадров (list). В вашей задаче, всего скорее, будут нужны генераторы последовательностей и итераторы: Python Practice Book: Iterators & Generators; Python wiki: Iterator; Python wiki: Generators.

вторник, 19 марта 2019 г.

Как организовать рестрим rtmp?

У меня есть rtmp поток и rtmp сервер, на который нужно отправить этот поток с определенным именем. Как лучше всего это можно организовать?(желательно на php или python, хотя можно и со сторонними утилитами)


Ответ

Cо сторонними утилитами
Подобного проще всего достичь с помощью FFMpeg:
/usr/bin/ffmpeg -re \ -i 'rtmp://src_stream:1935/play' \ -vcodec copy -acodec copy \ -f flv 'rtmp://dst_stream:1935/publish';
Например, эту командочку, можно было бы вызвать из любого удобного вам окружения.
Более подробно про команды рассказано тут:
FFmpeg Streaming Guide FFmpeg for streaming Онлайн вещание через Nginx-RTMP — несколько готовых рецептов Про аргументы командной строки FFMpeg
Можно пойти немного дальше, и использовать nginx c nginx-rtmp-module
Streaming with nginx-rtmp-module Getting started with nginx RTMP Attempting to Stream a Webcam to an RTMP Server nginx-rtmp-module wiki: exec_push
При этом nginx.conf всего скорее будет иметь вид:
#user nobody; worker_processes 1;
error_log logs/error.log debug;
events { worker_connections 1024; }
rtmp { server { listen 1935; ping 30s; notify_method get;
application src { live on; exec_push ffmpeg -i 'rtmp://src_stream:1935/play' -vcodec copy -acodec copy -f flv 'rtmp://dst_stream:1935/publish' 2>> '/var/log/ffmpeg-$name.log'; } } }
Hа python
Решение на Python легко организовать через PyAV. Это питонячие биндинги к libav
О том что это такое и как это использовать можно почитать тут:
Про обработку видео в Python
Про работу с RTMP в PyAV есть комментарий автора проекта:
Can I use PyAV to built a RTMP retransmit-server?
Пример
https://gist.github.com/w495/c4aa54e4783c2d3766407a5f4f7bc81d
import av
# Откроем ресурс на чтение input_resource = av.open( 'rtmp://src_stream:1935/play' ) # Откроем ресурс на запись. output_resource = av.open( 'rtmp://dst_stream:1935/publish', mode='w', format='flv' ) # Список потоков входного ресурса: видео и аудио input_streams = list() # Список потоков выходного ресурса: видео и аудио output_streams = list() # Для входного и выходного ресурсов возьмём поток видео. for stream in input_resource.streams: if stream.type == 'video': input_streams += [stream] # Создадим видео-поток для выходного ресурса. Кодек `h264`. output_streams += [output_resource.add_stream('h264')] break # Для входного и выходного ресурсов возьмём поток аудио. for stream in input_resource.streams: if stream.type == 'audio': input_streams += [stream] # Создадим аудио-поток для выходного ресурса. Кодек `aac`. output_streams += [output_resource.add_stream('aac')] break # В этом списке будем хранить пакеты выходного потока. output_packets = list() # Применим «инверсное мультиплексирование». Получим пакеты из потока. for packet in input_resource.demux(input_streams): # Получим все кадры пакета. for frame in packet.decode(): # Сбросим PTS для самостоятельного вычислении при кодировании. frame.pts = None # Закодируем соответствующие кадры для выходных потоков. for stream in output_streams: if packet.stream.type == stream.type: output_packets += [stream.encode(frame)] # Сбросим буфферы кодировщика. ??? Нужно ли ??? for stream in output_streams: output_packets += [stream.encode(None)] # Для каждого пакета применим «прямое мультиплексирование». for packet in output_packets: if packet: output_resource.mux(packet) output_resource.close()
Это немного искусственный пример, и нужно помнить про некоторые особенности потокового видео. В частности, — оно потенциально бесконечно, и это означает, что вы не сможете использовать списки пакетов и кадров (list). В вашей задаче, всего скорее, будут нужны генераторы последовательностей и итераторы:
Python Practice Book: Iterators & Generators Python wiki: Iterator Python wiki: Generators