configuration sections

Setup your stations and basic setup at scheduler/scheduler/config.cfg.


Each <station> section defines its primary source stream URL url1 and optionally a fallback stream URL url2 which is played in case of outage of the primary source URL. You can define multiple aliases for the station which can be used to address the station in the schedule. This can prevent playout errors caused by typos. You can define a default station which is played if no other stream is scheduled. The station title will be displayed in log and web GUI output.

status_dir should be readable and writeable for scheduler and apache users.

Put the the input file schedule.csv into status_dir. This can be done by Google calendar synchronization by cron or manually. Scheduler will check periodically if the file was updated.


This defines the path to the web application and the timezone. You do not need to change anything here.


This sections contains file paths to the synchronization and the web GUI. Additionally there are some date and timing parameters. You might setup your time zone.


This defines the host and the port of the liquidsoap instance. You do not need to change anything here.



		# put one of the comma separated aliases into google calendar event title (e.g. dolebrai)
			alias	dolebrai,dolebraï
			title	Dolebraï - rastageek's station

			alias	default
			title	default (88vier)

		#web application directory
		webapp_dir	/home/radio/scheduler/web/

		#language used for date output format
		language	German

		#link to scheduled result stream, for link in GUI header only...
		result_stream	http://localhost:8000/radio

		#contains input file schedule.csv and other shared files for scheduler, synchronization and web user
		status_dir	/home/radio/scheduler/status/

		#command to trigger synchronization with Google Calendar
		sync_command	/home/radio/scheduler/calcms/

		#output log
		log		/var/log/liquidsoap/scheduler.log

		#how long scheduler should sleep between checks (in seconds)
		sleep		30

		#pre-switching offset in seconds (e.g. switch 8 seconds before scheduled time)
		switch_offset	8

		#local schedule reload period (in seconds)
		reload		10
		#set log/debug level
		debug		1

		#liquidsoap telnet server
		host		localhost
		port		8001


start/stop scheduler

if directly started from command line, depending on debug level there will be output at the console.


If you use the upstart job you can run the scheduler as a service

  • start the scheduler by

sudo start scheduler

  • stop the scheduler by

sudo stop scheduler


Log will be written to configured path. You can use the log to find the root cause in case of errors. Additionally current scheduler and liquidsoap status will be written into a status file, which can be used by the web GUI to see the current status online. Make sure that the log directory exists and the user has permissions to read from and write into it.

2011-05-29 17:05:46	INIT
2011-05-29 17:05:46	RELOAD	schedule	/home/radio/scheduler/status/schedule.csv
2011-05-29 17:05:47	current	'frapó' since	2011-05-29 10:00:00
2011-05-29 17:05:47	PLAY	frapó
2011-05-29 17:05:47	liquidsoap station1 plays:
2011-05-29 17:05:47	liquidsoap station2.stop
2011-05-29 17:05:47	liquidsoap station2 plays:	http://warning/invalid_url
2011-05-29 17:05:47	next in	1 hours 24 min 5 secs	dolebrai at 2011-05-29 18:30:00

manually edit schedule

status/schedule.csv is a plain CSV file. Each line contains the starting time of a broadcast (RFC3339) and either the source stream URL or the name of a station alias. The file can be created manually or generated by the Google Calendar synchronization job.


  • play a audio stream
    2011-05-01 15:00; http:/localhost:8000/audio-stream
  • play a audio stream, in case of outage play a second stream as fallback
    2011-05-01 16:00; http:/localhost:8000/audio-stream; http:/localhost:8000/fallback-stream
  • play a station given by name. A station predefines a set of stream URL and fallback stream
    2011-05-01 14:00; dolebrai

Calendar Synchronization

You need to setup this only, if you want to use the Google Calendar integration to frequently update the CSV file by current content of your Google Calendar.

configure source calendar

Login to Google Calendar, create a broadcast switch calendar and go to calendar settings. Copy the private calendar URL into calcms/sync_cms/config/source/schedule.cfg. Replace „/basic“ by „/full“

