Azuracast: Playlist that "Interrupt other songs to play at scheduled time." does not work

Created on 11 Apr 2020  ·  4Comments  ·  Source: AzuraCast/AzuraCast

Using Docker installation method

Yes, Docker.

Host Operating System

Ubuntu 18.04
Describe the bug

"Interrupt other songs to play at scheduled time.", I enable this function for the playlist, it does not interrupt other songs, the playing songs continue playing ignoring the scheduled playlist completely.
To Reproduce

Expected behavior

At right time, the schedule playlist starts working by interrupting other sons.

WARNING! This file is automatically generated by AzuraCast.

Do not update it directly!

set("init.daemon", false)
set("init.daemon.pidfile.path","/var/azuracast/stations/cn/config/liquidsoap.pid")
set("log.stdout", true)
set("log.file", false)
set("server.telnet",true)
set("server.telnet.bind_addr","0.0.0.0")
set("server.telnet.port", 8004)
set("harbor.bind_addrs",["0.0.0.0"])

set("tag.encodings",["UTF-8","ISO-8859-1"])
set("encoder.encoder.export",["artist","title","album","song"])

setenv("TZ", "Asia/Shanghai")

playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90 = playlist(id="playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90",mode="randomize",reload_mode="watch",conservative=true,default_duration=10.,length=20.,"/var/azuracast/stations/cn/playlists/playlist_-E6-94-BE-E6-9D-BE-E9-9F-B3-E4-B9-90.m3u")
playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90 = audio_to_stereo(id="stereo_playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90", playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90)
playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90 = cue_cut(id="cue_playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90", playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90)

Standard Playlists

radio = random(id="chinese_standard_playlists", weights=[3], [playlist__E6_94_BE_E6_9D_BE_E9_9F_B3_E4_B9_90])

AutoDJ Next Song Script

def azuracast_next_song() =
uri = list.hd(get_process_lines("curl -s --request POST --url http://web/api/internal/1/nextsong --form api_auth="^string.quote("6523104dfe982e101f62a979876d553439ce97bae6e25783ec71af3e82c9a68d04110c8a360c45ab7a53de45ff027acc636f")^""), default="")
log("AzuraCast Raw Response: #{uri}")

if uri == "" or string.match(pattern="Error", uri) then
    log("AzuraCast Error: Delaying subsequent requests...")
    system("sleep 2")
    request.create("")
else
    request.create(uri)
end

end

dynamic = request.dynamic(id="chinese_next_song", timeout=20., azuracast_next_song)
dynamic = audio_to_stereo(id="chinese_stereo_next_song", dynamic)
dynamic = cue_cut(id="chinese_cue_next_song", dynamic)
radio = fallback(id="chinese_autodj_fallback", track_sensitive = true, [dynamic, radio])

requests = request.queue(id="chinese_requests")
requests = audio_to_stereo(id="chinese_stereo_requests", requests)
requests = cue_cut(id="chinese_cue_requests", requests)
radio = fallback(id="chinese_requests_fallback", track_sensitive = true, [requests, radio])

add_skip_command(radio)

radio = fallback(id="chinese_safe_fallback", track_sensitive = false, [radio, single(id="error_jingle", "/usr/local/share/icecast/web/error.mp3")])

radio = crossfade(smart=false, duration=3.,fade_out=2.,fade_in=2.,radio)

DJ Authentication

live_enabled = ref false
last_authenticated_dj = ref ""
live_dj = ref ""

def dj_auth(auth_user,auth_pw) =
user = ref ""
password = ref ""

if (auth_user == "source" or auth_user == "") and (string.match(pattern="(:|,)+", auth_pw)) then
    auth_string = string.split(separator="(:|,)", auth_pw)

    user := list.nth(default="", auth_string, 0)
    password := list.nth(default="", auth_string, 2)
else
    user := auth_user
    password := auth_pw
end

log("Authenticating DJ: #{!user}")

ret = list.hd(get_process_lines("curl -s --request POST --url http://web/api/internal/1/auth --form dj-user="^string.quote(!user)^" --form dj-password="^string.quote(!password)^" --form api_auth="^string.quote("6523104dfe982e101f62a979876d553439ce97bae6e25783ec71af3e82c9a68d04110c8a360c45ab7a53de45ff027acc636f")^""), default="")
log("AzuraCast DJ Auth Response: #{ret}")

authed = bool_of_string(ret)
if (authed) then
    last_authenticated_dj := !user
end

authed

end

def live_connected(header) =
dj = !last_authenticated_dj
log("DJ Source connected! Last authenticated DJ: #{dj} - #{header}")

live_enabled := true
live_dj := dj

ret = list.hd(get_process_lines("curl -s --request POST --url http://web/api/internal/1/djon --form dj-user="^string.quote(dj)^" --form api_auth="^string.quote("6523104dfe982e101f62a979876d553439ce97bae6e25783ec71af3e82c9a68d04110c8a360c45ab7a53de45ff027acc636f")^""), default="")
log("AzuraCast Live Connected Response: #{ret}")

end

def live_disconnected() =
dj = !live_dj

log("DJ Source disconnected! Current live DJ: #{dj}")

