Skip to main content

Listening

A deadair station is heard through one address. Everybody who connects hears the same broadcast at the same moment: there is no per-listener shuffle and no skip button. It is served from the same port as the console, so whatever already fronts that port carries the station too.

The mount​

The stream is /live.mp3 on your station's address. MP3 is always on, with no switch, because it is the compatibility floor: a Sonos, a car head unit or a hardware radio takes MP3, AAC or nothing.

Three more mounts can be switched on beside it, each off by default because each is another encoder running around the clock whether or not anybody is listening to it:

  • /live.opus
  • /live.aac
  • /live.flac, which is only worth anything when your sources are lossless too.

There is also an HLS stream at /live.m3u8, carrying AAC. An ordinary mount is one long-lived connection, which dies when a phone moves between wifi and mobile data. HLS is a series of ordinary web requests that a player simply retries, so it survives the handover, at the cost of a few more seconds of delay and one more encoder. Any web page may embed it, including players that fetch it from script.

For a hardware radio, a car receiver or a desktop player that wants a playlist file rather than a stream address, point it at /listen.pls or /listen.m3u on your station's address. Each lists every stream you publish, MP3 first, and the .m3u adds the HLS stream when it is on. Both need the address listeners reach you at, under Settings, Stream, because a playlist file has to name full addresses.

The mount is not authenticated. Anybody who can reach the address can listen, which for a radio station is usually the point. It is still your music under somebody else's licence, so read the licensing notes before you publish an address.

To limit how many people can listen at once, set Most listeners on each stream under Settings, Stream. It applies to each stream separately (the MP3 mount, each extra format and HLS), turns away only a new listener and never somebody already listening, and zero means no limit. Saving it restarts the stream server, which drops everyone listening for a few seconds, so change it when nobody is.

What a player shows​

A stream carries one line of text and one URL, and that is the whole display ceiling for anything that can only take a stream: a car head unit, a hardware radio, an amp with a screen.

The line is the record and its artist while music is playing. While the station is talking it is your station's name — a producer's label on an amp's screen is your paperwork in a listener's front room — except where the break knows a better way to say what it is: a forecast airs as Your Station - Weather in Brooklyn and a bulletin as Your Station - Sport news. Talk breaks, idents and anything an operator adds show the station's name, because nothing can tell from a label alone whether it was written for a listener or for you. Your listener apps show the same line.

The URL beside it is the artwork, and players that fetch it draw it in place of a cover. It carries the record's sleeve when your station holds a copy of one, the picture for a kind of break while the station is talking, and your station's logo the rest of the time — an uncached record, the bed, off air. The logo is also what a break of a kind with no picture of its own shows.

The station ships a picture for a weather forecast and one for a news bulletin. Replace either with your own, or put the shipped one back, under Settings, Artwork: jpeg, png, webp or gif, up to 4 MB, and a square one, since that is the shape everything draws it in. The address listeners reach you at has to be set for any of this to leave the station, because there is no base to make the URL absolute against otherwise; that is Settings, Stream, and it is the same setting the logo needs.

The first few seconds​

By default a station airs only while somebody is listening, so connecting is what puts it on air. The first seconds after pressing play are warm-up: the station takes the mount, hands over the first record and the encoder starts. A few seconds of nothing is the station starting, not failing. If the first records are still downloading, the station says so on air rather than leaving you in silence. When the last listener leaves, it stays on for five minutes in case they come back. The check-up explains the rule, and how to set a station to air whenever it has something to play.

GET /nowplaying needs no sign-in, and a page on any other site may read it from the browser, so a widget of your own can show what is playing without a server of its own in between. If you write your own player, read the published mounts from it rather than connecting to each to see: a connection, however brief, is an audience for five minutes. And send one user agent from every request, because HLS listeners are counted by address and agent, and two agents count as two listeners.

On Android​

