Голосовой ассистент на Python
В последние годы голосовые ассистенты стали неотъемлемой частью нашей жизни. Они помогают нам управлять своими устройствами, находить информацию и взаимодействовать с различными устройствами всего лишь с помощью голоса. В этой статье мы рассмотрим, как создать собственного голосового ассистента на языке программирования Python.
Голосового ассистента с базовым функционалом можно написать на одном лишь Python, этот язык предлагает простой синтаксис и большое количество библиотек
pip install psutil SpeechRecognition pyttsx3 g4f pycaw
import os
import psutil
import subprocess
import speech_recognition as sr
import pyttsx3
import g4f
import webbrowser
from pycaw.pycaw import AudioUtilities, ISimpleAudioVolume
from pathlib import Path
Кратко расскажу для чего нужна каждая из библиотек
os | Используется для работы с операционной системой |
psutil | Поиск и завершение процессов приложений по имени |
subprocess | Используется для открытия приложений |
speech_recognition | Обеспечивает распознавание речи из аудио |
pyttsx3 | Преобразование текста в звук |
g4f | Подключение Chat GPT 4 без API |
webbrowser | Открывает браузер для просмотра страниц |
pycaw | Управление звуком в Windows |
pathlib | Упрощение управления путями |
Далее нужно создать голосовой "движок" для преобразования текста в речь и озвучивание этого текста
engine = pyttsx3.init()
def speak(text):
engine.say(text)
engine.runAndWait()
Что делает код
engine = pyttsx3.init()
– это создание голосового "движка". Он и будет отвечать за преобразование текста в речьdef speak(text):
– это определение функцииspeak
, которая принимает текст (например, команду или ответ) и проговаривает егоВнутри
speak
:engine.say(text)
– передаёт текст в "движок" для озвучиванияengine.runAndWait()
– запускает озвучивание и ждёт его завершения, чтобы не прерывать речь
Затем мы приступаем к основным функция ассистента, начиная с функции закрытия приложений
def close_process(process_name):
found = False
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'].lower() == process_name.lower():
proc.kill()
found = True
if found:
speak(f"Процессы {process_name} были закрыты.")
else:
speak(f"Процесс {process_name} не найден.")
Что делает код
Использует
psutil.process_iter(['pid', 'name'])
для перебора всех процессов, запущенных в системе, и получает только ихpid
(идентификатор процесса) иname
Сравнивает имя процесса с
process_name
(название процесса, который хотим закрыть), игнорируя регистрЕсли процесс найден,
proc.kill()
завершает егоЕсли хотя бы один процесс с этим именем найден и завершён, программа сообщает, что процессы были закрыты; если нет, сообщает, что таких процессов не обнаружено
Зачем нужен
found
Переменная
found
отслеживает, был ли найден и завершён хотя бы один процесс. Это позволяет ассистенту ответить, найдены ли процессы или нет
Функция открытия приложений
# Открытие приложений с поиском по всей файловой системе
def open_application(app_name):
app_path = None
search_paths = [Path("C:\\"), Path("D:\\"), Path("E:\\")]
for path in search_paths:
for root, dirs, files in os.walk(path):
dirs[:] = [d for d in dirs if not d.startswith('$') and not d.startswith('.')]
for file in files:
if file.lower() == app_name.lower() + ".exe":
app_path = os.path.join(root, file)
break
if app_path:
break
if app_path:
break
if app_path:
subprocess.Popen([app_path], cwd=os.path.dirname(app_path))
speak(f"{app_name} открыт.")
else:
speak(f"Приложение {app_name} не найдено.")
Что делает код
search_paths
задаёт диски для поискаos.walk
проходит по всем папкам и файлам на каждом дискеdirs[:] = [d for d in dirs if not d.startswith('$') and not d.startswith('.')]
исключает скрытые и системные папки из поиска, что ускоряет егоСравнивает имя файла с
app_name
, добавляя.exe
Как только файл найден,
subprocess.Popen
запускает его
2. Почему нужны break
break
прерывает поиск на том уровне, где найден файл, чтобы ускорить выполнение
Функция поиска в браузере
def search_in_browser(query):
url = f"https://yandex.ru/search/?text={query}"
try:
webbrowser.open(url)
speak(f"Ищу '{query}' в Яндексе.")
except Exception as e:
speak(f"Не удалось открыть браузер для поиска. Ошибка: {e}")
print({e})
Что делает код
Формирует URL для Яндекс-поиска с
query
Открывает URL через
webbrowser.open
Если открытие не удалось, ассистент сообщает об ошибке
Функция Chat GPT 4
def gpt(com):
if not com.strip():
return
try:
answer = g4f.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": com}],
stream=True,
)
full_response = ""
for part in answer:
speak(f"Ответ: {part}")
if isinstance(part, dict) and 'choices' in part and 'delta' in part['choices'][0]:
content = part['choices'][0]['delta'].get('content', '')
if content: # Проверяем, что контент не пустой
full_response += content
print(f"Накопленный ответ: {full_response}")
if full_response:
speak(f"Ответ: {full_response}")
except Exception as e:
speak("Произошла ошибка при обращении к GPT. Попробуйте снова.")
Что делает код
Проверяет, является ли
command
пустой строкой после удаления пробелов. Еслиcommand
пустая, функция завершает работу и ничего не выполняет дальшеОтправляет текст команды
command
в модель GPT-4
Функции включения и выключения звука
def mute_sound():
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
volume = session._ctl.QueryInterface(ISimpleAudioVolume)
volume.SetMasterVolume(0.0, None)
speak("Звук выключен.")
def unmute_sound():
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
volume = session._ctl.QueryInterface(ISimpleAudioVolume)
volume.SetMasterVolume(1.0, None)
speak("Звук включен.")
Что делает код
AudioUtilities.GetAllSessions()
получает все аудиосессии (запущенные приложения со звуком)volume.SetMasterVolume(0.0, None)
устанавливает громкость в0.0
, чтобы отключить звукSetMasterVolume(1.0, None)
устанавливает громкость на1.0
(максимум), чтобы включить звукПосле каждого действия ассистент сообщает об изменении громкости
Спящий режим
def sleep_mode():
speak("Ассистент переходит в спящий режим. Скажите 'проснись' для выхода.")
recognizer = sr.Recognizer()
with sr.Microphone() as source:
while True:
print("Спящий режим: ожидание команды...")
try:
audio = recognizer.listen(source, timeout=1, phrase_time_limit=5)
command = recognizer.recognize_google(audio, language='ru-RU').lower()
if 'проснись' in command:
speak("Ассистент пробудился.")
break
except sr.UnknownValueError:
continue
except sr.WaitTimeoutError:
continue
Что делает код
Постоянно слушает микрофон
timeout=1
иphrase_time_limit=5
ограничивают время ожиданияЕсли ассистент услышит "проснись", он выходит из цикла и пробуждается
Функция для распознавания команд
def main():
speak("Ассистент активирован. Чем я могу помочь?")
while True:
command = recognize_command()
if "закрой" in command:
app_name = command.replace("закрой", "").strip()
close_process(str(app_name) + ".exe")
elif "открой" in command:
app_name = command.replace("открой", "").strip()
open_application(app_name)
elif "выключить звук" in command:
mute_sound()
elif "включить звук" in command:
unmute_sound()
elif 'поиск' in command:
query = command.replace('поиск', '').strip()
if query:
search_in_browser(query)
else:
speak("Не указано, что искать.")
elif 'спящий режим' in command:
sleep_mode()
elif 'стоп' in command:
speak("Ассистент завершает работу.")
break
elif "выключение" in command:
speak("Вы уверены, что хотите выключить компьютер?")
of = recognize_command()
if of == "да":
shutdown_computer()
else:
gpt(command)
Что делает код
Создаёт
recognizer
для распознавания речи и захватывает звук через микрофонИспользует
recognizer.recognize_google
для преобразования звука в текстЕсли текст не распознан (
sr.UnknownValueError
), ассистент сообщает, что команда не распознана
Основной цикл программы
def main():
speak("Ассистент активирован. Чем я могу помочь?")
while True:
command = recognize_command()
if "закрой" in command:
app_name = command.replace("закрой", "").strip()
close_process(str(app_name) + ".exe")
elif "открой" in command:
app_name = command.replace("открой", "").strip()
open_application(app_name)
elif "выключить звук" in command:
mute_sound()
elif "включить звук" in command:
unmute_sound()
elif 'поиск' in command:
query = command.replace('поиск', '').strip()
if query:
search_in_browser(query)
else:
speak("Не указано, что искать.")
elif 'спящий режим' in command:
sleep_mode()
elif 'стоп' in command:
speak("Ассистент завершает работу.")
break
elif "выключение" in command:
speak("Вы уверены, что хотите выключить компьютер?")
of = recognize_command()
if of == "да":
shutdown_computer()
else:
gpt(command)
if __name__ == "__main__":
main()
Что делает код
Использует микрофон для получения переменной command
Проверяет что сказал пользователь и выполняет задачу
Если пользователь произнес что-то другое, то передает этот запрос Chat GPT
Полный код
import os
import psutil
import subprocess
import speech_recognition as sr
import pyttsx3
import g4f
import webbrowser
from pycaw.pycaw import AudioUtilities, ISimpleAudioVolume
from pathlib import Path
def close_process(process_name):
found = False
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'].lower() == process_name.lower():
proc.kill()
found = True
if found:
speak(f"Процессы {process_name} были закрыты.")
else:
speak(f"Процесс {process_name} не найден.")
def open_application(app_name):
app_path = None
search_paths = [Path("C:\\"), Path("D:\\"), Path("E:\\")]
for path in search_paths:
for root, dirs, files in os.walk(path):
dirs[:] = [d for d in dirs if not d.startswith('$') and not d.startswith('.')]
for file in files:
if file.lower() == app_name.lower() + ".exe":
app_path = os.path.join(root, file)
break
if app_path:
break
if app_path:
break
if app_path:
subprocess.Popen([app_path], cwd=os.path.dirname(app_path))
speak(f"{app_name} открыт.")
else:
speak(f"Приложение {app_name} не найдено.")
def search_in_browser(query):
url = f"https://yandex.ru/search/?text={query}"
try:
webbrowser.open(url)
speak(f"Ищу '{query}' в Яндексе.")
except Exception as e:
speak(f"Не удалось открыть браузер для поиска. Ошибка: {e}")
print({e})
def mute_sound():
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
volume = session._ctl.QueryInterface(ISimpleAudioVolume)
volume.SetMasterVolume(0.0, None)
speak("Звук выключен.")
def unmute_sound():
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
volume = session._ctl.QueryInterface(ISimpleAudioVolume)
volume.SetMasterVolume(1.0, None)
speak("Звук включен.")
def sleep_mode():
speak("Ассистент уходит в спящий режим. Скажите 'проснись' для выхода.")
recognizer = sr.Recognizer()
with sr.Microphone() as source:
while True:
print("Спящий режим: ожидание команды...")
try:
audio = recognizer.listen(source, timeout=1, phrase_time_limit=5)
command = recognizer.recognize_google(audio, language='ru-RU').lower()
if 'проснись' in command:
speak("Ассистент пробудился.")
break
except sr.UnknownValueError:
continue
except sr.WaitTimeoutError:
continue
def gpt(com):
if not com.strip():
return
try:
answer = g4f.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": com}],
stream=True,
)
full_response = ""
for part in answer:
speak(f"Ответ: {part}")
if isinstance(part, dict) and 'choices' in part and 'delta' in part['choices'][0]:
content = part['choices'][0]['delta'].get('content', '')
if content: # Проверяем, что контент не пустой
full_response += content
print(f"Накопленный ответ: {full_response}")
if full_response:
speak(f"Ответ: {full_response}")
except Exception as e:
speak("Произошла ошибка при обращении к GPT. Попробуйте снова.")
def recognize_command():
recognizer = sr.Recognizer()
with sr.Microphone() as source:
print("Слушаю...")
audio = recognizer.listen(source)
try:
command = recognizer.recognize_google(audio, language='ru-RU')
print("Вы сказали:", command)
return command.lower()
except sr.UnknownValueError:
speak("Не удалось распознать команду.")
return ""
except sr.RequestError:
speak("Ошибка соединения с сервисом распознавания.")
return ""
def main():
speak("Ассистент активирован. Чем я могу помочь?")
while True:
command = recognize_command()
if "закрой" in command:
app_name = command.replace("закрой", "").strip()
close_process(str(app_name) + ".exe")
elif "открой" in command:
app_name = command.replace("открой", "").strip()
open_application(app_name)
elif "выключить звук" in command:
mute_sound()
elif "включить звук" in command:
unmute_sound()
elif 'поиск' in command:
query = command.replace('поиск', '').strip()
if query:
search_in_browser(query)
else:
speak("Не указано, что искать.")
elif 'спящий режим' in command:
sleep_mode()
elif 'стоп' in command:
speak("Ассистент завершает работу.")
break
elif "выключение" in command:
speak("Вы уверены, что хотите выключить компьютер?")
of = recognize_command()
if of == "да":
shutdown_computer()
else:
gpt(command)
if __name__ == "__main__":
main()
Хочу поблагодарить всех, кто следил за процессом разработки, и призвать вас к обратной связи. Надеюсь эта статья была для вас полезна.