If you want to use the public calendar URL instead of the private one you need to set user and password at the <access> section additionally


	type			google_calendar
		time_zone	Europe/Berlin
	read_blocks		0

configure output CSV file

Set the output path to schedule file schedule.csv at calcms/sync_cms/config/target/schedule.cfg . The directory should be the same as status_dir at scheduler configuration.


	type 				liquidsoap_scheduler
		file			/home/radio/scheduler/status/schedule.csv
		time_zone		Europe/Berlin
		default_entry		default
		debug			1

Use Google Calendar to create new events

Login to Google Calendar Create a new event in your broadcast calendar, put one of the station aliases into the event title (e.g. dolebrai). Save the event. After synchronization the station will be played out at the time defined in the event. If you want to play a stream which is not configured in your stations, you can just put the stream URL into the title field. If you want to use an additional fallback URL, you can put after the first URL separated with a colon „;“

trigger synchronizing

To synchronize the CSV file with the Google Calendar content,

  • you can still execute calcms/
  • you can create a cronjob (e.g. hourly:
    0 * * * * /home/radio/scheduler/calcms/ >> /var/log/liquidsoap/sync.log
  • you can click at web GUI to synchronize the calendar.
  • you can touch a file named update at scheduler's status_dir. The scheduler will then execute the synchronization. This is used by the web GUI.

You can use multiple source and target files by configuring them in scheduler/calcms/sync_cms/config/source/ or scheduler/calcms/sync_cms/config/target/. For this you will need to adopt

see log

INFO:	last update: 2011-06-05 19:50:37
INFO:	read  events from google calendar: ''
INFO:	found 7 events
[1]     2011-06-02  18:00                     :                             - pi radio
[1]     2011-06-06  18:00                     :                             - frrapo
[1]     2011-06-07  02:00                     :                             - ansage
[2]     2011-06-07  18:00                     :                             - ansage
[1]     2011-06-08  18:00                     :                             - pi radio
[1]     2011-06-09  18:00                     :                             - pi radio
INFO:	clean up old database entries...
save to '/home/radio/scheduler/status/schedule.csv
INFO:	set last-update time: 2011-06-05 19:52:53


For restricted access change access permissions at scheduler/web/.htaccess and scheduler/.htpasswd. Default access is test/test

Configure <web> section at scheduler/config.cfg

Check http://localhost/scheduler/


This should work from scratch, so this section is only to show you how it works. Please see here for liquidsoap installation and see liquidsoap website to learn liquidsoap scripting language and get an overview on additional configuration.

There is a example liquidsoap file to get all running: play.liq.

To play out the currently scheduled stream execute

liquidsoap play.liq

The scheduler uses two http input streams station1 and station2 and telnet server for communication with liquidsoap. You may change anything else in the liq script to fit your needs.

This is the basic liquidsoap script. Put a mp3 to /home/radio/sound/net_outage.mp3 or change the path to an existing mp3 in the script below to define the fallback. Otherwise you can use the built-in drone-noise fallback.


#enable STDOUT logging for upstart support
set("log.stdout", true)

#enable telnet server
set("server.telnet", true)

#define two stations, station2 is fallback stream for station1
station1	= input.http(id="station1", "http://init/liquidsoap")
station2	= input.http(id="station2", "http://init/liquidsoap")

#define net outage channel
announce	= mksafe(single(id="announce",   "say:unstable network!"));
#defined a noised sine signal as net outage 
net_outage 	= mksafe(amplify(0.1,add([sine(),noise()])));
#play a file instead of sine signal
#net_outage 	= mksafe(single(id="net_outage", "/home/radio/sound/net_outage.ogg")) 

#in case of net outage announce it every minute
net_outage      = smooth_add(
		( { 0s }, announce )

#set station2 as fallback for station1 and net_outage as fallback for station2
radio = fallback(
	id="http_input fallback",


#audio out to soundcard

#output stream - http://localhost:8000/radio
	protocol="http", port=8000, mount="/radio",
	%vorbis.cbr(samplerate=44100, channels=2, bitrate=160), 

#avoid buffer overruns
output.dummy(fallible=true, station1);
output.dummy(fallible=true, station2);