The Android app is a listener first: background playback, lock-screen controls, what is on air, and a choice of format. Give it your station's address, and it shows you the name of the station that answered before keeping it. Out of the box it plays Automatic: HLS where your station publishes it, so moving between wifi and mobile data does not cut the stream, and MP3 where it does not. Pick a format yourself under Settings if you would rather; the picker greys out whatever your station does not publish. Listening needs no account. Now playing is the cover and little over it: left alone for a few seconds while a record plays, the words, the controls and the tabs fade away and the art fills the screen, and the first touch brings them back. A sleep timer sits under Settings, Listening while the station is playing; it stops the station after 15, 30, 45 or 60 minutes or at the end of the record that is on, fading out over the last ten seconds. Beside it, Keep the screen on answers Never (the default), While charging or Always, and holds the screen on only while this phone is playing the station and Now playing is in front. The lock screen, the notification shade and a car's screen show how far through the record you are, following the audio you hear; the bar cannot be dragged, because a live station cannot be scrubbed, and a break shows the live stream as before. Under the controls on Now playing, the output button opens the phone's own output switcher, so the station can play through Bluetooth earbuds or a speaker the phone can send sound to, and while it does, a line under the controls says "Playing on" and names it. A phone without a switcher opens Bluetooth settings instead. It is careful with the battery: with the display dark, when nobody can see the answer, it asks the station every thirty seconds rather than every three, and a stream it has given up reconnecting to stops instead of sitting there looking like it is still playing.

Signed in, it can ask the station for a record (an admin gives a friend an account to sign in with by inviting them): Request sits at the end of the controls on Now playing and on Up next, and leads to a search, an optional name, dedication or message, and a list of what became of your recent requests (requests has the rules). Now playing also has a Lyrics button whenever the record you are hearing has words (see Lyrics).

Signed in with the operator's account, the same email and password the console takes, it adds what the station has played, what is coming up and what it said between records, with a page for every record, album and artist. It becomes the remote as well. The desk, reached from Settings, is where everything that can take the station off air lives: whether it is on air and who it is going out to, Skip, Take off air, the hold against the schedule, what puts the station on air, and why it is or is not on. Elsewhere you can reorder and drop the running order, rate records, albums, artists and breaks, put a playlist or a chart on air, and add a record: Add a record on Up next searches the library by title, Play next puts one straight after what the station is already holding and Add to the end puts it last, and a record's own page offers the same two. Records the station has no audio for yet are listed but cannot be added, and a record the station declines (something you disliked, say) is refused with a sentence rather than a number. Say something, under Manage on Up next, asks the station for the news, the weather or a word from the host after the record on air (see asking for a break now). In a car, pause stops the stream, the next button is the operator's Skip and is offered to nobody else, and pressing play on the wheel starts the station even when the app is not running.

The station can sit outside the app, on three surfaces. A Quick Settings tile starts and stops it from the shade without opening the app, showing Warming up for the seconds between the press and the first sound. A home-screen widget (Settings, Home-screen widget, Add to the home screen, or the launcher's own widget list) shows what is playing over its cover, or who is on the mic while the station talks, with a button that starts and stops it; signed in as the operator it carries Skip too, and that one arms on the first press and forgets itself after five seconds, so a press in a pocket costs nobody a record. And the station can be the phone's wallpaper (Settings, Station wallpaper, Set as wallpaper), which opens the system's own picker on it so you choose the lock screen, the home screen or both. It draws the cover at the top, the middle or the foot of the screen, so it sits where your icons are not, and it can colour the phone from the station's own colours, from the cover on screen, or from a colour you pick. Nothing is ever written over the wallpaper you already had, and choosing another wallpaper is how it comes off again.

Each of those decides for itself when it is worth asking the station anything, because a surface that exists for as long as the phone is on must not poll for as long as the phone is on. The widget and the wallpaper both default to showing what is on while this phone is playing, which asks your station nothing at all the rest of the time. Set either to follow the station instead and the widget checks every half hour, and whenever you tap the time it shows, and says how old that answer is once it is more than two minutes.

deadair:// links open the app. A link names a station and fills in the setup screen with it: nothing changes until you check the address and choose to listen, and Keep the station I have turns it down. The console has one under the mounts on Check-up, Machinery, beside a code to scan, which is the shortest way to hand a phone a station on your own network. The macOS app reads the same links.

It is on Google Play. To build it yourself instead, you need a JDK and the Android SDK, and the instructions are in the app's directory.

On an iPhone​

The iPhone app is a listener first: background playback, the lock screen and Control Center, what is on air with its artwork, and a choice of format, read from what your station publishes. It starts on Automatic, the same as Android: HLS where your station publishes it, MP3 otherwise. Give it your station's address and it shows you the name of the station that answered before keeping it. A station on your own network makes iOS ask for Local Network access the first time, which is expected. Pause and stop both drop the connection, and a phone call stops the stream rather than holding it, because a held connection still counts as a listener. Listening needs no account.

Now playing turns on its side: the cover sits beside the title and the controls. Under the controls an AirPlay button opens the system's list of speakers, so the station can play on an AirPlay speaker or a Bluetooth device, and while it does a line under the controls says "Playing on" and names it. Choosing one moves the sound rather than adding a second listener; headphones coming out, or a speaker going away, stop the station. The lock screen, Control Center and CarPlay show how far through the record you are, following the audio you hear, and say LIVE during a break. Under Settings, Listening, the sleep timer stops the station after 15, 30, 45 or 60 minutes or at the end of the record, and Keep the screen on answers Never (the default), While charging or Always, holding the screen on only while this phone is playing the station and Now playing is in front.

The station can sit outside the app. A Now playing widget for the Home Screen, small or medium, shows the record you are hearing with its cover, or who is on the mic during a break, with a Play or Stop button that works without opening the app. It asks the station nothing of its own: it shows what the app last heard, and says when that was once it is more than a couple of minutes old. While the station plays, a Live Activity on the Lock Screen and in the Dynamic Island shows what is on, a bar for how far through the record it is, and a Stop button. It starts when you press play in the app (iOS refuses to start one from the background, so a play from the widget or Siri starts none) and goes when you stop. Show on the Lock Screen, under Settings, Listening, turns it off. Siri and Shortcuts start the station with "Play deadair", even after you have swiped the app away, and so can the Action button. The app has a CarPlay screen too, the station as a single row, but it turns on only once Apple approves the app for CarPlay, and until then the app does nothing in the car.

Signed in, it can ask the station for a record: Request sits at the end of the controls on Now playing and on Up next, as on Android, and Now playing has a Lyrics button whenever the record you are hearing has words (see Lyrics). Signed in with the operator's account, the same email and password the console takes, with an authenticator code when the account has one, it becomes the remote Android is: Skip and Shuffle on Now playing, and the next button on the lock screen as the operator's Skip; Up next to reorder and drop; Manage to replan the show, add a record, put a playlist or a chart on air, and ask the station to say something now (the news, the weather or a word from the host); the host picker; ratings for records, albums, artists and what the station said; and the desk, opened from Settings, with Take off air, the hold, the air mode and why the station is or is not on. It reads the same deadair:// links as the other two apps.

It is not on the App Store yet. To build it yourself you need Xcode 16 or later, and the instructions are in the app's directory.

On a Mac​

The desktop app is a listener with a proper player and the operator's desk in one window. The first release is for macOS on Apple Silicon and nothing else.

It plays through the system's own player, so the stream shows up in the system's Now Playing display and answers the media keys. The next key is the operator's Skip and is registered only while you are signed in as the operator; pause and stop both drop the connection, because a paused connection still counts as a listener. It can also send the station to a BluOS network speaker. Changing where it plays is a transfer rather than an addition: the local player stops and disconnects before the speaker is asked to play, so the station never counts two listeners for one person.

While the station is playing on a speaker rather than the Mac, a strip across the top of the window says which one ("Playing on Kitchen"), so it can be read from across the room, and says so when the speaker did not answer the last look. Clicking it opens the output picker.

Studio is the record on air across the whole screen, to sit back from: the cover large, the title, who is presenting and the playhead, over the cover's own colours, with Listen and Stop and nothing else. Open it with the TV button in the bar, Window › Studio, or F, and leave it with Escape, F or its close button. The controls and the pointer fade after a few seconds of stillness. Keep the display awake, on the Settings page, answers Never (the default), While charging or Always, and holds the display awake only while Studio is up where it can be seen and the station is playing.

Listening needs no account. Signed in, it shows the words of the record you are hearing in the Now playing panel, and a button beside play in Studio swaps the cover for them (see Lyrics). It also shows the running order, which it can reorder and drop from, the timetable, the library, who is presenting and what they have said, and the check-up, and it can change the station's settings. On the desk, Say something beside Take a call asks the station for the news, the weather or a word from the host.

It is built from source with .NET 10. The bundle it produces is not notarised, so macOS refuses the first launch. On macOS 15 and later a right-click and Open no longer gets past that: open it once, let it refuse, then press Open Anyway in System Settings › Privacy & Security, or run xattr -dr com.apple.quarantine on the app. The build instructions are in the app's directory.

Apart from your station, the one thing the desktop app talks to is GitHub: at launch it asks once whether there is a newer desktop release, sending nothing but its own name and version, and offers a link if there is. Turn it off under Settings, Updates.

On a speaker or a television​

The station can put itself on a speaker on your network: anything with Chromecast built in (Google's own speakers, many televisions and a good few AV receivers), a Sonos, a BluOS player, or any UPnP/DLNA renderer. Turn on the Speakers plugin and use Play on a speaker under the transport on the Desk. The plugin looks for speakers on your network by itself, which works when the station can see your network's multicast: running on the host's network rather than a Docker bridge network, as the install guide explains (on Unraid, see its page). Where it cannot, add each speaker in the plugin's settings. A Chromecast, a Sonos or a BluOS player is added by the address your router gave it. Any other renderer is added by the address of its description, an http:// URL ending in .xml that a UPnP browser shows, and some renderers move it when they restart.

The speaker fetches the stream itself, from the station's public address (Settings, Stream, Public URL) unless Address for speakers beside it says otherwise, so that address has to be one the speaker can reach. A speaker playing the station is a listener like any other, and holds it on air while it plays. The station keeps it playing: if the stream drops, or the station restarts, it plays it again on its own. It lets go when you stop it from the same menu, or when somebody at the speaker stops it there or plays something else on it, and it never plays the station over whatever they chose.

The speaker shows the station's name and the programme rather than each record, because a Chromecast's own player cannot be told what changed without starting the stream again. A Sonos and a BluOS player read the record from the stream itself.

Some televisions cannot play an https:// stream at all through their DLNA player, Samsung's among them: they show "This file format is not supported" while the same stream plays over plain http://. For those, and for any speaker that cannot reach the public address from inside your network, set Settings, Stream, Address for speakers to the station's plain http:// address on your network, such as http://192.168.1.10:8080. Speakers are then handed that address while listeners keep the public one.

Through Music Assistant​

The station cannot put itself on a HomePod or any other AirPlay speaker, nor on an Alexa. Music Assistant can, and all it needs is the stream. In Music Assistant, add a custom radio station and give it the station's MP3 address: /live.mp3 on your station's address, which Check-up, Machinery has a Copy button for under Listen. Music Assistant then plays the station on any speaker it reaches.

Music Assistant usually runs on your own network, so the address has to be one it can reach from there. When the public address does not resolve inside your network, or routes out and back in through a tunnel, give it the station's plain http:// address on your network instead, the same one Address for speakers takes.

Music Assistant playing the station is a listener like any other and holds it on air while it plays, so the first seconds after you press play are the station coming on air, not a fault.

Lyrics​

A record's words reach a listener only through a signed-in app, and never through the stream or the presenter: the station never says a lyric. They come from the LRCLIB plugin, once Look up the words of each record is on under Settings, Measurement. It is off by default, because lyrics are somebody else's copyrighted text and the sources are run by volunteers.

  • Android and iPhone: signed in, Now playing has a Lyrics button whenever the record you are hearing has words. There is none on an instrumental or a talk break.
  • Mac: signed in, the Now playing panel shows them under a Lyrics heading that folds away, and Studio has a button beside play that swaps the cover for them.
  • The console: each record's page in the library has a Lyrics card, with the time of each line where the source has timings, which source they came from, and Every source for what each lyrics source answered.

Timed lyrics light the line being sung and keep it in view, following the audio you hear rather than the station's clock. Where the source times each word, the sung part of the line lights as it is sung. Lyrics without timings are shown as they came.

In the console​

The console does not play the station itself, deliberately: it is the desk, and the listening surfaces are the mount, the three apps and the speakers it casts to. Which formats are published, and whether HLS is on, are under Settings, Stream. What puts the station on air is under Settings, Playout, and on the Desk under Why is it not on air?. The listener count and the published mounts are on Check-up, Machinery.