Random Audiobook on MPD
from kekskurse at 2025-07-03 20:43:01 +0200 +0200
I want the Zigbee light switch attached directly to the headboard of my bed to play a random Sherlock Holmes or Three Investigators episode when pressed and held. To do this, I first need to write a Python script that connects to my MPD and retrieves a list of all possible audiobooks, then selects one at random and plays it. The script then needs to be made available on the Pi running Home Assistant and linked to the button.
Setup Homeassistant
I run Homeassistant inside a Docker container. Therefor i need to mount the folder with the python script inside the container. I use the /opt directly in this setup
services:
homeassistant:
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- /opt/:/opt/root
...
after that i could make the script visible to homeassistant by adding the following content to my configuration.yaml:
shell_command:
hoerbuch: python3 /opt/root/randomhoerbuch
Than i used the Homeassistant GUI to create an automation which run the script on the hold action of the button:
alias: Button Bed Long
description: ""
trigger:
- platform: device
domain: mqtt
device_id: cdb815a53346bc4bca446b097a2da234
type: action
subtype: hold
discovery_id: 0x00158d00027d83ba action_hold
condition: []
action:
- service: shell_command.hoerbuch
data: {}
mode: single
Python code
#!/bin/python3
import random
from mpd import MPDClient
# Konfigurierbare Einstellungen
MPD_HOST = "192.168.1.101"
MPD_PORT = 6600
MPD_PASSWORD = None # oder z.B. "meinPasswort"
ALBUM_ARTISTS = ["Sherlock Holms - Aus den Tagebüchern"] # Beispielkünstler
def connect_to_mpd():
client = MPDClient()
client.timeout = 10
client.idletimeout = None
client.connect(MPD_HOST, MPD_PORT)
if MPD_PASSWORD:
client.password(MPD_PASSWORD)
return client
def get_albums_by_artist(client, artist):
albums = client.list("album", "albumartist", artist)
return [album for album in albums if album]
def get_songs_from_album(client, artist, album):
# Versuche zuerst mit albumartist
songs = client.find("albumartist", artist, "album", album)
if not songs:
# Fallback auf artist, falls albumartist nicht funktioniert
songs = client.find("artist", artist, "album", album)
print(f"Keine Songs gefunden für:\nArtist: {artist}\nAlbum: {album}")
return songs
def main():
client = connect_to_mpd()
# Alle Alben sammeln
artist_album_map = {}
for artist in ALBUM_ARTISTS:
albums = get_albums_by_artist(client, artist)
if albums:
artist_album_map[artist] = albums
# Zufällig Künstler und Album wählen
if not artist_album_map:
print("Keine Alben gefunden.")
return
artist = random.choice(list(artist_album_map.keys()))
album_entry = random.choice(artist_album_map[artist])
album = album_entry["album"] if isinstance(album_entry, dict) else album_entry
print(f"Spiele zufälliges Album:\nKünstler: {artist}\nAlbum: {album}")
# Songs holen und abspielen
songs = get_songs_from_album(client, artist, album)
client.clear()
for song in songs:
client.add(song["file"])
client.play()
client.close()
client.disconnect()
if __name__ == "__main__":
main()
Versionshistorie
- radio and mpd random audiobook script from kekskurse at 2025-07-03 20:43:01 +0200 +0200