Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to make script Python3.x compatible. #9

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 40 additions & 22 deletions alexa.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@
from respeaker import Microphone

from creds import Client_ID, Client_Secret, refresh_token
from respeaker.vad import vad
import time

import contextlib
import wave
from gpiozero import LED, Button
from signal import pause

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__file__)

if platform.machine() == 'mips':
mp3_player = 'madplay -o wave:- - | aplay -M'
else:
mp3_player = 'ffplay -autoexit -nodisp -loglevel quiet -'

# mp3_player = 'ffplay -autoexit -nodisp -loglevel quiet -'
mp3_player = 'mplayer -'

class Alexa:
"""
Expand Down Expand Up @@ -66,6 +73,7 @@ def generate(audio, boundary):
Returns:

"""
start_time = time.time()
logger.debug('Start sending speech to Alexa Voice Service')
chunk = '--%s\r\n' % boundary
chunk += (
Expand All @@ -92,24 +100,32 @@ def generate(audio, boundary):
}
}

yield chunk + json.dumps(d) + '\r\n'
yield (chunk + json.dumps(d) + '\r\n').encode()

chunk = '--%s\r\n' % boundary
chunk += (
'Content-Disposition: form-data; name="audio"\r\n'
'Content-Type: audio/L16; rate=16000; channels=1\r\n\r\n'
)

yield chunk
yield chunk.encode()

for a in audio:
yield a
with contextlib.closing(wave.open('recording.wav', 'wb')) as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(16000)
for a in audio:
wf.writeframes(a)
yield a

yield '--%s--\r\n' % boundary
yield ('--%s--\r\n' % boundary).encode()
print("Finished sending data to AVS")
print("Time spent recording audio: " + str(time.time() - start_time))
logger.debug('Finished sending speech to Alexa Voice Service')

@staticmethod
def pack(audio, boundary):
print('Start sending speech to Alexa Voice Service')
logger.debug('Start sending speech to Alexa Voice Service')
body = '--%s\r\n' % boundary
body += (
Expand Down Expand Up @@ -150,7 +166,9 @@ def pack(audio, boundary):

return body

def recognize(self, audio):
def recognize(self):
print('Button pressed!')
audio = self.mic.listen(duration=3)
url = 'https://access-alexa-na.amazon.com/v1/avs/speechrecognizer/recognize'
boundary = 'this-is-a-boundary'
if isinstance(audio, types.GeneratorType):
Expand All @@ -167,24 +185,31 @@ def recognize(self, audio):
}
data = self.pack(audio, boundary)

start_time = time.time()
r = self.session.post(url, headers=headers, data=data, timeout=20)
response_waiting_time = time.time() - start_time
print("Time Alexa request took: " + str(response_waiting_time))
self.process_response(r)

def process_response(self, response):
logger.debug("Processing Request Response...")
print("Processing Request Response...")

if response.status_code == 200:
data = "Content-Type: " + response.headers['content-type'] + '\r\n\r\n' + response.content
msg = email.message_from_string(data)
data = b"Content-Type: " + response.headers['content-type'].encode('utf-8') + b'\r\n\r\n' + response.content
msg = email.message_from_bytes(data)
for payload in msg.get_payload():
if payload.get_content_type() == "application/json":
j = json.loads(payload.get_payload())
logger.debug("JSON String Returned: %s", json.dumps(j, indent=2))
elif payload.get_content_type() == "audio/mpeg":
logger.debug('Play ' + payload.get('Content-ID').strip("<>"))

f = open(payload.get('Content-ID').strip("<>")+'.wav', 'wb')
f.write(payload.get_payload(decode=True))
f.close()
p = subprocess.Popen(mp3_player, stdin=subprocess.PIPE, shell=True)
p.stdin.write(payload.get_payload())
p.stdin.write(payload.get_payload(decode=True))
p.stdin.close()
p.wait()
else:
Expand All @@ -198,6 +223,7 @@ def process_response(self, response):
for directive in j['messageBody']['directives']:
if directive['namespace'] == 'SpeechSynthesizer':
if directive['name'] == 'speak':
print("SpeechSynthesizer audio: " + directive['payload']['audioContent'].lstrip('cid:'))
logger.debug(
"SpeechSynthesizer audio: " + directive['payload']['audioContent'].lstrip('cid:'))
elif directive['namespace'] == 'SpeechRecognizer':
Expand Down Expand Up @@ -241,19 +267,11 @@ def on_quit(signum, frame):
quit_event.set()

signal.signal(signal.SIGINT, on_quit)

while not quit_event.is_set():
if mic.wakeup(keyword='alexa'):
logging.debug('wakeup')
data = mic.listen()
try:
alexa.recognize(data)
except Exception as e:
logging.warn(e.message)

right_button = Button(3)
right_button.when_pressed = alexa.recognize
pause()
mic.close()
logging.debug('Mission completed')


if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion auth_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def index(self):
raise cherrypy.HTTPRedirect(p.url)

def authresponse(self, var=None, **params):
code = urllib.quote(cherrypy.request.params['code'])
code = urllib.parse.quote(cherrypy.request.params['code'])
callback = cherrypy.url()
payload = {"client_id": Client_ID, "client_secret": Client_Secret, "code": code,
"grant_type": "authorization_code", "redirect_uri": callback}
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ requests>=2.4.3
CherryPy>=4.0.0
webrtcvad
pocketsphinx
respeaker>=0.4.0
respeaker>=0.4.0
gpiozero==1.3.2