You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/ko/6-consumer/lessons/1-speech-recognition/pi-audio.md

9.9 KiB

오디오 캡처 - Raspberry Pi

이 수업의 이 부분에서는 Raspberry Pi에서 오디오를 캡처하는 코드를 작성합니다. 오디오 캡처는 버튼으로 제어됩니다.

하드웨어

Raspberry Pi는 오디오 캡처를 제어하기 위해 버튼이 필요합니다.

사용할 버튼은 Grove 버튼입니다. 이 버튼은 신호를 켜거나 끄는 디지털 센서입니다. 버튼을 눌렀을 때 높은 신호를 보내고, 누르지 않았을 때 낮은 신호를 보내도록 설정할 수 있으며, 반대로 눌렀을 때 낮은 신호를 보내고 누르지 않았을 때 높은 신호를 보내도록 설정할 수도 있습니다.

ReSpeaker 2-Mics Pi HAT을 마이크로폰으로 사용하는 경우, 이 HAT에 이미 버튼이 장착되어 있으므로 버튼을 연결할 필요가 없습니다. 다음 섹션으로 넘어가세요.

버튼 연결하기

버튼은 Grove 베이스 HAT에 연결할 수 있습니다.

작업 - 버튼 연결하기

Grove 버튼

  1. Grove 케이블의 한쪽 끝을 버튼 모듈의 소켓에 삽입하세요. 케이블은 한 방향으로만 들어갑니다.

  2. Raspberry Pi의 전원을 끈 상태에서, Grove 케이블의 다른 쪽 끝을 Pi에 부착된 Grove 베이스 HAT의 D5로 표시된 디지털 소켓에 연결하세요. 이 소켓은 GPIO 핀 옆에 있는 소켓 줄에서 왼쪽에서 두 번째에 위치합니다.

D5 소켓에 연결된 Grove 버튼

오디오 캡처

Python 코드를 사용하여 마이크로폰에서 오디오를 캡처할 수 있습니다.

