Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regarding the Scheduled Playback of Promotional Ads #4217

Open
dycfan666 opened this issue Nov 21, 2024 · 5 comments
Open

Regarding the Scheduled Playback of Promotional Ads #4217

dycfan666 opened this issue Nov 21, 2024 · 5 comments
Labels

Comments

@dycfan666
Copy link

Description

I am using Liquidsoap 2.2.5+dev.

I have a playlist for an advertising audio file:

input_ad = mksafe(playlist(reload_mode="watch", mode="sequence", "/var/www/html/radiolist/local_scunicomad.playlist.m3u"))
This playlist contains a dozen or so promotional advertisement audio files.

I want the main stream to play the entire playlist input_ad every 10 minutes. My Liquidsoap script is as follows:
timed_promotions = delay(600., input_ad) outputmusic_two = fallback([timed_promotions, outputmusic_one])
The Liquidsoap script runs fine, and indeed, it plays one item from input_ad every 10 minutes. However, it does not play the entire playlist input_ad as I intended; it only plays one file every 10 minutes instead of completing the full playlist.

I am seeking help with how to make the main stream play the entire advertisement playlist input_ad every 10 minutes.

Thank you so much!

Steps to reproduce

I want the main stream to play the entire playlist input_ad every 10 minutes. My Liquidsoap script is as follows:
timed_promotions = delay(600., input_ad) outputmusic_two = fallback([timed_promotions, outputmusic_one])

Expected behavior

The Liquidsoap script runs fine, and indeed, it plays one item from input_ad every 10 minutes. However, it does not play the entire playlist input_ad as I intended; it only plays one file every 10 minutes instead of completing the full playlist.

Liquidsoap version

Liquidsoap 2.2.5+dev.

Liquidsoap build config

* Liquidsoap version  : 2.2.5+dev

 * Compilation options
   - Release build       : false
   - Git SHA             : (none)
   - OCaml version       : 5.2.0
   - OS type             : Unix
   - Libs versions       : angstrom=0.16.0 bigstringaf=0.10.0 bytes=[distributed with OCaml 4.02 or above] camlp-streams camomile.lib=2.0 cry=1.0.3 curl=0.9.2 dtools=0.4.5 dune-build-info=3.16.0 dune-private-libs.dune-section=3.16.0 dune-site=3.16.0 dune-site.private=3.16.0 duppy=0.9.4 ffmpeg-av=1.1.11 ffmpeg-avcodec=1.1.11 ffmpeg-avdevice=1.1.11 ffmpeg-avfilter=1.1.11 ffmpeg-avutil=1.1.11 ffmpeg-swresample=1.1.11 ffmpeg-swscale=1.1.11 fileutils=0.6.4 gen=1.1 liquidsoap-lang=2.2.5 liquidsoap-lang.console=2.2.5 liquidsoap_builtins liquidsoap_core liquidsoap_ffmpeg liquidsoap_optionals liquidsoap_oss liquidsoap_runtime magic-mime=1.3.1 menhirLib=20240715 metadata=0.3.0 mm=0.8.5 mm.audio=0.8.5 mm.base=0.8.5 mm.image=0.8.5 mm.midi=0.8.5 mm.video=0.8.5 pcre=7.5.0 ppx_string.runtime=v0.17.0 re=1.11.0 sedlex=3.2 seq=[distributed with OCaml 4.07 or above] stdlib-shims=0.3.0 str=5.2.0 stringext=1.6.0 threads=5.2.0 unix=5.2.0 uri=4.4.0
   - architecture        : amd64
   - host                : x86_64-pc-linux-gnu
   - target              : x86_64-pc-linux-gnu
   - system              : linux
   - ocamlopt_cflags     : -O2 -fno-strict-aliasing -fwrapv -pthread -fPIC -pthread
   - native_c_compiler   : gcc -O2 -fno-strict-aliasing -fwrapv -pthread -fPIC -pthread -D_FILE_OFFSET_BITS=64
   - native_c_libraries  : -lm -ldl -lpthread

 * Configured paths
   - mode              : default
   - standard library  : (set by dune-site)
   - scripted binaries : (set by dune-site)
   - rundir            : (set by dune-site)
   - logdir            : (set by dune-site)
   - camomile files    : (set by dune-site)

 * Supported input formats
   - MP3               : no (requires mad)
   - AAC               : no (requires faad)
   - Ffmpeg            : yes
   - Flac (native)     : no (requires flac)
   - Flac (ogg)        : no (requires ogg)
   - Opus              : no (requires opus)
   - Speex             : no (requires speex)
   - Theora            : no (requires theora)
   - Vorbis            : no (requires vorbis)

 * Supported output formats
   - FDK-AAC           : no (requires fdkaac)
   - Ffmpeg            : yes
   - MP3               : no (requires lame)
   - MP3 (fixed-point) : no (requires shine)
   - Flac (native)     : no (requires flac)
   - Flac (ogg)        : no (requires ogg)
   - Opus              : no (requires opus)
   - Speex             : no (requires speex)
   - Theora            : no (requires theora)
   - Vorbis            : no (requires vorbis)

 * Tags
   - Taglib (ID3 tags) : no (requires taglib)
   - Vorbis            : no (requires vorbis)

 * Input / output
   - ALSA              : no (requires alsa)
   - AO                : no (requires ao)
   - FFmpeg            : yes
   - GStreamer         : no (requires gstreamer)
   - JACK              : no (requires bjack)
   - OSS               : yes
   - Portaudio         : no (requires portaudio)
   - Pulseaudio        : no (requires pulseaudio)
   - SRT               : no (requires srt)

 * Audio manipulation
   - FFmpeg            : yes
   - LADSPA            : no (requires ladspa)
   - Lilv              : no (requires lilv)
   - Samplerate        : no (requires samplerate)
   - SoundTouch        : no (requires soundtouch)
   - StereoTool        : no (requires ctypes-foreign)

 * Video manipulation
   - camlimages        : no (requires camlimages)
   - FFmpeg            : yes
   - frei0r            : no (requires frei0r)
   - ImageLib          : no (requires imagelib)
   - SDL               : no (requires tsdl-image & tsdl-ttf)

 * MIDI manipulation
   - DSSI              : no (requires dssi)

 * Visualization
   - GD                : no (requires gd)
   - Graphics          : no (requires graphics)
   - SDL               : no (requires tsdl-image & tsdl-ttf)

 * Additional libraries
   - FFmpeg filters    : yes
   - FFmpeg devices    : yes
   - inotify           : no (requires inotify)
   - irc               : no (requires irc-client-unix)
   - jemalloc          : no (requires jemalloc)
   - lastfm            : no (requires lastfm)
   - lo                : no (requires lo)
   - memtrace          : no (requires memtrace)
   - mem_usage         : no (requires mem_usage)
   - osc               : no (requires osc-unix)
   - ssl               : no (requires ssl)
   - tls               : no (requires tls-liquidsoap)
   - posix-time2       : no (requires posix)
   - windows service   : no (requires winsvc)
   - YAML support      : no (requires yaml)
   - XML playlists     : no (requires xmlplaylist)

 * Monitoring
   - Prometheus        : no (requires prometheus)

