Play Random Media Script w/ Shuffle, Repeat, Multi-room, Volume support

This script blueprint provides an easy to way play media from a set of content. A list of media is sent in and one is randomly chosen to play. The following field parameters can be given when the script is called:

  • [required] Primary media player
  • [required] List of content IDs (typically URLs) where one will randomly be chosen to play
  • [required] Content type of the media to play (defaults to music)
  • [optional] List of additional media players (to group together for a multi-room setup, e.g. Sonos)
  • [optional] Volume (it is applied to all grouped players)
  • [optional] Shuffle
  • [optional] Repeat

The script also has a few fail safes based on observed behaviour including:

  • Double checking that shuffle and repeat actually get set and if not, set again
  • If shuffle didnā€™t get set the script also forces skipping to the next song so you donā€™t always hear the first song in an album or playlist

This script is particularly convenient when:

  • You want to set a sleep timer but donā€™t want the same music each night
  • You have a set of playlists you frequently listen to but like to mix it up

Additional Notes

  • I recommend setting the mode to parallel when using the same script for multiple automations
  • This blueprint is very similar to my play_media script, except it takes a list of content ids instead of one
  • This blueprint has no inputs, but is meant to be a script called from automations
    Ā 

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

# ***************************************************************************
# *  Copyright 2022 Joseph Molnar
# *
# *  Licensed under the Apache License, Version 2.0 (the "License");
# *  you may not use this file except in compliance with the License.
# *  You may obtain a copy of the License at
# *
# *      http://www.apache.org/licenses/LICENSE-2.0
# *
# *  Unless required by applicable law or agreed to in writing, software
# *  distributed under the License is distributed on an "AS IS" BASIS,
# *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# *  See the License for the specific language governing permissions and
# *  limitations under the License.
# ***************************************************************************

# Plays media, randomly chosen from the list given, on the specified devices with various options for shuffle, repeat, etc.

blueprint:
  name: "Play Random Media"
  description:
    "This blueprint is used to add a script for playing media. The script randomly chooses which media
    to use from the list given and provides shuffle, repeat and volume options. \
    If you have a multi-room setup (e.g. Sonos) additional media players can be specified. The players \
    will be grouped together with the primary media player."
  domain: script

fields:
  media_content_ids:
    name: "Content IDs"
    description: "The list of IDs and one will be randomly chosen to play"
    example: "https://open.spotify.com/playlist/37i9dQZF1DX4fQhfyVRsHW"
    required: true
    selector:
      object:
  media_content_type:
    name: "Content Type"
    description: "The type of content that will play. Platform dependent."
    example: "music"
    required: true
    selector:
      text:
  entity_id:
    description: "The entity id that will be used to play and control the specified media."
    name: "Entity"
    required: true
    selector:
      entity:
        domain: media_player
  group_members:
    description: "The entity ids of the additional entities to group together in a multi-room system. This ignores all types but entity ids."
    name: "Group Members"
    required: false
    selector:
      target:
        entity:
          domain: media_player
  shuffle:
    name: "Shuffle"
    description: "True/false for enabling/disabling shuffle. If not set, current setting is used."
    required: false
    selector:
      boolean: null
  repeat:
    name: "Repeat Mode"
    description: "Repeat mode set to off, all, one. If not set, current mode is used."
    required: false
    selector:
      select:
        options:
          - "off"
          - "all"
          - "one"
  volume_level:
    name: "Volume Level"
    description: "Float for volume level. Range 0..1. If a value isn't given, volume isn't changed. If you specified Group Members the volume will be applied to all members."
    required: false
    selector:
      number:
        min: 0
        max: 1
        step: 0.01
        mode: slider

variables:
  # we put this here so we can easily see what was chosen and was seeing some
  # oddities when put directly in the call itself
  media_content_id: >-
    {% if media_content_ids is string %}
      {{media_content_ids}}
    {% elif media_content_ids is mapping %}
      "dictionary object isn't support"
    {% elif media_content_ids is iterable %} 
      {{ media_content_ids | random }}
    {% else %}
      "specified object isn't support"
    {% endif %}

sequence:
  # if group members are defined then we do a grouping
  - choose:
      - conditions: >
          {{ group_members is defined }}
        sequence:
          - service: media_player.join
            data:
              group_members: >-
                {# can't modify a list or reset a variable, so using a replaceable array in a mutable container as work around#}
                {# we only uses entity_id, and there will only be one given it is a dictionary #}
                {# but in the future we can look at converting areas and devices into entities #}
                {%- set workaround = namespace(members = []) -%}
                {%- for key in group_members if key == 'entity_id'-%} 
                  {%- set workaround.members = group_members[key] -%}
                {%- endfor -%} 
                {{ workaround.members }}
              entity_id: "{{ entity_id }}"

  # we only set repeat if the repeat value was given
  - choose:
      - conditions: >
          {{ repeat is defined }}
        sequence:
          - service: media_player.repeat_set
            data:
              repeat: "{{ repeat }}"
              entity_id: "{{ entity_id }}"
    default: []

  # it appears that if you set shuffle and repeat
  # that both do not happen all the time (at least
  # on Sonos), so delay is here to help
  - choose:
      - conditions: >
          {{ repeat is defined and shuffle is defined }}
        sequence:
          - delay:
              hours: 0
              minutes: 0
              seconds: 1
              milliseconds: 0
    default: []

  # we only set shuffle if the shuffle value was given
  - choose:
      - conditions: >
          {{ shuffle is defined }}
        sequence:
          - service: media_player.shuffle_set
            data:
              shuffle: "{{ shuffle }}"
              entity_id: "{{ entity_id }}"
    default: []

  # we only set the volume if the volume value was given
  - choose:
      - conditions: >
          {{ volume_level is defined }}
        sequence:
          - service: media_player.volume_set
            data:
              volume_level: "{{ volume_level }}"
              entity_id: "{{ entity_id }}"
          - choose:
              # if we have additional members, we set all their volumes
              - conditions: >
                  {{ group_members is defined }}
                sequence:
                  # need to make the right target definition
                  - service: media_player.volume_set
                    data:
                      volume_level: "{{ volume_level }}"
                    target: >-
                      {{ group_members }}
            default: []
    default: []

  # no matter what, we get the media playing
  # assuming we have the right media type
  - service: media_player.play_media
    data:
      media_content_id: "{{ media_content_id }}"
      media_content_type: "{{ media_content_type }}"
      entity_id: "{{ entity_id }}"

  # now we double check shuffle state and set
  # again because sometimes it doesn't take
  - choose:
      - conditions: >
          {{ shuffle is defined and is_state_attr(entity_id, 'shuffle', shuffle) == false }}
        sequence:
          - service: media_player.shuffle_set
            data:
              shuffle: "{{ shuffle }}"
              entity_id: "{{ entity_id }}"
          # in this case we wil also force the next
          # track just to be sure
          - choose:
              - conditions: >
                  {{ shuffle == true }}
                sequence:
                  - service: media_player.media_next_track
                    data:
                      entity_id: "{{ entity_id }}"
            default: []
    default: []

  # now we double check repeat state and set
  # again because sometimes it doesn't take
  - choose:
      - conditions: >
          {{ repeat is defined and is_state_attr(entity_id, 'repeat', repeat) == false }}
        sequence:
          - service: media_player.repeat_set
            data:
              repeat: "{{ repeat }}"
              entity_id: "{{ entity_id }}"
    default: []

mode: parallel
max_exceeded: silent
icon: mdi:music-box-multiple-outline

Revisions

  • 2022-11-06: Fixed issue with radio stations not working due to string quote handling in the media content id
  • 2022-04-24: Initial release

Available Blueprints

1 Like

As mentioned above, this is exceptionally similar to my previous play media blueprint, except it takes a list of media content ids and will choose one randomly to play when the script is invoked. I posted this now because Iā€™m about to post another automation blueprint that has a dependency on this particular script.

Hi

for some reason when i import the script and try to create the scrpt using the blueprint the gui does not show any inputs. so i cant figure out how to input the required parameters to get the script to work

please let me know if im missing anything

thanks

AR

Hi Ariel,

I have the same issue. Iā€™m eager to use this blueprint but I canā€™t find how to make it work.

I also get the message ā€œThis blueprint doesnā€™t have any inputs.ā€

Hopefully @Talvish or someone can help point us in the right direction. It looks like an awesome blueprint if we can get it to work.

Cheers

i am looking for this HA function for a long time. i want to trigger this script via a nfc tag for my child as a good night story from spotify. i do not get this script to workā€¦ i need a little bit help

Hey @Todzjoe , it the script not working for you? Any particular error you can share?

Hey @Borto and @a.ramos ,

Sorry for the large delay. If by input you mean that no inputs are set when you create the script from the blueprint, that is correct. Instead, the values are set when you call the script from your automation.

Iā€™ll update the text shown when creating a script to indicate all values are set when you call the script (right now it only says there are no inputs).

Just in case, here is an example of calling the script from the Developer Tools / Services tool.

Iā€™ve been playing around with radio stations on Sonos and found what appears to be a quote issue that doesnā€™t impact other services like Spotify. Iā€™ve updated this script with the fix.

Hey @Todzjoe, I didnā€™t hear back from you but I just posted a fix related to quotes showing up and interfering with radio station playback. The fix may help other channels so I thought Iā€™d ping you. Hopefully this helps or you are already in a good spot.

@Talvish , how do I specify multiple playlists? I tried this:

action:
  - service: script.play_random_playlist_sonos
    data:
      media_content_ids: >-
        https://open.spotify.com/playlist/exampleplaylist1
        https://open.spotify.com/playlist/exampleplaylist2
      entity_id: media_player.sonos

ā€¦ but it always seems to play from the latest entry in the media content ids list, exampleplaylist2, never list 1. How do I format this correctly? Thanks!

Thank you for this blueprint. i have the same issue as @richair777 with songs. Always the last song is played. Is this a bug or do I need to adapt the code?

Thanks

Try this:

service: script.play_random_media
data:
  media_content_type: music
  entity_id: media_player.[yourmediaplayer]
  shuffle: true
  media_content_ids:
    - https://open.spotify.com/playlist/[exampleplaylistId1]
    - https://open.spotify.com/playlist/[exampleplaylistId2]

Thanks, but that does not work unfortunately. Or do I need to change the url?

My code is:

service: script.play_random_begin_de_dag_song_on_spotifydata: entity_id: media_player.sonos repeat: "off" media_content_type: track shuffle: true media_content_ids: >- spotify://e885bd14859e6990e290d3e209af3213/spotify:track:6ExlwDMSghJwO31tnCYebQ >- spotify://e885bd14859e6990e290d3e209af3213/spotify:track:4Z5uVUyOK4lehbsiWXvZbZ >- spotify://e885bd14859e6990e290d3e209af3213/spotify:track:6F77hFiGFvITsx22B5GYgD

Iā€™ve edited my response above to make it clearer. Basically the idea is that you separate the playlists on new lines with a dash and a space preceding them. They may also be auto-formatted afterwards adding the ā€œ- >-ā€œ before a new line, which I had alluded to before my edit. As for whether it needs to be a https URL or a Spotify URL, Iā€™ve only used https but Iā€™d suggest that since ā€˜somethingā€™ plays when using the Spotify URL then it likely doesnā€™t matter. Hope this helps.

1 Like

Iā€™ve edited my response above to make it clearer. Basically the idea is that you separate the playlists on new lines with a dash and a space preceding them. They may also be auto-formatted afterwards adding the ā€œ- >-ā€œ before a new line, which I had alluded to before my edit. As for whether it needs to be a https URL or a Spotify URL, Iā€™ve only used https but Iā€™d suggest that since ā€˜somethingā€™ plays when using the Spotify URL then it likely doesnā€™t matter. Hope this helps.

This did the trick. Thank you so much. It is really powerful to have multiple playlists being played randomly. Thank you for your blueprint.

The blueprint is all @Talvish but glad I could help you out with the syntax :slightly_smiling_face:

Oops, sorry @Talvish , I overlooked you. Credit to you for the blueprint, and thank you @bungamungus for your reply.

Iā€™ve got a parrot in my living room near a Google Home speaker and Iā€™m interested in using something like this to play random MP3 files with bird sounds (and maybe R2D2 beeps?) for him throughout the day. If I have them in the Home Assistant media storage how would I go about getting those content ids for the script input?

Edit: Nevermind found the answer myself. You just need to use the media-source:// url that matches the path to the files like this:
media-source://media_source/local/bird/r2d2-sounds-1.mp3

Edit 2: Looks like I spoke too soon, I still had the ā€œplay mediaā€ action still in my automation and that worked, putting that media source url in the script did not. I get Entity media_player.living_room_speaker does not support this service.

Hi @Talvish , After import blueprint to HA. I canā€™t find your script service on the Developer Tools / Services tool. I have tried reboot system without succesfull.
And If I create script from Blueprint, not only there are no inputs options but also have Response error: 500
Do I need to add any config to HA to display this service script ? Thanks

Hi @Talvish - is this intended for Sonos only? Im trying to also get this working with Google home and im getting the error:

master_bedroom_speaker does not support this service.

1 Like