ret = list.hd(get_process_lines("curl -s --request POST --url http://web/api/internal/1/djoff --form dj-user="^string.quote(dj)^" --form api_auth="^string.quote("6523104dfe982e101f62a979876d553439ce97bae6e25783ec71af3e82c9a68d04110c8a360c45ab7a53de45ff027acc636f")^""), default="")
log("AzuraCast Live Disconnected Response: #{ret}")

live_enabled := false
last_authenticated_dj := ""
live_dj := ""

end

A Pre-DJ source of radio that can be broadcast if needed

radio_without_live = radio
ignore(radio_without_live)

Live Broadcasting

live = audio_to_stereo(input.harbor("/", id = "chinese_input_streamer", port = 8005, auth = dj_auth, icy = true, icy_metadata_charset = "UTF-8", metadata_charset = "UTF-8", on_connect = live_connected, on_disconnect = live_disconnected, buffer = 5., max = 10.))
ignore(output.dummy(live, fallible=true))

radio = fallback(id="chinese_live_fallback", track_sensitive=false, [live, radio])

Record Live Broadcasts

stop_recording_f = ref (fun () -> ())

def start_recording(path) =
output_live_recording = output.file(%fdkaac(channels=2, samplerate=44100, bitrate=192, afterburner=true, aot="mpeg4_aac_lc", sbr_mode=true), fallible=true, reopen_on_metadata=false, "#{path}", live)
stop_recording_f := fun () -> source.shutdown(output_live_recording)
end

def stop_recording() =
f = !stop_recording_f
f ()

stop_recording_f := fun () -> ()

end

server.register(namespace="recording", description="Start recording.", usage="recording.start filename", "start", fun (s) -> begin start_recording(s) "Done!" end)
server.register(namespace="recording", description="Stop recording.", usage="recording.stop", "stop", fun (s) -> begin stop_recording() "Done!" end)

Allow for Telnet-driven insertion of custom metadata.

radio = server.insert_metadata(id="custom_metadata", radio)

Apply amplification metadata (if supplied)

radio = amplify(override="liq_amplify", 1., radio)

Send metadata changes back to AzuraCast

def metadata_updated(m) =
if (m["song_id"] != "") then
ret = list.hd(get_process_lines("curl -s --request POST --url http://web/api/internal/1/feedback --form song="^string.quote(m["song_id"])^" --form media="^string.quote(m["media_id"])^" --form playlist="^string.quote(m["playlist_id"])^" --form api_auth="^string.quote("6523104dfe982e101f62a979876d553439ce97bae6e25783ec71af3e82c9a68d04110c8a360c45ab7a53de45ff027acc636f")^""), default="")
log("AzuraCast Feedback Response: #{ret}")
end
end

radio = on_metadata(metadata_updated,radio)

Local Broadcasts

output.icecast(%mp3(samplerate=44100, stereo=true, bitrate=128, id3v2=true), id="chinese_local_1", host = "127.0.0.1", port = 8000, password = "HqT2cy7Q", mount = "/radio.mp3", name = "曼谛悟思电台", description = "曼谛悟思的直播内容。", genre = "", url = "", public = false, encoding = "UTF-8", radio)
output.icecast(%mp3(samplerate=44100, stereo=true, bitrate=192, id3v2=true), id="chinese_local_2", host = "127.0.0.1", port = 8000, password = "HqT2cy7Q", mount = "/radio-192.mp3", name = "曼谛悟思电台", description = "曼谛悟思的直播内容。", genre = "", url = "", public = false, encoding = "UTF-8", radio)
output.icecast(%mp3(samplerate=44100, stereo=true, bitrate=64, id3v2=true), id="chinese_local_3", host = "127.0.0.1", port = 8000, password = "HqT2cy7Q", mount = "/radio-64.mp3", name = "曼谛悟思电台", description = "曼谛悟思的直播内容。", genre = "", url = "", public = false, encoding = "UTF-8", radio)

Remote Relays

Relevant Logs

Screenshots

Device(s):

  • Device:
  • OS:
  • Browser:
  • Version:

Additional context

Most helpful comment

This is unfortunately by design with the "Advanced AutoDJ configuration options" in playlists. Since they're managed by the Liquidsoap AutoDJ and there is no way to reload Liquidsoap configuration without actually restarting the Liquidsoap service itself, this is a necessary component any time you make changes to a playlist with those settings enabled.

All 4 comments

only after manually restarting the liquidsoap service, it takes effects immediately.

Yes it is effectively by restarting liquidsoap that the programmed playlists work.

Yes it is effectively by restarting liquidsoap that the programmed playlists work.

As log shows, it works in the following day, and I will test it tonight.

This is unfortunately by design with the "Advanced AutoDJ configuration options" in playlists. Since they're managed by the Liquidsoap AutoDJ and there is no way to reload Liquidsoap configuration without actually restarting the Liquidsoap service itself, this is a necessary component any time you make changes to a playlist with those settings enabled.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RemBdev picture RemBdev  ·  4Comments

Rafaelrds2017 picture Rafaelrds2017  ·  3Comments

adamderann picture adamderann  ·  4Comments

SlvrEagle23 picture SlvrEagle23  ·  3Comments

TogarUshindi picture TogarUshindi  ·  3Comments