My Radio Mutes Its Own Ads

My Radio Mutes Its Own Ads

SWR1 announces in its own radio text when ads are playing. Two triggers in Home Assistant are enough to make my Sonos speakers mute themselves.

Half past six, bathroom, the radio is on. Music, news, traffic report — and then the first ad jingle of the day. It cuts off after a blink. Nobody pressed a button. The speaker muted itself.

Behind it is no language model detecting ads, no audio fingerprinting, no subscription service. Behind it is an automation with two triggers — and a station that voluntarily announces when ads are playing.

That’s the actual joke of the thing: I didn’t have to build the detection at all. SWR1 delivers it for free.

The station gives it away itself

Every radio station sends a small text channel alongside the audio. On FM, this is known as RDS radio text; on an internet stream, the same text arrives as title metadata. Whether the station taps the same source internally, I don’t know — all that matters to us is that the same text arrives at the speaker.

The crucial point: this text field is not a static station name. It changes constantly. On SWR1, a sample from a single morning included this, among other things:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Walk of life / Dire Straits
Get lucky / Daft Punk feat. Pharrell Williams
I don't like Mondays / The Boomtown Rats
Something stupid / Robbie Williams & Nicole Kidman
Guten Morgen Baden-Württemberg mit Cora Klausnitzer & Matthias
SWR1 Baden-Württemberg Verkehrsservice
SWR1 Stau-Hotline: 0711-929 10 100
Aktuelle Nachrichten auch auf swr1.de
Nachricht über die SWR1 App
SWR1 Baden-Württemberg
Werbung in SWR1          ← the marker everything listens for

Song title, artist, presenter, traffic report, phone numbers — and right in the middle, the announcement that ads are currently playing. The station says so because the field is maintained anyway. Nobody thought that someone would build a mute automation on top of it.

My Sonos speaker reads this metadata from the stream, and the Sonos integration passes it into Home Assistant as the media_title attribute. That makes the ad block a perfectly normal state change in the system — and everything Home Assistant can do with state changes now works for radio ads too.

The signal chain is short:

1
2
3
4
5
6
SWR1 broadcast
  └─ Radio text in the stream ("Werbung in SWR1")
      └─ Sonos speaker reads the stream metadata
          └─ Sonos integration exposes it as the media_title attribute
              └─ Automation triggers on the exact text
                  └─ media_player.volume_mute

Step 1: Find your station’s marker

This is the most important section of this article, because Werbung in SWR1 works exclusively for SWR1 Baden-Württemberg. Other stations phrase it differently, or don’t send a marker at all. Before you build anything, you need to check what your station actually sends.

Here’s how:

  1. Play your target station on the speaker you want to control later.
  2. In Home Assistant, open Developer Tools → States.
  3. Find your media player entity, e.g. media_player.bathroom.
  4. Watch the media_title attribute column while an ad block plays.
  5. Note the text exactly: capitalization, spaces, special characters. The trigger compares character by character.

Faster: use Developer Tools → Template. This line shows you the live radio text without hunting through a long attribute list:

1
{{ state_attr('media_player.bathroom', 'media_title') }}

If you don’t want to sit next to the screen and wait for the next ad block, mirror the radio text into a template sensor. It then shows up in history, and you can review at your leisure what ran through over the day:

1
2
3
4
template:
  - sensor:
      - name: "Radio Text Bathroom"
        state: "{{ state_attr('media_player.bathroom', 'media_title') }}"

If you can’t find a usable marker, that’s where it ends — your station simply doesn’t send the information. Annoying, but honestly the more likely outcome. I got lucky with SWR1.

Step 2: Two triggers, one if

Now comes the ingredient many people don’t have on their radar: Home Assistant can trigger on an attribute change, not just on a state change.

The state of my speaker is playing the entire time. It doesn’t change when the ad starts — audio keeps playing, after all. What changes is the media_title attribute. That’s exactly what the trigger listens for via the line attribute: media_title. Without it, the automation would never fire. If you’re still missing the trigger basics, start with Home Assistant A-Z: A for Automations.

The second trick is symmetry:

  • to: Werbung in SWR1 — the radio text changes to the marker: ads start, mute.
  • from: Werbung in SWR1 — the radio text changes away from the marker: ads are over, audio back on.

Two triggers, two IDs, one if. That’s all there is to it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
blueprint:
  name: Mute Sonos on Ads
  description: Mutes playback when the RDS stream reports an ad marker
  domain: automation
  input:
    media_player:
      name: Media Player
      description: The media player entity to control
      selector:
        entity:
          domain: media_player

trigger:
- platform: state
  entity_id:
  - !input media_player
  attribute: media_title
  to: Werbung in SWR1
  id: mute
- platform: state
  entity_id:
  - !input media_player
  attribute: media_title
  from: Werbung in SWR1
  id: unmute
condition: []
action:
- if:
  - condition: trigger
    id:
    - mute
  then:
  - service: media_player.volume_mute
    data:
      is_volume_muted: true
    target:
      entity_id: !input media_player
  else:
  - service: media_player.volume_mute
    data:
      is_volume_muted: false
    target:
      entity_id: !input media_player

To install it, drop the file into your Home Assistant configuration under blueprints/automation/<your-name>/sonos_ad_mute.yaml, reload blueprints under Settings → Automations & Scenes → Blueprints, and create automations from it. How blueprints work in general is covered in Home Assistant A-Z: B for Blueprints. You can also just paste the content from trigger: onward as a normal automation and replace !input media_player with your entity.

Two notes on the code that I don’t want to withhold:

