One answer from my side was still missing. The script works on my pimatic system as well. The mp3 must be in the same directory as the script and the script must be manually aborted. After the mp3 was play it command line is is busy. I must press crtl+c
.
-
Let Google Home say "Hello"!
-
Ok, thats how its been build.
If you want i can stop the program after the play and leave out the Friendly name -
No its fine. Need some simple playground for the start…
-
hi, you can test a first version of pimatic-sounds (v0.0.8).
The plugin lets you speak a text or play a mp3 file to a chromecast device.
The minimum node requirement is v8.You control it via a rule. The action syntax is:
play [text | file | stop] [“test text for tts” | “filename”] vol [0-100] on [SoundsDevice]
The 3 typical use cases are:
- play text “this is a nice text” vol 50 on mychromecast
- play file “nice-music.mp3” vol 25 on mychromecast
- play stop mychromecast
The mp3 filename may not contain spaces and the mp3’s must be placed in a folder ‘sounds’ in the home directory of Pimatic (mostly /home/pi/pimatic-app
Read the README for details
-
Hi, have installed it.
Installation went fine, but when I want to create a device I get an error that the node-gtts module is missing.
-
Ah, thats a dependency i have missed to put in the package. You could install it in de pimatic-sounds directory. Npm install node-gtts
I can’t update the plugin for the next hours -
This post is deleted!
-
Hi, yepp I had a look in the package.json. After installtion the package it works.
Good that you called the plugin “sound”. So you can add stuff like sonos… in the future. :D
I running the sonos-api since two years. It works (with some additionals I had to do to resume music after tts or sound play), but I for my part don’t like to use sonos for tts and play simple sound anymore. The google speaker are small and really cheap, so it can be placed it simply everywhere.BTT: Seems nobody knows how to handle the problem with the python script? See first post . I will continue to work on the problem…
-
I got it to running. I need to do some tests and then I will provide it here.
Current functions are:
- Get current volume
- Set volume
- play TTS {volume}
- play MP3 {volume}
- show picture (jpg).
Not yet implemented- play video (can be done easy, but I don’t need it)
.
Currently I am working on it to make it even faster. Current time to cast the medium need 2-3s. I thing this can be easy improved. But my time is currently limited… Stay tuned! -
Here is the script. Sorry for comments in german.
Only this block needs to be changed.
findeIP = { "tablet": "192.168.xxx.xxx", "ghubWZ": "192.168.xxx.xxx, "miBox" : "192.168.xxx.xxx", } webSerAddr = "192.168.xxx.xxx" webSerPort = xxxx saveMP3 = "/home/user/folder/_subfolder/" klingelTon = "someNiceRing.mp3" bildAnzeigeZeit = 10
#! /usr/bin/python3 # # ------------------------------------------------------------------------------ # Skript dient zur Steuerung / Ausgabe von Chromecast Geräten (TTS, Ton, Bild) # # ghLS modus option [lautstärke] # | | | | # Aufruf: sh /home/user/googleHomeControl.py <gh> # Aufruf: sh /home/user/googleHomeControl.py <gh> <vol> # Aufruf: sh /home/user/googleHomeControl.py <gh> <status> # Aufruf: sh /home/user/googleHomeControl.py <gh> <klingel> [<vol>] # Aufruf: sh /home/user/googleHomeControl.py <gh> <tts> <text> [<vol>] # Aufruf: sh /home/user/googleHomeControl.py <gh> <bild> # ------------------------------------------------------------------------------ # Import Bibliotheken #--------------------------------------------------------------------------------------------------- import os import signal import sys import time #import threading #import pychromecast #import requests #--------------------------------------------------------------------------------------------------- # Variablendeklaration #--------------------------------------------------------------------------------------------------- findeIP = { "tablet" : "192.168.xxx.xxx", "ghubWZ" : "192.168.xxx.xxx, "miBox" : "192.168.xxx.xxx", } webSerAddr = "192.168.xxx.xxx" webSerPort = xxxx saveMP3 = "/home/user/folder/_subfolder/" klingelTon = "someNiceRing.mp3" bildAnzeigeZeit = 10 #--------------------------------- vol = -1 volAktuell = -1 volSoll = -1 volPlay = -1 modus = "" datei = "" text = "" castdevice = "" #--------------------------------------------------------------------------------------------------- # Webserver erzeugen #--------------------------------------------------------------------------------------------------- def createWebSrv(option): import http.server import socketserver import requests webSerUrl = "http://" + webSerAddr + ":" + str(webSerPort) psIDwebSrv = os.popen("ps ax | grep 'googleHomeControl.py server start' | grep -v 'grep' | grep -v 'sh -c' | cut -c 1-5") psIDwebSrv = psIDwebSrv.read() # Falls <option> STATUS if option == "status": try: request = requests.get(webSerUrl) if request.status_code == 200: print("\nWebserver LÄUFT bereits: " + webSerUrl) print("ProzessID des Webservers: " + psIDwebSrv) except requests.exceptions.ConnectionError: print("\nWebserver läuft NICHT !\n") # Falls <option> START if option == "start": try: request = requests.get(webSerUrl) if request.status_code == 200: print("\nWebserver LÄUFT bereits: " + webSerUrl) except requests.exceptions.ConnectionError: os.chdir(saveMP3) Handler = http.server.SimpleHTTPRequestHandler httpd = socketserver.TCPServer(('', webSerPort), Handler) print("\nWebserver JETZT erreichbar: " + webSerUrl) httpd.serve_forever() # Falls <option> STOP if option == "stop": try: request = requests.get(webSerUrl) if request.status_code == 200: # httpd.shutdown() # httpd.server_close() print("\nProzessID des Webservers: " + psIDwebSrv) print("Webserver wird beendet . . .\n") os.kill(int(psIDwebSrv), signal.SIGKILL) except requests.exceptions.ConnectionError: print("\nWebserver LÄUFT NICHT, nix zum beenden da !\n") exit() #--------------------------------------------------------------------------------------------------- # Lautstärke einstellen #--------------------------------------------------------------------------------------------------- def setVOL(vol): global volAktuell # lokale Variable <volAktuell> global beschreiben volAktuell = castdevice.status.volume_level # <volAktuell> mit aktueller Lautstärke definieren (global verfügbar) print("Lautstärke IST: " + str(round(volAktuell*100))) global volSoll # lokale Variable <volSoll> global beschreiben volSoll = vol # <volSoll> mit übergebener Lautstärke definieren (global verfügbar) # Wenn valide Lautstärke (0-100) übergeben, dann Lautstärke setzen if vol != -1: castdevice.set_volume(float(volSoll)/100) time.sleep(0.25) global volPlay # lokale Variable <volPlay> global beschreiben volPlay=castdevice.status.volume_level # <volPlay> mit gesetzter Lautstärke definieren (global verfügbar) print("Lautstärke SOLL: " + str(round(volPlay * 100))) # time.sleep(0.25) #--------------------------------------------------------------------------------------------------- # TTS erzeugen #--------------------------------------------------------------------------------------------------- def createTTS(text): from gtts import gTTS # import hashlib global datei datei = text + ".mp3" # Erzeuge Dateinamen aus übergebenem Text # datei = hashlib.md5(text.encode()).hexdigest()+".mp3" # Erzeuge MD5 Dateinamen für Caching # Erzeuge Pfad für MP3 Ablage, falls nicht vorhanden try: os.mkdir(saveMP3 + modus) except: pass # Prüfen ob Dateiname bereits existiert if not os.path.isfile(saveMP3 + modus + "/" + datei): tts = gTTS(text, lang='de') # text2speech erzeugen tts.save(saveMP3 + modus + "/" + datei) # tts stream in Datei mit dem Namen <text>.mp3 speichern #--------------------------------------------------------------------------------------------------- # Media abspielen #--------------------------------------------------------------------------------------------------- def castMedia(datei): # Erzeuge Objekt "mediaController" mediaController = castdevice.media_controller # Erzeuge URL aus Webserver Informationen und übergebenen Parametern url = "http://" + webSerAddr + ":" + str(webSerPort) + "/" + modus + "/" + datei # Deklariere URL & Medienformat für "mediaController" if modus == "bild": mediaController.play_media(url, "image/jpg") if modus != "bild": mediaController.play_media(url, "audio/mp3") # Blockiere "mediaController" für andere Ausgaben mediaController.block_until_active() # Falls KEIN BILD anzeigt wird, aktuelle Wiedergabe pausieren & übergebene Lautstärke setzen if modus != "bild": mediaController.pause() # time.sleep(0.25) time.sleep(0.5) # time.sleep(1.0) castdevice.set_volume(volPlay) time.sleep(0.25) # Übergebenes Medium wiedergeben mediaController.play() # Kommandozeilenausgabe abhängig von Medium if modus != "bild": print("Medium wird abgespielt . . .\n") while not mediaController.status.player_is_idle: # Notwendig um Töne abspielen zu können. Castvorgang wird sonst sofort abgebrochen! # time.sleep(1.0) time.sleep(0.5) if modus == "bild": for remaining in range(bildAnzeigeZeit - 1, -1, -1): sys.stdout.write("\r") sys.stdout.write("Medium wird abgespielt für {:2d}s . . .".format(remaining)) sys.stdout.flush() time.sleep(1) print("\n") # Castvorgang beenden mediaController.stop() castdevice.quit_app() # Lautstärke auf Eingangswert zurücksetzen, falls diuch Tonwiedergabe verändert if modus != "bild": castdevice.set_volume(volAktuell) # time.sleep(0.25) #--------------------------------------------------------------------------------------------------- # Methodenaufruf #--------------------------------------------------------------------------------------------------- ghome = sys.argv[1] # Falls "server" anstelle eines GH übergeben wird, dann Server Option ausführen if ghome == "server": option = sys.argv[2] createWebSrv(option) exit() # Ermittlung der IP durch übergebenen GH Namen ghomeIP = findeIP.get(sys.argv[1], "null") if ghomeIP == "null": print("Unbekanntes Chromecast Gerät ! ! !\n") exit() # Castdevice initialisieren import pychromecast castdevice = pychromecast.Chromecast(ghomeIP) castdevice.wait() # Nur Kommandozeilenausgabe relevant print() print() print("Datei: googleHomeControl.py") print("--------------------------------------------------------------------") ## Falls <modus> nicht übergeben wurde, dann exit # Falls <modus> nicht übergeben wurde, dann setVOL(-1) aufrufen (nur Lautstärke ausgeben) und exit try: modus = sys.argv[2] except: setVOL(-1) # exit() # Falls Nummer übergeben, dann Wert als Lautstärke setzen if (modus.isdigit()): vol = modus setVOL(vol) # exit() # Falls "status" übergeben, dann aktuelle Lautstärke zurückgeben if modus == "status": # !!!!!!!!!!!! HIER FEHLT NOCH WAS !!!!!!!!!!!! setVOL(-1) # exit() # Falls "klingel" übergeben, dann Audio MP3 in übergebener Lautstärke abspielen if modus == "klingel": # Optionaler Parameter > "Klingellautstärke" <vol>. Falls übergeben, dann Klingel in übergebener # Lautstärke ausgeben, ansonsten aktuelle Lautstärke beibehalten. try: vol = sys.argv[3] setVOL(vol) except: setVOL(-1) datei = klingelTon # Falls Text übergeben, dann Wert als TTS setzen if modus == "tts": try: text = sys.argv[3] except: print("Text fehlt!\n") exit() # Optionaler Parameter > "Ansagelautstärke" <vol>. Falls übergeben, dann Ansage in übergebener # Lautstärke ausgeben, ansonsten aktuelle Lautstärke beibehalten. try: vol = sys.argv[4] setVOL(vol) except: setVOL(-1) createTTS(text) # Falls "bild" übergeben, dann Bild auf Google Hub anzeigen if modus == "bild": try: datei = sys.argv[3] except: print("Bild fehlt!\n") # Verarbeitete Daten ausgeben print("GoogleHomeLS: " + ghome ) print("Modus: " + modus ) print("Text: " + text ) print("Datei: " + datei ) print("--------------------------------------------------------------------") print() #exit() # Medium an Chromecast Gerät senden if modus == "klingel" or modus == "tts" or modus == "bild": castMedia(datei) #--------------------------------------------------------------------------------------------------- exit()
It is still under construction. I realized groups via a shell script which is really specific for my home situation, so I will not help other user. If there is some interest, I can clean it from the specific stuff an provide it.