Нам понадобится:
— Python 2.7
— библиотеки:
pyaudio
pycurl
pywin32
+ набор стандартных библиотек
— какой-либо аудиоконвертер поддерживающий flac и wav, а также работу из командной строки, я использовал этот.
Как это работает
Мы записываем аудиофайл, отправляем Google Voice-у, получаем ответ в виде:
{«status»:0,«id»:«5e34348f2887c7a3cc27dc3695ab4575-1»,«hypotheses»:[{«utterance»:«пример»,«confidence»:0.7581704}]},
и далее его обрабатываем, также научим компьютер «разговаривать», с помощью того-же Google Voice.
Начинаем
Для начала нам необходимо подключить все модули, чтобы потом к этому не возвращаться:
import time, pyaudio, wave, os, urllib,urllib2,pycurl,httplib,sys,win32api,win32con,string
from ctypes import *
Окей, теперь напишем функцию Talk, которая позволит компьютеру разговаривать с нами.
def Talk(text):
def downloadFile(url, fileName):
fp = open(fileName, "wb")
curl = pycurl.Curl()
curl.setopt(pycurl.URL, url)
curl.setopt(pycurl.WRITEDATA, fp)
curl.perform()
curl.close()
fp.close()
def getGoogleSpeechURL(phrase):
googleTranslateURL = "http://translate.google.com/translate_tts?tl=en&"
parameters = {'q': phrase}
data = urllib.urlencode(parameters)
googleTranslateURL = "%s%s" % (googleTranslateURL,data)
return googleTranslateURL
def speakSpeechFromText(phrase):
googleSpeechURL = getGoogleSpeechURL(phrase)
downloadFile(googleSpeechURL,"ans.mp3")#файл, полученный с сервера сохраняется под именем ans.mp3
speakSpeechFromText(text)
#используем кодеки, чтобы воспроизвести речь
winmm = windll.winmm
winmm.mciSendStringA('Open "ans.mp3" Type MPEGVideo Alias theMP3',0,0,0)
winmm.mciSendStringA('Play theMP3 Wait',0,0,0)
winmm.mciSendStringA("Close theMP3","",0,0)
В общем, получаем функцию Talk(text), которая соответственно «говорит» нам text.
Кодеки были единственным решением, которое позволило мне воспроизвести mp3 из Python.
Ах, да, еще Google общается с нами исключительно на английском (и воспринимает только англ.), т.к мне не удалось подружить Python и utf-8.
Запись
Следующий шаг — запись речи, которую будет обрабатывать Google. Смело копипастим:
def Record():
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("Recording...")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("Done recording.")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
Этот код находится на сайте pyaudio и я его оставил практически без изменений.
Но, вот и первая проблема, мы получили файл wav, а Google понимает flac… Непорядок.
Здесь нас выручит конверетер и модуль os:
def Convert():
print "Converting"
os.system('C:\Users\Егор\Desktop\Расширение\TotalAudioConverter\AudioConverter.exe C:\Users\Егор\Desktop\Расширение\output.wav C:\Users\Егор\Desktop\Расширение\output.flac')
print "Done"
Здесь поясню, мы указываем путь к установленному конвертеру, а затем в качестве параметров передаем сначала входной файл, затем выходной (пути указывать полностью).
Посылаем нашу запись на сервер
def Send():
global ANSWER
url = 'https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=en-EN'#Здесь можно выбрать язык
flac=open('output.flac',"rb").read()
header = {'Content-Type' : 'audio/x-flac; rate=16000'}
req = urllib2.Request(url, flac, header)
data = urllib2.urlopen(req)
a = data.read()
ANSWER = eval(a)
if ANSWER['status'] == 5:
print 'Sorry, I do not understand you.'
Talk('Sorry, I do not understand you.')
ANSWER = 0
else:
ANSWER = ANSWER['hypotheses'][0]['utterance']#Отбираем то что google нам ответил(можно иначе)
print ANSWER
os.remove('C:\Users\Егор\Desktop\Расширение\output.wav')#Удаляем ненужные записи
os.remove('C:\Users\Егор\Desktop\Расширение\output.flac')
return ANSWER
Обработка
Получив ответ, мы можем ее использовать. Здесь все зависит исключительно от вашей фантазии.
Просто приведу несколько примеров:
def Processing():
global ANSWER
if ANSWER == 0:
return 0
elif 'chrome' in ANSWER.lower():
os.system('C:\Users\Егор\AppData\Local\Google\Chrome\Application\chrome.exe')#Запускаем Google Chrome, если он услышал слово chrome)
elif 'skype' in ANSWER.lower():
os.system('C:\Users\Егор\Downloads\SkypePortable\SkypePortable.exe')#аналогично
elif 'cd rom' in ANSWER.lower() or 'cd-rom' in ANSWER.lower() or 'open d' in ANSWER.lower() or 'dvd' in ANSWER.lower() or 'dvd-rom' in ANSWER.lower() or 'dvd rom' in ANSWER.lower() or 'cdrom' in ANSWER.lower() or 'cd - rom' in ANSWER.lower():
winmm = windll.winmm
winmm.mciSendStringA("set cdaudio door open", "", 0,0)#Если слышит что- то связанное с dvd то открывает лоток дисковода
Также еще я добавил функцию, которая на указанное время останавливала выполнение программы, но там большой код и я не вижу смысла выкладывать его здесь, т.к польза от него стремится к нолю.
Запускаем
После того, как мы описали эти функции, добавим следующий код:
print 'Hi, what do you want?'
Talk('Hi, what do you want?')
Record()
Convert()
print ('Sending...')
Send()
print 'Done'
Processing()
while True:
ANSWER = None
#Talk('Done.')
print 'Do you want something else? (Your command\No)'
Talk('Do you want something else??')
Record()
Convert()
print 'Sending...'
Send()
print 'Done'
#print ANSWER
if ANSWER == 0:
continue
if ANSWER.lower()== 'no' or\#Если ответили нет, завершаем программу
ANSWER.lower()== 'nope' or ANSWER.lower()== 'not' or ANSWER.lower()== 'nay':
break
else:
Processing()
print 'Okay, bye'
Talk('Okay, bye')
Готово!
На этом хотелось бы закончить. Я рад, если кому-то помог.
Спасибо за внимание.
Комментарии (9)
Dimones
24.07.2015 07:26А почему не Яндекс.SpeechKit? У него насколько я помню распознавание русской речи на уровне. Плюс можно выделять из контекста значимые слова, не так давно была статья об этом.
art1415926535
24.07.2015 09:06+1/me просто умер об код.
Отрефакторили бы сначала перед тем, как выкладывать.
RoboSloNE
24.07.2015 10:15+3А почему не третий питон? И почему вы выбрали процедурный подход, а не ООП?
Вы используете urllib и curl, хотя можно было бы выбрать что-то одно. А еще проще было бы с requests.
Использование стороннего конвертера тоже кажется странным шагом, а кое-что из импортированного вообще не используется.
aikikode
24.07.2015 12:43+1С одной стороны хорошо, что вы продвигаете Python на Windows, но с другой стороны в этом случае неплохо было бы добавить больше примеров выполнения различных команд применительно к данной ОС.
Под Linux, кстати, существует большое количество аналогичных программ. Применительно к Google Speech Recognition API и Python могу предложить посмотреть на LiSpeak. К сожалению, у меня не получилось заставить ее работать, но там есть неплохие наработки. В частости я их использовал для программы uspeak на Python 3.
Businka76
10.08.2015 19:33Самое сложное и пока у меня нет идей как реализовать это стартовое событие — ок гугл. После которой и запускается запись на распознование.
Тут явно сервис гугл не подходит ибо не реально и не стоит весь звук в сеть отдавать.
Punk_Joker
Давненько не писал на Python конечно, но если не ошибаюсь #coding:utf-8 в первой строке, и сохранить документ в этой же кодировке. Должно помочь