Начитавшись разных постов о Google Voice и его использовании, решил написать что-то свое. А именно — голосовое управление компьютером. Сразу оговорюсь, что ОС — Windows.

Нам понадобится:

— 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)


  1. Punk_Joker
    23.07.2015 21:37
    +5

    Давненько не писал на Python конечно, но если не ошибаюсь #coding:utf-8 в первой строке, и сохранить документ в этой же кодировке. Должно помочь


  1. Wedmer
    24.07.2015 00:06

    Просто оставлю это (для заинтересованных) здесь.
    Конечно без гугла, но тоже неплохо.


  1. Dimones
    24.07.2015 07:26

    А почему не Яндекс.SpeechKit? У него насколько я помню распознавание русской речи на уровне. Плюс можно выделять из контекста значимые слова, не так давно была статья об этом.


    1. HomoLuden
      24.07.2015 12:52

      А почему не Win SAPI, например? (кроме «фатального недостатка» привязки к Windows)


  1. art1415926535
    24.07.2015 09:06
    +1

    /me просто умер об код.

    Отрефакторили бы сначала перед тем, как выкладывать.


    1. justabaka
      24.07.2015 10:25

      И справа в «популярное за сутки»: «Почему программировать легко» :)


  1. RoboSloNE
    24.07.2015 10:15
    +3

    А почему не третий питон? И почему вы выбрали процедурный подход, а не ООП?
    Вы используете urllib и curl, хотя можно было бы выбрать что-то одно. А еще проще было бы с requests.
    Использование стороннего конвертера тоже кажется странным шагом, а кое-что из импортированного вообще не используется.


  1. aikikode
    24.07.2015 12:43
    +1

    С одной стороны хорошо, что вы продвигаете Python на Windows, но с другой стороны в этом случае неплохо было бы добавить больше примеров выполнения различных команд применительно к данной ОС.

    Под Linux, кстати, существует большое количество аналогичных программ. Применительно к Google Speech Recognition API и Python могу предложить посмотреть на LiSpeak. К сожалению, у меня не получилось заставить ее работать, но там есть неплохие наработки. В частости я их использовал для программы uspeak на Python 3.


  1. Businka76
    10.08.2015 19:33

    Самое сложное и пока у меня нет идей как реализовать это стартовое событие — ок гугл. После которой и запускается запись на распознование.
    Тут явно сервис гугл не подходит ибо не реально и не стоит весь звук в сеть отдавать.