Вопрос или проблема
Я пытаюсь реализовать кусок кода для записи голоса с микрофона и управления этим с помощью Bluetooth-устройства, нажимая две разные кнопки для начала и остановки записи. Я могу обнаружить нажатие кнопки (KEY_PAGEDOWN) для начала записи, но когда я нажимаю другую кнопку для остановки записи и сохранения в файл .wav, это не работает, потому что внутренний цикл while продолжает работать вечно и не прерывается, когда я нажимаю кнопку остановки (KEY_PAGEUP).
Любая помощь будет очень признательна
for event in bluetooth_device.read_loop():
if event.type == ecodes.EV_KEY and event.value == 1:
keyevent = categorize(event)
if keyevent.keycode == 'KEY_PAGEDOWN':
recorder.start()
print("Запись... нажмите > для остановки")
while True:
frame = recorder.read()
audio.extend(frame)
if keyevent.keycode == 'KEY_PAGEUP':
recorder.stop()
# сохранить аудио в файл формата wave
with wave.open("audio.wav", 'w') as f:
f.setparams((1, 2, 16000, 0, "NONE", "NONE"))
f.writeframes(struct.pack("h" * len(audio), *audio))
И чтобы пролить больше света на то, что я пытаюсь сделать, приведенный ниже код работает хорошо в блоке try except, но в моем случае я хочу управлять записью с помощью кнопок Bluetooth-устройства
try:
recorder.start()
print("Запись... нажмите Ctrl+C для остановки")
while True:
frame = recorder.read()
audio.extend(frame)
except KeyboardInterrupt:
print("Запись остановлена")
recorder.stop()
# сохранить аудио в файл формата wave
with wave.open("audio.wav", 'w') as f:
f.setparams((1, 2, 16000, 0, "NONE", "NONE"))
f.writeframes(struct.pack("h" * len(audio), *audio))
print("Аудио сохранено в audio.wav")
finally:
recorder.delete()
-
Основная проблема в том, что ваш
while True:
цикл внутри блокаKEY_PAGEDOWN
мешает программе проверять событиеKEY_PAGEUP
. -
Чтобы исправить это, вам нужно выйти из внутреннего цикла, когда нажимается кнопка остановки.
-
Вы можете достичь этого, используя флаг для управления циклом записи.
recording = False
for event in bluetooth_device.read_loop():
if event.type == ecodes.EV_KEY and event.value == 1:
keyevent = categorize(event)
if keyevent.keycode == 'KEY_PAGEDOWN':
if not recording:
recorder.start()
print("Запись... нажмите > для остановки")
recording = True
if keyevent.keycode == 'KEY_PAGEUP':
if recording:
recorder.stop()
with wave.open("audio.wav", 'w') as f:
f.setparams((1, 2, 16000, 0, "NONE", "NONE"))
f.writeframes(struct.pack("h" * len(audio), *audio))
print("Запись остановлена и сохранена в audio.wav")
recording = False
if recording:
frame = recorder.read()
audio.extend(frame)
Ответ или решение
Для решения вашей задачи с записью аудио и управлением этой записью с помощью кнопок Bluetooth-устройства, необходимо внести изменения в структуру вашего кода. Основная проблема заключается в том, что внутренний цикл while True:
блокирует обработку последних событий, в частности нажатия кнопки остановки записи. Чтобы исправить эту ситуацию, мы можем использовать переменную-флаг для контроля состояния записи.
Вот исправленный пример кода, который демонстрирует, как правильно организовать цикл, чтобы он мог обрабатывать события нажатия кнопок Bluetooth, не блокируя их:
import wave
import struct
from inputs import get_key
from my_recorder import Recorder # Предполагается, что у вас есть модуль для работы с записью
recorder = Recorder()
audio = []
recording = False
for event in bluetooth_device.read_loop():
# Проверяем, является ли событие нажатием кнопки
if event.type == ecodes.EV_KEY and event.value == 1:
keyevent = categorize(event)
# Запуск записи при нажатии кнопки "KEY_PAGEDOWN"
if keyevent.keycode == 'KEY_PAGEDOWN':
if not recording:
recorder.start()
print("Запись... нажмите > для остановки.")
recording = True
# Остановка записи при нажатии кнопки "KEY_PAGEUP"
elif keyevent.keycode == 'KEY_PAGEUP':
if recording:
recorder.stop()
# Сохраняем аудио в файл формата .wav
with wave.open("audio.wav", 'w') as f:
f.setparams((1, 2, 16000, 0, "NONE", "NONE"))
f.writeframes(struct.pack("h" * len(audio), *audio))
print("Запись окончена, файл сохранен как audio.wav.")
recording = False
# Если запись идет, продолжаем собирать аудио данные
if recording:
frame = recorder.read()
audio.extend(frame)
Объяснение изменений:
-
Флаг состояния записи: Ввод переменной
recording
, которая будет указывать, идет ли запись. Это позволяет выполнять команды нажатия кнопок независимо от процесса записи. -
Оптимизация ожидания событий: Вместо блокирующего цикла, программа постоянно проверяет поступающие события. Если состояние записи активно, происходит чтение аудио данных с помощью
recorder.read()
и их накопление в спискеaudio
. -
Абстракция: Программа должна быть структурирована с учетом абстракций. В этом примере подразумевается, что используется модуль
my_recorder
, в котором реализованы методы для управления устройством записи.
Заключение
Данный алгоритм позволяет обеспечить плавное взаимодействие с Bluetooth-устройством для начала и окончания записи. Вам нужно удостовериться, что ваша библиотека для работы с Bluetooth-устройством корректно обрабатывает события нажатия кнопок, и обеспечивать, чтобы фоновые процессы не блокировали обработку входящих данных. Наконец, правильная организация кода поможет избежать затруднений и повысит эффективность записи звука.