Introduction

One of the nice things about smart speakers is that they can play audio from a wide variety of sources. Combine this with Home Assistant and you have yourself a webradio and custom audio dashboard :)

This blog post will explain my setup and will provide you with the code and pointers needed to build your own version of it.

Screenshot of webradio dashboard
Webradio control center

Note that I’m setting this all up in YAML. Helpers like the dropdown and textbox can also be created using the UI. At the end of this blog posts, it’ll become clear why I’m doing everything in YAML.

Set-up

To set everything up, we’ll need some helpers that’ll provide a dropdown and a textbox, some scripts, and some Lovelace elements.

Let’s go through each part step-by-step. I’ll provide the full code at the end of this blogpost.

Helpers

These helpers will provide the dropdown selection of radio stations and a text field to enter our own URLs into.

Feel free to adapt the list of radio stations to your choosing. Finding the correct URL is often the hardest part. Check if your favorite station has a web player and whether you can extract the URL of the stream from the address bar or the network requests. There are also online services that will provide you with streams for lots of webradio stations.

Radio station dropdown

input_select:
  radio_station:
    name: 'Pick station'
    icon: mdi:radio
    initial: VRT Studio Brussel
    options:
      - VRT Radio 1
      - VRT Studio Brussel
      - VRT MNM
      - VRT NWS
      - Topradio
      - Qmusic
      - VBRO
      - Willy Radio

Custom URL textbox

input_text:
  url:
    name: URL
    min: 10
    max: 255
    icon: mdi:web
    mode: text

Scripts

Play from dropdown

The code below will be called by a button on our dashboard and will play the station that’s selected in the dropdown.

Optionally, it will also provide an image (the logo of the radio station) to be displayed on our Lovelace dashboard while playing. For this you’ll need to download the logos or images you want and store them in (a subfolder of) /config/www/ which will be referenced as /local/.

script:
  play_radio:
    alias: Play radio
    icon: mdi:play
    description: Play web radio on smart speaker
    mode: restart
    sequence:
      - service: media_player.volume_set
        data:
          entity_id: media_player.livingroom
          volume_level: 0.10
      - service: media_player.play_media
        data:
          entity_id: media_player.livingroom
          media_content_type: music
          media_content_id: >
            {%- set station = states('input_select.radio_station') -%}
            {% if station == "VRT Radio 1" %} http://icecast.vrtcdn.be/radio1-high.mp3
            {% elif station == "VRT Studio Brussel" %} http://icecast.vrtcdn.be/stubru-high.mp3
            {% elif station == "VRT Studio Brussel - #ikluisterbelgisch" %} http://icecast.vrtcdn.be/stubru_tgs-high.mp3
            {% elif station == "VRT MNM" %} http://icecast.vrtcdn.be/mnm-high.mp3
            {% elif station == "VRT NWS" %} http://progressive-audio.lwc.vrtcdn.be/content/fixed/11_11niws-snip_hi.mp3
            {% elif station == "Topradio" %} https://str.topradio.be/topradio.mp3
            {% elif station == "Qmusic" %} https://21293.live.streamtheworld.com/QMUSIC.mp3
            {% elif station == "VBRO" %} https://radiohuis.com/VBRO
            {% elif station == "Willy Radio" %} http://20723.live.streamtheworld.com/WILLY.mp3
            {% endif %}
          extra:
            thumb: >
              {%- set station = states('input_select.radio_station') -%}
              {% if 'Studio Brussel' in station %}  https://<your_HA_URL>/local/img/logo/logo_stubru.svg
              {% elif 'MNM' in station %} https://<your_HA_URL>/local/img/logo/logo_mnm.svg
              {% elif 'NWS' in station %} https://<your_HA_URL>/local/img/logo/logo_vrtnws.svg
              {% elif station[:3] == "VRT" %} https://<your_HA_URL>/local/img/logo/logo_vrt.svg
              {% elif station == "Topradio" %} https://<your_HA_URL>/local/img/logo/logo_topradio.svg
              {% elif station == "Qmusic" %} https://<your_HA_URL>/local/img/logo/logo_qmusic.svg
              {% elif station == "VBRO" %} https://<your_HA_URL>/local/img/logo/logo_vbro.png
              {% elif station == "Willy Radio" %} https://<your_HA_URL>/local/img/logo/logo_willy.svg
              {% endif %}
            stream_type: LIVE

Play custom URL

For this script we’ll also need the media_extractor integration. This uses youtube_dl to extract the audio stream from the video/stream/audoclip/… you give it.

media_extractor:

script:
  play_media_url:
    alias: Play media from URL
    mode: single
    icon: mdi:music-box-multiple-outline
    sequence:
      - service: media_player.media_stop
        target:
          entity_id: media_player.livingroom
      - service: media_player.volume_set
        data:
          entity_id: media_player.livingroom
          volume_level: 0.10
      - service: media_extractor.play_media
        data:
          media_content_type: MUSIC
          media_content_id: "{{ states('input_text.url') }}"
        target:
          entity_id: media_player.livingroom

Lovelace Dashboard

You can design your dashboard anyway you like.

I chose to use the Mini Media Player custom card to display what’s playing on my smart speaker. You can find it on HACS.

type: vertical-stack
cards:
  - type: custom:mini-media-player
    group: false
    artwork: cover
    source: full
    sound_mode: full
    info: short
    name: Living Room
    idle_view:
      when_idle: true
    entity: media_player.livingroom
  - type: entities
    entities:
      - entity: input_select.radio_station
        name: station
      - entity: script.play_radio
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.play_radio
  - type: entities
    entities:
      - entity: input_text.url
        name: URL
      - entity: script.play_media_url
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.play_media_url
        icon: mdi:play