Installation method

From OPAM

Additional Info

No response

@dycfan666 dycfan666 added the bug label Nov 21, 2024
@vitoyucepi
Copy link
Collaborator

Hi @dycfan666,
May I ask you to try instead the following sample?

input_ad = playlist("/var/www/html/radiolist/local_scunicomad.playlist.m3u")
timed_promotions = delay(600., input_ad)
outputmusic_two = fallback([timed_promotions, outputmusic_one])

I think it may be reload_mode="watch".
By the way, what does mode="sequence" mean? I've never heard of this parameter before.

@dycfan666
Copy link
Author

Regrettably, the issue persists. Here is my revised code:

Define the audio source for ads

input_ad = mksafe(playlist(reload_mode="watch", mode="randomize", "/var/www/html/radiolist/local_scunicomad.playlist.m3u"))

Ensure promotional content is inserted every 10 minutes

timed_promotions = delay(600., input_ad)
outputmusic_two = fallback([timed_promotions, outputmusic_one])

However, the desired functionality is still not achieved. My goal is for the main stream to play for 10 minutes, followed by the entire ad playlist being played in full. Currently, after 10 minutes of the main stream, only a single item from the ad playlist is played before returning to the main stream. I have no choice but to seek further assistance!

@gAlleb
Copy link
Contributor

gAlleb commented Nov 29, 2024

As an option.

radio = playlist("/music")

ads = playlist(loop=false, reload=0, "/ads")

thread.when(predicate.activates({ 00m or 10m or 20m or 30m or 40m or 50m }), fun() -> ads.reload())

radio = fallback(track_sensitive=true,[

                  ads, radio
       
                 ])

radio = mksafe(radio)
 
output(radio)

We've got ads playlist which doesn't reload itself and doesn't loop. Instead reload is called every 10 minutes. Of course the duration of tracks should be taken into consideration too.

So what we have is: radio source plays, at 10m and so on minutes of every hour ads playlist is reloaded and played fully without interruption of radio source, then stops until next reload.

Downside: if ads starts to play at 09m55s and the reload happens at 10m (when it's still playing) - we are likely to hear the whole playlist for the second time.

So either we need track_sensitive=false or to ponder more!

@gAlleb
Copy link
Contributor

gAlleb commented Nov 29, 2024

So if you want your ads to interrupt the main source - you can use the above function changing track_sensitive=true to track_sensitive=false. Here is another option)) We use request.queue. Why? What?) Seems to be some kind of reverse engineering of native LS functions)

# Our main playlist:
radio = playlist("/music")

# Path (only path) to our ads playlist:
ads = "/path/to/ads.m3u"

# We create a queue for ads, where we will push our playlist
ads_queue = request.queue()

# Our function where we check if queue is empty or not. If it's empty we push our ads playlist into it. 
# If it has tracks - we do nothing.
def play_ads_queue()

if ads_queue.queue() == [] then

  tracks = list.iter(fun (x) -> begin
       let (_, uri) = x
       ads_queue.push.uri(uri)
     end, playlist.parse("#{ads}"))

   log("Pushed ads playlist to queue")

else
   log("Queue is already populated")
end

end

# We run the above function every 10 minutes
thread.run(every=600., play_ads_queue)

# Our fallback
radio = fallback(track_sensitive=true,[

                  ads_queue, radio
       
                 ])

radio = mksafe(radio)
 
output(radio)

@dycfan666
Copy link
Author

Thank you very much for your enthusiastic and meticulous guidance. Following the method you provided, I have successfully achieved the functionality I needed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants