Python InputDevice остановить внутренний цикл While, когда кнопка нажата с Bluetooth-устройства

Вопрос или проблема

Я пытаюсь реализовать кусок кода для записи голоса с микрофона и управления этим с помощью 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)

Объяснение изменений:

  1. Флаг состояния записи: Ввод переменной recording, которая будет указывать, идет ли запись. Это позволяет выполнять команды нажатия кнопок независимо от процесса записи.

  2. Оптимизация ожидания событий: Вместо блокирующего цикла, программа постоянно проверяет поступающие события. Если состояние записи активно, происходит чтение аудио данных с помощью recorder.read() и их накопление в списке audio.

  3. Абстракция: Программа должна быть структурирована с учетом абстракций. В этом примере подразумевается, что используется модуль my_recorder, в котором реализованы методы для управления устройством записи.

Заключение

Данный алгоритм позволяет обеспечить плавное взаимодействие с Bluetooth-устройством для начала и окончания записи. Вам нужно удостовериться, что ваша библиотека для работы с Bluetooth-устройством корректно обрабатывает события нажатия кнопок, и обеспечивать, чтобы фоновые процессы не блокировали обработку входящих данных. Наконец, правильная организация кода поможет избежать затруднений и повысит эффективность записи звука.

Оцените материал
Добавить комментарий

Капча загружается...