From 8a26bee3a81c61c9aebd5cc1af5c1cca484a4dd9 Mon Sep 17 00:00:00 2001 From: Tony Miller Date: Sun, 6 Feb 2022 15:28:09 -0800 Subject: [PATCH 1/2] add ffmpeg input and hls output from ffmpeg branch --- liquidsoap/Dockerfile | 7 ++-- liquidsoap/PACKAGES | 4 +-- liquidsoap/radio.liq | 74 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/liquidsoap/Dockerfile b/liquidsoap/Dockerfile index 819ba99..2734a51 100644 --- a/liquidsoap/Dockerfile +++ b/liquidsoap/Dockerfile @@ -3,7 +3,7 @@ FROM archlinux RUN yes | pacman -Sy archlinux-keyring RUN pacman-key --init RUN pacman-key --populate archlinux -RUN yes | pacman -Syu --noconfirm opam make m4 gcc patch diffutils ffmpeg git automake autoconf pkg-config which taglib sudo glibc jq libffi pcre libmad +RUN yes | pacman -Syu --noconfirm opam make m4 gcc patch diffutils gavl ffmpeg git automake autoconf pkg-config which taglib sudo glibc jq libffi pcre libmad RUN useradd liquidsoap && mkdir /home/liquidsoap && chown -R liquidsoap /home/liquidsoap RUN usermod -aG wheel liquidsoap @@ -34,7 +34,7 @@ RUN opam update # depext no longer required to install, integrated with opam # RUN opam install depext -y # RUN opam depext taglib mad lame ogg vorbis cry samplerate liquidsoap -y -RUN opam install taglib mad lame ogg vorbis cry samplerate ocurl liquidsoap -y +RUN opam install gavl ffmpeg taglib mad lame ogg vorbis cry samplerate ocurl liquidsoap -y # RUN for i in ocaml-gavl ocaml-ffmpeg ocaml-dtools ocaml-duppy ocaml-mm ocaml-cry ocaml-taglib ocaml-lame ocaml-mad ocaml-ogg ocaml-vorbis ocaml-samplerate; do \ # cd /home/liquidsoap && git clone https://github.com/savonet/$i && cd $i && opam pin add --yes --no-action .; \ @@ -51,11 +51,14 @@ RUN mkdir /home/liquidsoap/tracks RUN chown liquidsoap:liquidsoap /home/liquidsoap/tracks RUN mkdir /home/liquidsoap/recordings RUN chown liquidsoap:liquidsoap /home/liquidsoap/recordings +RUN mkdir /home/liquidsoap/hls +RUN chown liquidsoap:liquidsoap /home/liquidsoap/hls WORKDIR /home/liquidsoap/radio RUN eval $(opam env) && liquidsoap --check radio.liq RUN chown 1000:1000 /home/liquidsoap/tracks RUN chown 1000:1000 /home/liquidsoap/recordings +RUN chown 1000:1000 /home/liquidsoap/hls EXPOSE 9000 CMD ["/bin/bash", "-c", "eval `opam config env`; liquidsoap radio.liq"] diff --git a/liquidsoap/PACKAGES b/liquidsoap/PACKAGES index be4b45c..af1d642 100644 --- a/liquidsoap/PACKAGES +++ b/liquidsoap/PACKAGES @@ -117,11 +117,11 @@ ocaml-flac # is very efficient and has a quality setting for # tweaking load vs. quality of the conversion. # It is the recommended module to use with video -# ocaml-gavl +ocaml-gavl # FFMPEG is currently only used to convert from # and to many formats. -# ocaml-ffmpeg +ocaml-ffmpeg # Frei0r is a minimalistic plugin API for video sources and filters. # ocaml-frei0r diff --git a/liquidsoap/radio.liq b/liquidsoap/radio.liq index 9322d1d..2f359e6 100755 --- a/liquidsoap/radio.liq +++ b/liquidsoap/radio.liq @@ -66,6 +66,9 @@ stop_dump_f = ref (fun () -> ()) # live_dj = ref empty() live_dj = ref(source.fail()) +live_video_audio = ref(source.fail()) +live_video = ref(source.fail()) +vj_video = ref(source.fail()) # def dj_dummy_started() = # log("dj dummy on_start") @@ -237,13 +240,24 @@ end live_dj := map_metadata(new_meta, !live_dj,update=false) +live_video := input.ffmpeg(id="main_video", max_buffer=60.0, "https://viz.streampusher.com:16666/hls/datafruits.m3u8") +vj_video := input.ffmpeg(id="vj_video", max_buffer=60.0, "https://viz.streampusher.com:16666/vj/datafruits.m3u8") + +live_video_audio := audio_to_stereo(drop_video(!live_video)) # live_dj := pipe(process="./stereo_tool_cmd_64 - - -s ./stereotool.sts -k '#{stereo_tool_key}'", buffer=10.0, replay_delay=10.0, !live_dj) # output.dummy(fallible=true, on_start=dj_dummy_started, on_stop=dj_dummy_stopped, !live_dj) output.file(%mp3, "/home/liquidsoap/recordings/#{radio_name}-#{current_dump_filename}.mp3", !live_dj, fallible=true, append=true) source = fallback(id="fallback",track_sensitive=false, - [!live_dj,scheduled_shows,mksafe(backup_playlist)]) + [!live_video_audio, !live_dj,scheduled_shows,mksafe(backup_playlist)]) + +single_video = noise() + +video_source = fallback(id="video_fallback",track_sensitive=false, + [!live_video, + mux_audio(drop_audio(!vj_video), audio=source), + mksafe(mux_audio(single_video, audio=source))]) # source = if tunein_metadata_updates_enabled == "true" then on_track(tunein.submit(partnerid=tunein_partner_id,partnerkey=tunein_partner_key,stationid=tunein_station_id), source) else source end @@ -263,3 +277,61 @@ output.icecast(%mp3,id="icecast", icy_metadata="true",description="", url="", encoding="UTF-8", mksafe(buffer(source))) + +aac_lofi = %ffmpeg(format="mpegts", + %audio( + codec="aac", + channels=2, + ar=44100 + ), + %video( + codec="libx264", + b="5M" + ) + ) + +aac_midfi = %ffmpeg(format="mpegts", + %audio( + codec="aac", + channels=2, + ar=44100, + b="96k" + ), + %video( + codec="libx264", + b="5M" + ) + ) + +aac_hifi = %ffmpeg(format="mpegts", + %audio( + codec="aac", + channels=2, + ar=44100, + b="192k" + ), + %video( + codec="libx264", + b="5M" + ) + ) + +streams = [("aac_lofi",aac_lofi), + ("aac_midfi", aac_midfi), + ("aac_hifi", aac_hifi)] + +def segment_name(~position,~extname,stream_name) = + timestamp = int_of_float(time()) + duration = 2 + "#{stream_name}_#{duration}_#{timestamp}_#{position}.#{extname}" +end + +output.file.hls(playlist="#{radio_name}.m3u8", + segment_duration=2.0, + segments=5, + segments_overhead=5, + segment_name=segment_name, + persist_at="/home/liquidsoap/state.config", + "/home/liquidsoap/hls", + streams, + video_source) From 02211c8c790a312cc9885eabd31b006bd8ea3820 Mon Sep 17 00:00:00 2001 From: Tony Miller Date: Mon, 7 Feb 2022 11:24:38 -0800 Subject: [PATCH 2/2] try to use a single video source for now --- liquidsoap/radio.liq | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/liquidsoap/radio.liq b/liquidsoap/radio.liq index 2f359e6..e1fc760 100755 --- a/liquidsoap/radio.liq +++ b/liquidsoap/radio.liq @@ -66,9 +66,9 @@ stop_dump_f = ref (fun () -> ()) # live_dj = ref empty() live_dj = ref(source.fail()) -live_video_audio = ref(source.fail()) -live_video = ref(source.fail()) -vj_video = ref(source.fail()) +# live_video_audio = ref(source.fail()) +# live_video = ref(source.fail()) +# vj_video = ref(source.fail()) # def dj_dummy_started() = # log("dj dummy on_start") @@ -150,9 +150,9 @@ def my_request_function () = end end -backup_playlist = cue_cut(audio_to_stereo(request.dynamic(id="backup_playlist", timeout=60.0, my_request_function))) +backup_playlist = audio_to_stereo(request.dynamic(id="backup_playlist", timeout=60.0, my_request_function)) -scheduled_shows = cue_cut(audio_to_stereo(request.queue(id="scheduled_shows", timeout=60.0))) +scheduled_shows = audio_to_stereo(request.queue(id="scheduled_shows", timeout=60.0)) def format_time(~sec,~min,~hour,~mday,~mon,~year, ~wday,~yday,~isdst) = @@ -240,25 +240,28 @@ end live_dj := map_metadata(new_meta, !live_dj,update=false) -live_video := input.ffmpeg(id="main_video", max_buffer=60.0, "https://viz.streampusher.com:16666/hls/datafruits.m3u8") -vj_video := input.ffmpeg(id="vj_video", max_buffer=60.0, "https://viz.streampusher.com:16666/vj/datafruits.m3u8") - -live_video_audio := audio_to_stereo(drop_video(!live_video)) +# live_video := input.ffmpeg(id="main_video", max_buffer=60.0, "https://viz.streampusher.com:16666/hls/datafruits.m3u8") +# vj_video := input.ffmpeg(id="vj_video", max_buffer=60.0, "https://viz.streampusher.com:16666/vj/datafruits.m3u8") +# +# live_video_audio := audio_to_stereo(drop_video(!live_video)) # live_dj := pipe(process="./stereo_tool_cmd_64 - - -s ./stereotool.sts -k '#{stereo_tool_key}'", buffer=10.0, replay_delay=10.0, !live_dj) # output.dummy(fallible=true, on_start=dj_dummy_started, on_stop=dj_dummy_stopped, !live_dj) output.file(%mp3, "/home/liquidsoap/recordings/#{radio_name}-#{current_dump_filename}.mp3", !live_dj, fallible=true, append=true) source = fallback(id="fallback",track_sensitive=false, - [!live_video_audio, !live_dj,scheduled_shows,mksafe(backup_playlist)]) + [!live_dj,scheduled_shows,mksafe(backup_playlist)]) +# [!live_video_audio, !live_dj,scheduled_shows,mksafe(backup_playlist)]) single_video = noise() -video_source = fallback(id="video_fallback",track_sensitive=false, - [!live_video, - mux_audio(drop_audio(!vj_video), audio=source), - mksafe(mux_audio(single_video, audio=source))]) - +# live video (w audio), vj video mixed with radio audio, single video mixed with radio audio +video_source = mux_audio(single_video, audio=source) +# video_source = fallback(id="video_fallback",track_sensitive=false, +# [!live_video, +# mux_audio(drop_audio(!vj_video), audio=buffer(source)), +# mksafe(mux_audio(single_video, audio=buffer(source)))]) +# # source = if tunein_metadata_updates_enabled == "true" then on_track(tunein.submit(partnerid=tunein_partner_id,partnerkey=tunein_partner_key,stationid=tunein_station_id), source) else source end source.on_track(pub_metadata)