작업 - 오디오 캡처하기

  1. Pi의 전원을 켜고 부팅이 완료될 때까지 기다리세요.

  2. VS Code를 실행하세요. Pi에서 직접 실행하거나 Remote SSH 확장을 통해 연결할 수 있습니다.

  3. PyAudio Pip 패키지는 오디오를 녹음하고 재생하는 기능을 제공합니다. 이 패키지는 몇 가지 오디오 라이브러리에 의존하므로, 먼저 다음 명령어를 터미널에서 실행하여 설치하세요:

    sudo apt update
    sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev libasound2-plugins --yes 
    
  4. PyAudio Pip 패키지를 설치하세요.

    pip3 install pyaudio
    
  5. smart-timer라는 새 폴더를 만들고, 이 폴더에 app.py라는 파일을 추가하세요.

  6. 이 파일의 맨 위에 다음 임포트를 추가하세요:

    import io
    import pyaudio
    import time
    import wave
    
    from grove.factory import Factory
    

    이는 pyaudio 모듈, 웨이브 파일을 처리하기 위한 표준 Python 모듈, 그리고 버튼 클래스를 생성하기 위해 grove.factory 모듈을 임포트합니다.

  7. 그 아래에 Grove 버튼을 생성하는 코드를 추가하세요.

    ReSpeaker 2-Mics Pi HAT을 사용하는 경우, 다음 코드를 사용하세요:

    # The button on the ReSpeaker 2-Mics Pi HAT
    button = Factory.getButton("GPIO-LOW", 17)
    

    이는 ReSpeaker 2-Mics Pi HAT에 연결된 버튼이 있는 D17 포트에 버튼을 생성합니다. 이 버튼은 눌렸을 때 낮은 신호를 보내도록 설정됩니다.

    ReSpeaker 2-Mics Pi HAT을 사용하지 않고, Grove 베이스 HAT에 연결된 Grove 버튼을 사용하는 경우, 다음 코드를 사용하세요.

    button = Factory.getButton("GPIO-HIGH", 5)
    

    이는 D5 포트에 버튼을 생성하며, 이 버튼은 눌렸을 때 높은 신호를 보내도록 설정됩니다.

  8. 그 아래에 오디오를 처리하기 위한 PyAudio 클래스의 인스턴스를 생성하세요:

    audio = pyaudio.PyAudio()
    
  9. 마이크와 스피커의 하드웨어 카드 번호를 선언하세요. 이는 이 수업의 이전 단계에서 arecord -laplay -l 명령어를 실행하여 찾은 카드 번호입니다.

    microphone_card_number = <microphone card number>
    speaker_card_number = <speaker card number>
    

    <microphone card number>를 마이크 카드 번호로 바꾸세요.

    <speaker card number>를 스피커 카드 번호로 바꾸세요. 이는 alsa.conf 파일에서 설정한 번호와 동일합니다.

  10. 그 아래에 오디오 캡처 및 재생에 사용할 샘플 레이트를 선언하세요. 사용하는 하드웨어에 따라 이 값을 변경해야 할 수도 있습니다.

    rate = 48000 #48KHz
    

    나중에 이 코드를 실행할 때 샘플 레이트 오류가 발생하면, 이 값을 44100 또는 16000으로 변경하세요. 값이 높을수록 음질이 좋아집니다.

  11. 그 아래에 capture_audio라는 새 함수를 생성하세요. 이 함수는 마이크로폰에서 오디오를 캡처하는 데 사용됩니다:

    def capture_audio():
    
  12. 이 함수 내부에 다음 코드를 추가하여 오디오를 캡처하세요:

    stream = audio.open(format = pyaudio.paInt16,
                        rate = rate,
                        channels = 1, 
                        input_device_index = microphone_card_number,
                        input = True,
                        frames_per_buffer = 4096)
    
    frames = []
    
    while button.is_pressed():
        frames.append(stream.read(4096))
    
    stream.stop_stream()
    stream.close()
    

    이 코드는 PyAudio 객체를 사용하여 오디오 입력 스트림을 엽니다. 이 스트림은 마이크로폰에서 16KHz로 오디오를 캡처하며, 4096 바이트 크기의 버퍼로 캡처합니다.

    코드는 Grove 버튼이 눌려 있는 동안 루프를 돌며, 매번 4096 바이트 버퍼를 배열에 읽어옵니다.

    💁 open 메서드에 전달된 옵션에 대한 자세한 내용은 PyAudio 문서를 참조하세요.

    버튼이 해제되면 스트림이 중지되고 닫힙니다.

  13. 이 함수의 끝에 다음 코드를 추가하세요:

    wav_buffer = io.BytesIO()
    with wave.open(wav_buffer, 'wb') as wavefile:
        wavefile.setnchannels(1)
        wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
        wavefile.setframerate(rate)
        wavefile.writeframes(b''.join(frames))
        wav_buffer.seek(0)
    
    return wav_buffer
    

    이 코드는 바이너리 버퍼를 생성하고, 캡처된 모든 오디오를 WAV 파일로 작성합니다. WAV 파일은 비압축 오디오를 파일로 저장하는 표준 방식입니다. 그런 다음 이 버퍼가 반환됩니다.

  14. 오디오 버퍼를 재생하기 위한 play_audio 함수를 추가하세요:

    def play_audio(buffer):
        stream = audio.open(format = pyaudio.paInt16,
                            rate = rate,
                            channels = 1,
                            output_device_index = speaker_card_number,
                            output = True)
    
        with wave.open(buffer, 'rb') as wf:
            data = wf.readframes(4096)
    
            while len(data) > 0:
                stream.write(data)
                data = wf.readframes(4096)
    
            stream.close()
    

    이 함수는 오디오 출력을 위한 또 다른 오디오 스트림을 엽니다. 이 스트림은 입력 스트림과 동일한 설정을 사용합니다. 그런 다음 버퍼를 웨이브 파일로 열고, 4096 바이트 청크로 출력 스트림에 작성하여 오디오를 재생합니다. 스트림은 이후 닫힙니다.

  15. capture_audio 함수 아래에 다음 코드를 추가하여 버튼이 눌릴 때까지 루프를 실행하세요. 버튼이 눌리면 오디오를 캡처한 후 재생합니다.

    while True:
        while not button.is_pressed():
            time.sleep(.1)
    
        buffer = capture_audio()
        play_audio(buffer)
    
  16. 코드를 실행하세요. 버튼을 누르고 마이크에 대고 말하세요. 버튼을 놓으면 녹음된 소리를 들을 수 있습니다.

    PyAudio 인스턴스가 생성될 때 ALSA 오류가 발생할 수 있습니다. 이는 Pi의 오디오 장치 설정 때문이며, 무시해도 됩니다.

    pi@raspberrypi:~/smart-timer $ python3 app.py 
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.front
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
    

    다음과 같은 오류가 발생하면:

    OSError: [Errno -9997] Invalid sample rate
    

    rate44100 또는 16000으로 변경하세요.

💁 이 코드는 code-record/pi 폴더에서 확인할 수 있습니다.

😀 오디오 녹음 프로그램이 성공적으로 작동했습니다!

면책 조항:
이 문서는 AI 번역 서비스 Co-op Translator를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있지만, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서를 해당 언어로 작성된 상태에서 권위 있는 자료로 간주해야 합니다. 중요한 정보의 경우, 전문적인 인간 번역을 권장합니다. 이 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 당사는 책임을 지지 않습니다.