How to interrupt voice assistant in python - python

I am building a voice assistant that can tell stories. While the bot is telling stories I want to interrupt in between and ask it to stop or go backward or to end the story. I tried few ways, but they are not working I am not able to listen while it is speaking cause after the speaking part gets ended it goes to listening part.
Thanks in advance
Here is my code
while True:
r = sr.Recognizer()
with sr.Microphone() as source:
print("Talk")
audio_text = r.listen(source)
print("Time over, thanks")
try:
inp=r.recognize_google(audio_text, language = "en-IN")
print("Text: "+inp)
except:
inp="sorry"
print("Sorry, I did not get that")
if inp.lower() == "quit":
bot_voice("Ok bye see you later")
break
if inp.lower() == "sorry":
bot_voice("Sorry, I did not get that")
if (deter==0):
y=-1
deter=1
for x in stories:
m=x
y=m.find(inp)
if(y>-1):
filename = 'Stories/data/'+x+'.txt'
with open(filename) as f_in:
for line in f_in:
bot_voice(line)
break
else:
results = model.predict([bag_of_words(inp, words)])
results_index = numpy.argmax(results)
tag = labels[results_index]
for tg in data["intents"]:
if tg['tag'] == tag:
responses = tg['responses']
reply=random.choice(responses)
if(reply=='7417'):
filename = "Stories/list.txt"
bot_voice("I know quite a few stories, they are")
with open(filename) as f_in:
for x,line in enumerate(f_in):
bot_voice(line)
bot_voice("which one you want")
deter=0
else:
print("bot:",reply)
bot_voice(reply)

This isn't possible with the speech recognition you are using. This speech recognition takes input and doesn't provide output. With your output system, which I assume is something like pyttsx, would just read as it is told. You would require a stop system and you would need to do this with a machine learning-based program that is capable of conversations and can stop when told to stop and take keywords as commands.
I recommend Pytorch as a starter for Python Machine Learning. Here is an article on conversational AI.
Article on Conversational AI with Pytorch

Related

What is wrong with my "If Statement" in line 44 and my addition to variable statement in line 37?

I am currently making the rough outline for a voice controller so I can stop designing parts, but even while making the rough outline I ran into some issues with my rusty skill level in if statement and syntax of variable addition. The specific error is that the program exits out after the first time I ask the script how its doing rather than continuing to run like it should if I remove the line with the variable addition along with the chunk about the differed statement that replaces the old "how are you" after it being asked once.
from time import ctime
import time
import os
import pyttsx3
import random
repetitionsocial1=0
numberList = ["Thanks for asking. But I am a computer","222","I eat poop","444","555"]
def recordAudio():
# Record Audio
r = sr.Recognizer()
with sr.Microphone() as source:
print("Say something!")
audio = r.listen(source)
# Speech recognition using Google Speech Recognition
data = ""
try:
# Uses the default API key
# To use another API key: `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")`
data = r.recognize_google(audio)
print("You said: " + data)
except sr.UnknownValueError:
print("Offline Recognition could not understand audio")
except sr.RequestError as e:
print("Could not request results from Offline Recognition service; {0}".format(e))
return data
def jarvis(data):
global repetitionsocial1
if "how are you" in data and repetitionsocial1==0 :
repetitionsocial1=repetitionsocial1+1
engine = pyttsx3.init()
engine.say("What answer do you expect. I am a Computer?")
engine.runAndWait()
if "how are you" in data and repetitionsocial1>=0:
engine = pyttsx3.init()
engine.say("I am still fine, but again, I am a computer. You have asked me this"+str(repetitionsocial1)+"times")
engine.runAndWait()
if "what time is it" in data:
engine = pyttsx3.init()
engine.say(ctime())
engine.runAndWait()
# if "where is" in data:
# data = data.split(" ")
# location = data[2]
# speak("Hold on Frank, I will show you where " + location + " is.")
# os.system("chromium-browser https://www.google.nl/maps/place/" + location + "/&")
# initialization
time.sleep(2)
engine = pyttsx3.init()
engine.say("Hi Frank, what can I do for you?")
engine.runAndWait()
while 1:
data = recordAudio()
jarvis(data)
Look at these two snippets.
if "how are you" in data and repetitionsocial1==0 :
repetitionsocial1=repetitionsocial1+1
...
if "how are you" in data and repetitionsocial1>=0:
...
when the first condition is true, it adds 1 to repetitionsocial1, so now that variable contains 1. Therefore, the second condition will also be true, because 1>=0.
You should use elif when you have mutually exclusive conditions, and don't want to consider the variable changes that occurred as a result of the first condition.

Is it possible to always have a google cloud speech recognition/api listening for a keyword python

