ДИСКЛЕЙМЕР:
Я не программист, а лишь энтузиаст-копипастер, который делится тем, в чем смог разобраться. Поэтому, не исключено, что знающие специалисты некоторые моменты или формулировки могут счесть неправильными или нелепыми.
Подача данного материала предполагает, что вы обладаете некоторым уровнем знаний 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
.