Переключение плейлиста на rtmp-стрим в Liquidsoap – Mikulski
Наложение сайта

Переключение плейлиста на rtmp-стрим в Liquidsoap

ДИСКЛЕЙМЕР:
Я не программист, а лишь энтузиаст-копипастер, который делится тем, в чем смог разобраться. Поэтому, не исключено, что знающие специалисты некоторые моменты или формулировки могут счесть неправильными или нелепыми.
Подача данного материала предполагает, что вы обладаете некоторым уровнем знаний Liquidsoap и nginx-rtmp модуля.
Как бы то ни было, следующие статьи и туториалы помогут вам разобраться:
Создание 24/7 радио-стрима (Liquidsoap)
Создание 24/7 радио-стрима ч.2 (Liquidsoap)
Свой Рестрим-Сервер (nginx-rtmp)
Синтаксис и методы описанные в этой статье, технически должны работать в Liquidsoap версиях 2.1.x - 2.2.x
Моя версия на момент публикации - 2.2.3.

Вступление и предварительная настройка

Что ж, в посте Создание 24/7 радио-стрима ч.2 (Liquidsoap) я описал возможность прямых включений аудиопотоков на стрим через оператор input.harbor. Однако, в Liquidsoap также предусмотрен механизм для подключения rtmp-источников, например, стрима из OBS.
В данном материале я покажу несколько примеров настройки таких подключений: используя встроенные возможности Liquidsoap и через включение потока с nginx-rtmp.
По умолчанию, rtmp-подключения используют порт 1935. Поэтому, во избежание возможных конфликтов (например, все с тем же nginx-rtmp, который его займет), я рекомендую настроить в firewall дополнительный порт, например, 1969, который будет использоваться в Liquidsoap.

input.rtmp

Для наглядности возьмем фрагмент скрипта, на основе предыдущих статей: где у нас есть плейлист с аудиофайлами и зацикленная анимация в качестве фона, сгруппированные в единый источник radio:

audio = playlist(reload_mode="watch", "/home/user/radio/music")
audio = mksafe(audio)
background = single("/home/user/radio/background.gif")
radio = source.mux_video(video=background, audio)
#radio = mux_video(video=background, audio) для версий 2.1.x

Теперь добавим сюда источник live для подключений по rtmp-протоколу:

audio = playlist(reload_mode="watch", "/home/user/radio/music")
audio = mksafe(audio)
background = single("/home/user/radio/background.gif")
radio = source.mux_video(video=background, audio)
#radio = mux_video(video=background, audio) для версий 2.1.x

live = input.rtmp(listen=true, "rtmp://localhost:1969/live/key")

Объясню, что здесь происходит:
Параметр listen=true означает, что Liquidsoap выступает в качестве самостоятельного rtmp-сервера и “прослушивает” указанный дальше rtmp-адрес, чтобы забрать оттуда стрим, когда тот подключится.
В адресе значения live и key можно подставлять любые вами придуманные. Этот адрес вы затем укажите в OBS, чтобы отправить туда стрим, где localhost:1969 – это IP-вашего VPS и порт, а key – это ключ потока.

Далее объединяем radio и live в единый источник stream с переключателем, чтобы плейлист автоматически переключался с плейлиста на лайвстрим:

audio = playlist(reload_mode="watch", "/home/user/radio/music")
audio = mksafe(audio)
background = single("/home/user/radio/background.gif")
radio = source.mux_video(video=background, audio)
#radio = mux_video(video=background, audio) для версий 2.1.x

live = input.rtmp(listen=true, "rtmp://localhost:1969/live/key")
stream = fallback(track_sensitive=false, [live, radio])

Параметр track_sensitive=false, означает, что плейлист сразу переключится на rtmp-источник, не дожидаясь окончания доигрывания трека.
Установите track_sensitive=true, чтобы источники переключались только тогда, когда текущий трек закончится. Но имейте ввиду, что это может создать дополнительную нагрузку на ЦПУ и соответственно вызвать нежелательные лаги.

Если вы создавали свой скрипт на основе моих предыдущих гайдов, то обратите внимание, что теперь в output.url() вместо radio надо будет указать stream:

audio = playlist(reload_mode="watch", "/home/user/radio/music")
audio = mksafe(audio)
background = single("/home/user/radio/background.gif")
radio = source.mux_video(video=background, audio)
#radio = mux_video(video=background, audio) для версий 2.1.x

live = input.rtmp(listen=true, "rtmp://localhost:1969/live/key")
stream = fallback(track_sensitive=false, [live, radio])

#rtmp+codec
url = "rtmp://localhost/live"
enc = %ffmpeg(format="flv",
%video(codec="libx264", width=1280, height=720, pixel_format="yuv420p",
b="750k", maxrate="750k", minrate="750k", bufsize="1500k", profile="Main", preset="veryfast", framerate=30, g=60),
%audio(codec="aac", samplerate=44100, b="128k"))

#output
output.url(fallible=true, url=url, enc, stream)

nginx-rtmp

Если вы используете nginx-rtmp и хотите забирать поток оттуда, то есть несколько нюансов
[ну и предположим, что вы оставили в настройках nginx порт rtmp по умолчанию – 1935]:
Параметр listen, нужно перевести в значение false

live = input.rtmp(listen=false, "rtmp://localhost:1935/live/key")

А в конфиге nginx-rtmp для “прослушиваемого” app важно добавить строчку play_restart on; чтобы nginx-rtmp отправлял дополнительные сигналы о начале/конца стрима.
В противном случае, по завершению прямого эфира, Liquidsoap просто зависнет, ожидая данные из nginx.

application live {
            live on;
            record off;
            play_restart on;
            }

Вызов функций

Если вы более продвинутый пользователь Liquidsoap, то, вероятно, вы захотите вызывать какие-либо функции на коннект/дисконнект стрима.
В операторе input.rtmp не предусмотрено аргументов для подобных целей. Однако, если поковыряться в библиотеках исходного кода, то можно понять, что input.rtmp – это сокращенная, для удобства, версия оператора input.ffmpeg, где более богатый ассортимент всевозможных параметров.
На примере небольшого фрагмента с простейшими функциями, выглядеть это будет примерно так:

def live_start()
log("LiveStream is Started!")
end

def live_stop()
log("LiveStream is Stopped!")
end

listen = true 
live = input.ffmpeg(on_connect=live_start, on_disconnect=live_stop, max_buffer=5., format="live_flv", self_sync=true, int_args=[("listen", listen ? 1 : 0)],  "rtmp://localhost:1969/live/key")

on_connect и on_disconnect – это вызов нужных функций.
listen теперь вынесен в отдельную переменную.
Все прочие параметры (format, self_sync, max_buffer) взяты из конструктора input.rtmp.

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии