Background music: play random music tracks on chromecast

I’ve put together a system for automating music for our reception area. The idea is that it will automatically play music between certain hours. If anyone working at our business wants to they can manually cast whatever music they like, but if that stops, it will revert to a random selection of local music.
Part 1: python shuffle script

#!/usr/bin/env python3

import random, sys, os

nl = ['\n', '\r']

mediafiles = sys.stdin.readlines()

random.shuffle(mediafiles)

chosen = mediafiles[0]
while chosen[-1] in nl:
    chosen=chosen[:-1]

print (chosen)

Part 2: MQTT publish random track selection:
(I run this script once a minute with cron)

#!/bin/bash

directory=`ls /var/www/html/media/ | /usr/local/bin/random_mediafile` #Pipes media directories to the shuffle script
filename=`ls /var/www/html/media/"${directory}"/ | /usr/local/bin/random_mediafile` #Pipes media files from the randomly chosen directory to the shuffle script, returns one file

mosquitto_pub  -h mosquitto.local -t stat/server/currentsong -m "{\"FILENAME\": \"${filename}\",\"DIRECTORY\": \"${directory}\"}" &

Part 3: sensor configuration

  - platform: mqtt
    name: 'Current music'
    value_template: "{{value_json.FILENAME}}"
    json_attributes_topic: "stat/server/currentsong"
    state_topic: "stat/server/currentsong"

Part 4: script to play song

chromecast_music_playlist:
  alias: "Play a song at random from available songs"
  sequence:
    - service: media_player.play_media
      data_template:
        entity_id:
          - media_player.music #The chromecast device
        media_content_id: "http://LOCAL_MEDIASERVER/media/{{ state_attr('sensor.current_music','DIRECTORY') }}/{{ state_attr('sensor.current_music','FILENAME') }}"
        media_content_type: "audio"

Part 5: automations

- id: continue_music
  alias: "Continue music if stops"
  trigger:
  - platform: state
    entity_id: media_player.music
    to: 'off'
    for:
      seconds: 4
  - platform: state
    entity_id: media_player.music
    to: 'idle'
    for:
      seconds: 4
  - platform: state
    entity_id: input_boolean.reception_music
    to: 'on'
  condition:
  - condition: state
    entity_id: input_boolean.reception_music
    state: 'on'
  - condition: or
    conditions:
    - condition: state
      entity_id: media_player.music
      state: 'idle'
    - condition: state
      entity_id: media_player.music
      state: 'off'
    - condition: state
      entity_id: media_player.music
      state: 'paused'
  action:
  - service: script.chromecast_music_playlist
- id: marantz_on
  alias: "Turn on amplifier when chromecast audio in use"
  trigger:
  - platform: state
    entity_id: media_player.music
    to: 'playing'
  action:
  - service: media_player.turn_on
    data:
      entity_id: media_player.denon_avr
- id: marantz_off
  alias: "Turn off amplifier when chromecast audio idle"
  trigger:
  - platform: state
    entity_id: media_player.music
    to: 'off'
    for:
      seconds: 45
  - platform: state
    entity_id: media_player.music
    to: 'idle'
    for:
      seconds: 45
  action:
  - service: media_player.turn_off
    data:
      entity_id: media_player.denon_avr

Now all you need to do is create whatever conditions that control the reception_music input boolean. Whenever that turns on, it will trigger music to start. When turned off, no further tracks will play after the currently playing track. Personally I’ve set up an automation to turn on the boolean when I arrive at my workplace and off when I leave.

One irritation is the long (4 second) wait. This was necessary to enable casting other content. When that time was shorter, attempts to cast something else would fail because the script would take back over. I can probably come up with a way to improve that aspect.

3 Likes