Complete code

Below you’ll find the complete code for this blog post.

The reason I chose to define everything in YAML, including the helpers, is because I’ve split up my config in packages. This allows me to group to bundle related configurations together, making it easier to find all components.

If you don’t want to use packages, just move the code snippets to the relevant configurations (e.g. scripts.yaml).

configuration.yaml

homeassistant:
  packages: !include_dir_merge_named packages/

# Decided to keep this here as multiple packages may use this single integration
media_extractor:

packages/mediaplayers/media_url.yaml

---
# Play custom audio stream on smart speaker(s)
#
# https://www.home-assistant.io/integrations/media_extractor/
# https://www.home-assistant.io/integrations/input_text/
#
media_url:
  script:
    play_media_url:
      alias: Play media from URL
      mode: single
      icon: mdi:music-box-multiple-outline
      sequence:
        - service: media_player.media_stop
          target:
            entity_id: media_player.livingroom
        - service: media_player.volume_set
          data:
            entity_id: media_player.livingroom
            volume_level: 0.10
        - service: media_extractor.play_media
          data:
            media_content_type: MUSIC
            media_content_id: "{{ states('input_text.url') }}"
          target:
            entity_id: media_player.livingroom
  
  input_text:
    url:
      name: URL
      min: 10
      max: 255
      icon: mdi:web
      mode: text

packages/mediaplayers/webradio.yaml

---
# Play webradio on smart speaker(s)
#
# Based on https://community.home-assistant.io/t/chromecast-radio-with-station-and-player-selection/12732
#
# https://www.home-assistant.io/integrations/media_player
# https://www.home-assistant.io/integrations/input_select/
#
webradio:
  script:
    play_radio:
      alias: Play radio
      icon: mdi:play
      description: Play web radio on Chromecast
      mode: restart
      sequence:
        - service: media_player.volume_set
          data:
            entity_id: media_player.livingroom
            volume_level: 0.10
        - service: media_player.play_media
          data:
            entity_id: media_player.livingroom
            media_content_type: music
            media_content_id: >
              {%- set station = states('input_select.radio_station') -%}
              {% if station == "VRT Radio 1" %} http://icecast.vrtcdn.be/radio1-high.mp3
              {% elif station == "VRT Studio Brussel" %} http://icecast.vrtcdn.be/stubru-high.mp3
              {% elif station == "VRT Studio Brussel - #ikluisterbelgisch" %} http://icecast.vrtcdn.be/stubru_tgs-high.mp3
              {% elif station == "VRT MNM" %} http://icecast.vrtcdn.be/mnm-high.mp3
              {% elif station == "VRT NWS" %} http://progressive-audio.lwc.vrtcdn.be/content/fixed/11_11niws-snip_hi.mp3
              {% elif station == "Topradio" %} https://str.topradio.be/topradio.mp3
              {% elif station == "Qmusic" %} https://21293.live.streamtheworld.com/QMUSIC.mp3
              {% elif station == "VBRO" %} https://radiohuis.com/VBRO
              {% elif station == "Willy Radio" %} http://20723.live.streamtheworld.com/WILLY.mp3
              {% endif %}
            extra:
              thumb: >
                {%- set station = states('input_select.radio_station') -%}
                {% if 'Studio Brussel' in station %}  https://<my_homeassistant>/local/img/logo/logo_stubru.svg
                {% elif 'MNM' in station %} https://<my_homeassistant>/local/img/logo/logo_mnm.svg
                {% elif 'NWS' in station %} https://<my_homeassistant>/local/img/logo/logo_vrtnws.svg
                {% elif station[:3] == "VRT" %} https://<my_homeassistant>/local/img/logo/logo_vrt.svg
                {% elif station == "Topradio" %} https://<my_homeassistant>/local/img/logo/logo_topradio.svg
                {% elif station == "Qmusic" %} https://<my_homeassistant>/local/img/logo/logo_qmusic.svg
                {% elif station == "VBRO" %} https://<my_homeassistant>/local/img/logo/logo_vbro.png
                {% elif station == "Willy Radio" %} https://<my_homeassistant>/local/img/logo/logo_willy.svg
                {% endif %}
              stream_type: LIVE
  
  input_select:
    radio_station:
      name: 'Kies radiostation'
      icon: mdi:radio
      initial: VRT Studio Brussel
      options:
        - VRT Radio 1
        - VRT Studio Brussel
        - "VRT Studio Brussel - #ikluisterbelgisch"
        - VRT MNM
        - VRT NWS
        - Topradio
        - Qmusic
        - Topradio
        - VBRO
        - Willy Radio

Lovelace dashboard

Add new card > Manual.

type: vertical-stack
cards:
  - type: custom:mini-media-player
    group: false
    artwork: cover
    source: full
    sound_mode: full
    info: short
    name: Living Room
    idle_view:
      when_idle: true
    entity: media_player.livingroom
  - type: entities
    entities:
      - entity: input_select.radio_station
        name: station
      - entity: script.play_radio
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.play_radio
  - type: entities
    entities:
      - entity: input_text.url
        name: URL
      - entity: script.play_media_url
        tap_action:
          action: call-service
          service: script.turn_on
          service_data:
            entity_id: script.play_media_url
        icon: mdi:play

Enjoy playing your favourite radio station on your smart speakers!