I am just starting out with python and the google speech api/speech recognition. I was wondering if it is possible to always have the speech api listening for a keyword and when it hears the keyword to process commands. Since there is a limit on how much free audio the google speech api can process, is this possible? So far I have code that looks like this, but once the api does not hear any speech for a certain amount of seconds(I think 4), it throws an error. In a final project, I'd like to get this to work on a raspberry pi 3.
import speech_recognition as sr
import speak
from time import ctime
import time
import sys
r = sr.Recognizer()
lang = 'en'
data = ''
nameCalled = 0
# Enable Microphone and use for audio input
# Speech recognition using Google Speech Recognition
def spk(text, lang):
speak.tts(text, lang)
def audioRecord():
try:
with sr.Microphone() as source:
#r.energy_threshold = 500
# Increase for less sensitivity, decrease for more
print('Listening...')
audio = r.listen(source)
#r.adjust_for_ambient_noise(source)
data = r.recognize_google(audio)
print('You said ' + data)
return data
except sr.UnknownValueError:
print('Google could not understand audio!')
except sr.RequestError as e:
print('Could not request results for GSR')
def brain(data):
global nameCalled
#^^Keep track to see if amber was called^^
global lang
#If amber was said, than the next command heard can be executed
if nameCalled == 0:
if 'Amber' in data:
nameCalled = 1
spk('Yes?', lang)
elif 'nothing' in data:
spk('Okay', lang)
sys.exit()
else:
return 'null'
#Once we hear amber, the next command spoken can be executed,
# if something goes wrong, just set the nameCalled variable to 0
#and restart the process
elif nameCalled == 1:
if 'what time is it' in data:
spk(ctime(), lang)
if 'nothing' in data:
spk('Okay', lang)
sys.exit()
nameCalled = 0
else:
nameCalled = 0
# initialization
spk('hello nick, what can I do for you today', lang)
while 1:
data = audioRecord()
brain(data)
Kitt.ai provides 'Snowboy', a hotword detection engine which serves that purpose. You may trigger the speech recognition after the hotword is detected and it's pretty accurate too and it exactly fits this use-case.
Best of all, it runs offline.
You can set your code to run, after getting triggered by the hotword.
Check it out:
https://snowboy.kitt.ai

Audio File Speech Recognition in Python - location of word in seconds

I've been experimenting with the python speech recognition library https://pypi.python.org/pypi/SpeechRecognition/
To read downloaded versions of the BBC shipping forecast. The clipping of those files from live radio to the iplayer are obviously automated and not very accurate - so usually there is some audio before the forecast itself starts - a trailer, or the end of the news. I don't need to be that accurate but I'd like to get speech recognition to recognise the phrase "and now the shipping forecast" (or just 'shipping' would do actually) and cut the file from there.
My code so far (adpated form an example) transcribes and audio file of the forecast and uses a formula (based on 200 words per minute) to predict where the word shipping comes, but it's not proving to be very accurate.
Is there a way of getting the actual 'frame' or second onset that pocketsphinx itself detected for that word? I can't find anything in the documentation. Anyone any ideas?
import speech_recognition as sr
AUDIO_FILE = path.join(path.dirname(path.realpath(__file__)), "test_short2.wav")
# use the audio file as the audio source
r = sr.Recognizer()
with sr.AudioFile(AUDIO_FILE) as source:
audio = r.record(source) # read the entire audio file
# recognize speech using Sphinx
try:
print "Sphinx thinks you said "
returnedSpeech = str(r.recognize_sphinx(audio))
wordsList = returnedSpeech.split()
print returnedSpeech
print "predicted loacation of start ", float(wordsList.index("shipping")) * 0.3
except sr.UnknownValueError:
print("Sphinx could not understand audio")
except sr.RequestError as e:
print("Sphinx error; {0}".format(e))
You need to use pocketsphinx API directly for such things. It is also highly recommended to read pocketsphinx documentation on keyword spotting.
You can spot for keyphrase as demonstrated in example:
config = Decoder.default_config()
config.set_string('-hmm', os.path.join(modeldir, 'en-us/en-us'))
config.set_string('-dict', os.path.join(modeldir, 'en-us/cmudict-en-us.dict'))
config.set_string('-keyphrase', 'shipping forecast')
config.set_float('-kws_threshold', 1e-30)
stream = open(os.path.join(datadir, "test_short2.wav"), "rb")
decoder = Decoder(config)
decoder.start_utt()
while True:
buf = stream.read(1024)
if buf:
decoder.process_raw(buf, False, False)
else:
break
if decoder.hyp() != None:
print ([(seg.word, seg.prob, seg.start_frame, seg.end_frame) for seg in decoder.seg()])
print ("Detected keyphrase, restarting search")
decoder.end_utt()
decoder.start_utt()

pyttsx produces no sound