The syntax is the classic one. platform: and service: are the older form; newer Home Assistant versions prefer triggers: and actions:. The old form still works, and since this is my blueprint running in production, I’m showing it exactly as it sits on my system.

The else branch is deliberately simple — and exactly for that reason a dead end. It unmutes on every trigger that isn’t mute. With exactly two triggers, that’s clean. As soon as you add a third, it unmutes too, and you get a bug that takes a while to find. Anyone extending this should turn the if/else into a choose beforehand. I collect this kind of pitfall in 5 Automation Mistakes Everyone Makes in Home Assistant.

If your station isn’t quite so unambiguous

For SWR1, the text is always identical, so an exact comparison is enough. If your station sends varying text — say, with an appended timestamp or changing wording — you need a trigger that checks for a text fragment instead of the whole string:

1
2
3
4
5
6
7
8
9
trigger:
- platform: template
  value_template: >
    {{ 'Werbung' in (state_attr('media_player.bathroom', 'media_title') or '') }}
  id: mute
- platform: template
  value_template: >
    {{ 'Werbung' not in (state_attr('media_player.bathroom', 'media_title') or '') }}
  id: unmute

Warning: this variant is not running for me — I don’t need it. It’s the obvious path, but untested. If you build it, check especially that the word doesn’t accidentally show up in song titles or programme announcements too. Otherwise your radio happily mutes itself during a segment about advertising agencies.

One automation per speaker

The blueprint is instantiated five times for me — once per room:

RoomEntity
Officemedia_player.office
Bedroommedia_player.bedroom
Bathroommedia_player.bathroom
Living roommedia_player.living_room
Terracemedia_player.terrace

Looks like unnecessary copy-paste, but it’s necessary: on Sonos, muting is a property of the individual speaker. Even when several speakers are grouped together, each one has to be muted separately. Which is exactly what a blueprint is for — click five times, pick an entity five times, done. What else those five speakers draw in standby power, and how I switch them off at night, is covered in 5 Smart Home Automations: Saving Power with Home Assistant.

Ten days of recording: what does it actually do?

An automation like this quietly runs in the background, and after a few weeks you no longer notice whether it’s actually doing anything. So I evaluated my Home Assistant database, period August 17–27, 2026, i.e. ten days.

Result: 73 detected ad blocks — and the automation has worked reliably since it was set up. Not a single case where the marker was in the radio text and the mute didn’t fire.

Nearly all triggers cluster between 6 and 9 a.m.:

HourAd blocks
06:0044
07:0015
08:004
12:002
13:006
18:002

Before you conclude that SWR1 airs particularly heavy morning advertising: these numbers don’t show that. They only show when I have the radio on — almost exclusively in the morning, as an alarm and breakfast companion. I have no data on how many hours I listen at which time of day, and without that denominator, the distribution isn’t evidence of ad timing, just a picture of my listening habits. What the numbers do show: whenever the radio is on, the automation fires reliably.

On block length: for 31 blocks a clean end could be measured, 30 of which fell within a plausible range.

  • Median: 117 seconds — just under two minutes per ad block
  • Mean: 97 seconds
  • Range: 17 to 150 seconds
  • Sum of these 30 blocks: roughly 49 minutes of silence over ten days

Scaling the median up to all 73 blocks lands around two hours — but that’s an estimate, not a measurement, so I’d rather quote the 49 minutes that actually show up in the data.

One quirk from the evaluation I’m keeping: one block clocked in at 2216 seconds, over 36 minutes. No ad block is that long. What actually happened: the speaker was switched off mid-ad, the radio text stayed put, and the end was only registered the next time it was switched on. Not a bug in the automation, but a good example of why you shouldn’t dump raw recorder data into a statistic unfiltered.

Where the limits are

So you know what you’re signing up for — five real limitations:

1. The marker is hard-coded and station-specific. Werbung in SWR1 applies to SWR1 Baden-Württemberg and nowhere else. Whether other SWR stations use the same text, I haven’t tested. That’s why the observation step above comes so early: it’s the actual work of rebuilding this.

2. It mutes, it doesn’t skip. The ad time keeps running, it’s just silent. On a live stream there’s no other way — there’s nothing to skip to.

3. Only radio streams with metadata. Spotify, music from your own library, or line-in have no such field. The whole approach depends entirely on a station voluntarily sending something.

4. One automation per speaker, as above.

5. The automation is in charge of the mute. If you mute your speaker yourself for your own reasons and an ad block ends during that time, the automation lifts your mute. That happens rarely and doesn’t really hurt, but the interaction isn’t thought through.

And one number I checked with a stopwatch instead of estimating: latency. How many seconds of ads get through before the audio drops depends on how quickly the speaker updates the stream metadata and the integration passes the event on. For me that’s on average one to two seconds — the ad jingle is just barely audible, then it’s quiet.

Conclusion

The appeal of this automation isn’t the automation itself. It’s trivial: two triggers, one branch, two lines of action.

The appeal is that a problem that sounds like it needs machine learning and audio analysis dissolves into thin air the moment you look in the right place. The information was there the whole time. It just sat in a field nobody looks at.

That’s a pattern that works more often in smart homes than you’d think: before you start detecting something, check whether someone is already telling you. Entity attributes are an underrated goldmine for this — and the fact that Home Assistant can trigger on them directly makes them immediately usable.

What’s in your media_title when your station plays ads? Tell me in the comments — I’m curious which stations else deliver this.

Built with Hugo
Theme Stack designed by Jimmy
Build: 2026-09-03 09:31 UTC