I have found that it is very desirable to have Indigo impersonate Alexa and speak as Alexa through Airfoil to one or more of the speakers in my home to make various Indigo generated announcements.
Amazon provides a service that they call Polly which provides the same text-to-speech capability they use for the Echo Alexa service. https://aws.amazon.com/polly/ The Polly service has a free tier that includes 5 million characters per month for speech or Speech Marks requests, for the first 12 months, starting from your first request for speech. There after it's $4 for every 1 million characters processed. I've never come close to that. You will need to create an Amazon account to access Polly. You can also use the free Polly demonstration web app at Amazon to make .mp3 audio announcement files that Indigo can play at no ongoing cost. https://us-east-2.console.aws.amazon.co ... sizeSpeech I use the mp3 solution for standard recurring announcements and the live real-time synthesis for complex announcements about the state of my home systems.
I have attached a modified version of Amazon's example code that works as an Indigo Python script. It converts text from a variable into Alexa's speech. I have been using it very reliably for more than a year.
More complex, and not at all essential:I also wanted the audio coming directly from my Alexa Dot's and the audio coming from my Airfoil Airport Express units in each room to play from the higher quality speakers in each of those those rooms--I breadboarded small simple passive audio mixers by cutting two-way stereo splitter cables and inserting 1k ohm resisters in the left and right audio paths of both of the two splitter cables to function as a combiner/mixer. Alexa's voice is indistinguishable regardless of which system is the source (Echo or Indigo) for speech of music sourced from either system.
Also, not essential; I wanted to be able to trigger certain Alexa routines from Indigo without needing a human to actually speak to Alexa to trigger the routines. [An example is telling Alexa to "resume music" once an hour to prevent playing background music from timing out. Also Indigo can request specific playlists with this mechanism.] I set up a special Dot (named House) whose audio output I have connected to the audio input of the Mac Mini that hosts Indigo and Airfoil. This House-Dot is the music source that plays announcements and music house-wide the through Airport Expresses in each designated room using Airfoil. To have the Indigo/Alexa tell Amazon/Alexa to do something, I placed a small amplified speaker adjacent to the HouseDot in a cabinet. Indigo/Alexa speaks to Amazon/Alexa by electing this speaker. Originally I used one of the Airport Expresses to do this. But to avoid having "self-talking commands disrupt Airfoil's music distribution I added a USB audio adapter (Sabrent USB External Stereo Sound Adapter) to the Mac Mini. By directing Indigo's synthesized or recorded Alexa commands this way (as show in the code example) schizophrenic Alexa can say to herself "Alexa, do this... " and expect it to happen.
Hope this solution works for any others who might find it useful. If There's sufficient interest perhaps someone with the necessary skills could convert it into a plugin.
Code: Select all
## Alexa Speaks Announcement Text In Variable Through Airfoil To House Speakers
import os, boto3, time ## Amazon's boto3 Python module must be installed on Mac
SpeakThis = indigo.variables[740708485].value
str (SpeakThis) ## assure the variable to be spoken is a string
## Settings taken from Amazon's sample Polly code
defaultRegion = 'us-east-1'
defaultUrl = 'https://polly.us-east-1.amazonaws.com'
indigo.actionGroup.execute(348168416) ## Enable Default Announce Airfoil House Speakers Volume Settings
indigo.actionGroup.execute(1112870329) ## Enable Airfoil For System Audio
time.sleep(3) ## Delay for Airfoil to set up speakers
## boto3 functions provided in Amazon's Polly example code
def connectToPolly(regionName=defaultRegion, endpointUrl=defaultUrl):
return boto3.client('polly', region_name=regionName, endpoint_url=endpointUrl)
def speak(polly, text, format='mp3', voice='Joanna'): ## Joanna is Alexa
resp = polly.synthesize_speech(OutputFormat=format, Text=text, VoiceId=voice)
soundfile = open('/tmp/sound.mp3', 'w')
soundBytes = resp['AudioStream'].read()
soundfile.write(soundBytes)
soundfile.close()
os.system('afplay /tmp/sound.mp3')
os.remove('/tmp/sound.mp3')
polly = connectToPolly()
speak(polly, str(SpeakThis))
time.sleep(2) ## Time required for processing and speaking
indigo.actionGroup.execute(278671718) ## Restore Current Speakers Saved Volume Levels & Connections
indigo.actionGroup.execute(1082305604) ## Enable Airfoil For Line-In Audio
Code: Select all
## Alexa Speaks To Alexa
import os, boto3, time ## Amazon's boto3 module must be installed on Mac
SpeakThis = indigo.variables["AlexaSaysThisVariable"].value
str (SpeakThis) ## Assure that the variable value to be spoken is a strig
defaultRegion = 'us-east-1' ## values assigned in Polly example code
defaultUrl = 'https://polly.us-east-1.amazonaws.com'
## the Python module "SwitchAudioSource" must be installed on the Mac
## to make use of the USB audio adapter
os.system("switchaudiosource -t output -s 'USB Audio Device'")
def connectToPolly(regionName=defaultRegion, endpointUrl=defaultUrl):
return boto3.client('polly', region_name=regionName, endpoint_url=endpointUrl)
def speak(polly, text, format='mp3', voice='Joanna'): ## Joanna is Alexa
resp = polly.synthesize_speech(OutputFormat=format, Text=text, VoiceId=voice)
soundfile = open('/tmp/sound.mp3', 'w')
soundBytes = resp['AudioStream'].read()
soundfile.write(soundBytes)
soundfile.close()
os.system('afplay /tmp/sound.mp3')
os.remove('/tmp/sound.mp3')
polly = connectToPolly()
speak(polly, str(SpeakThis))
time.sleep(2) ## Delay needed for Polly to process and speak
os.system("switchaudiosource -t output -s 'Built-in Output'")
Code: Select all
## Alexa Records mp3 Announcement From Text In Variable
import os, boto3, time ## Amazon's boto3 Python module must be installed on Mac
SpeakThis = indigo.variables["AlexaSaysThisVariable"].value
str (SpeakThis) ## assure the variable to be spoken is a string
## Settings taken from Amazon's sample Polly code
defaultRegion = 'us-east-1'
defaultUrl = 'https://polly.us-east-1.amazonaws.com'
newFileName = SpeakThis + ".mp3" # new file named with what is spoken
newFilePath = "/Users/bentley/AnnouncementRecordings/"+newFileName
indigo.server.log(unicode(newFilePath))
## boto3 functions provided in Amazon's Polly example code
def connectToPolly(regionName=defaultRegion, endpointUrl=defaultUrl):
return boto3.client('polly', region_name=regionName, endpoint_url=endpointUrl)
def speak(polly, text, format='mp3', voice='Joanna'): ## Joanna is Alexa
resp = polly.synthesize_speech(OutputFormat=format, Text=text, VoiceId=voice)
soundfile = open(newFilePath, 'w')
soundBytes = resp['AudioStream'].read()
soundfile.write(soundBytes)
soundfile.close() # New recordings left in Announcements Directory
os.system('afplay /newFilePath')
polly = connectToPolly()
speak(polly, str(SpeakThis))