I am just creating a chatbot in Python. It's working well but I want to add pyttsx to this chatbot so that it could speak its output.
My code is
import aiml
import sys
import pyttsx
engine = pyttsx.init()
# Create a Kernel object.
kern = aiml.Kernel()
brainLoaded = False
forceReload = False
while not brainLoaded:
if forceReload or (len(sys.argv) >= 2 and sys.argv[1] == "reload"):
kern.bootstrap(learnFiles="std-startup.xml", commands="load aiml b")
brainLoaded = True
kern.saveBrain("standard.brn")
else:
try:
kern.bootstrap(brainFile = "standard.brn")
brainLoaded = True
except:
forceReload = True
print "\nINTERACTIVE MODE (ctrl-c to exit)"
while(True):
hea = kern.respond(raw_input("> "))
print hea
engine.say (hea)
engine.runAndWait()
When I am running this code I am not hearing any voice but I can see chat on terminal. I want it to speak the response, too. What am I doing wrong?
engine.runAndWait is outside the while(True): loop, so it's unlikely to be played until the loop is interrupted.
If you move it into the loop, and and the sound is choppy, test the code below:
import pyttsx
engine = pyttsx.init()
engine.say("Oh, hello!")
My experience with pyttsx is that it needs to be fed short amounts of text, otherwise the text is interrupted. I'm not sure exactly why that is, but truncating the sentences yourself and saying several phrases should suit your purpose:
engine.say("It's nice to meet you.")
engine.say("I hope you are doing well.")
engine.say("Would you like to join us ")
engine.say ("tomorrow at eight for dinner?")
But you'd need to parse the text and truncate it in a way that would keep the message intact.

How to get Spotify current playing song in Python (Windows)?

I want to show the current playing song in Spotify on a 16x2 LCD.
I was thinking of connecting the LCD with my Arduino and then making a Python script that sends the current playing song of Spotify to the Arduino.
To get to the point, I'm looking for a way to get Spotify's current playing song in Python. (I'm using Windows 8.) I found some ways like dbus, but they were either for Linux or for Mac.
Thanks in advance! (And sorry for bad English grammar.)
I encountered the same issue, so I wrote a library to solve this issue. The library can be found at github: https://github.com/XanderMJ/spotilib. Keep in mind that this is still work in progress.
Just copy the file and place it in your Python/Lib directory.
import spotilib
spotilib.artist() #returns the artist of the current playing song
spotilib.song() #returns the song title of the current playing song
spotilib.artist() returns only the first artist. I started working on an other library spotimeta.py to solve this issue. However, this is not working at 100% yet.
import spotimeta
spotimeta.artists() #returns a list of all the collaborating artists of the track
If an error occurs, spotimeta.artists() will return only the first artist (found with spotilib.artist())
Hope this will help you (if still needed)!
The easiest way would probably be to scrobble the currently playing tracks from the Spotify client to a last.fm account and then use python to get it from there.
Last.fm allows you to get scrobbled tracks via their api with user.getRecentTracks which provides the nowplaying="true" attribute if a song is playing. It also provides some other useful things you may want for an external display like a link to the album art and last.fm page for the song.
Here's a quick example that takes a username and api key as cmd line arguments and fetches what is currently playing for that user using the requests library.
from time import sleep
import requests
import json
from pprint import pprint
import sys
def get_playing():
base_url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user='
user = sys.argv[1]
key = sys.argv[2]
r = requests.get(base_url+user+'&api_key='+key+'&format=json')
data = json.loads(r.text)
latest_track = data['recenttracks']['track'][0]
try:
if latest_track['#attr']['nowplaying'] == 'true':
artist = latest_track['artist']['#text']
song = latest_track['name']
album = latest_track['album']['#text']
print "\nNow Playing: {0} - {1}, from the album {2}.\n".format(artist, song, album)
except KeyError:
print '\nNothing playing...\n'
def main():
if len(sys.argv)<3:
print "\nError: Please provide a username and api key in the format of: 'scrobble.py username api_key\n"
else:
get_playing()
if __name__ == '__main__':
main()
In a quick test it does seem to take a minute or so to realize the track is no longer playing after pausing or exiting the Spotify client however.
Is there more than one pytify ?
This worked for me until today:
https://code.google.com/p/pytify/
Spotify has been updated, now song is not shown in windows title anymore.
They will bring the "feature" back:
https://community.spotify.com/t5/ideas/v2/ideapage/blog-id/ideaexchange/article-id/73238/page/2#comments
while True:
print("Welcome to the project, " + user_name['display_name'])
print("0 - Exit the console")
print("1 - Search for a Song")
user_input = int(input("Enter Your Choice: "))
if user_input == 1:
search_song = input("Enter the song name: ")
results = spotifyObject.search(search_song, 1, 0, "track")
songs_dict = results['tracks']
song_items = songs_dict['items']
song = song_items[0]['external_urls']['spotify']
webbrowser.open(song)
print('Song has opened in your browser.')
elif user_input == 0:
print("Good Bye, Have a great day!")
break
else:
print("Please enter valid user-input.")

Categories