Raspberry Piのマイク入力をPythonスクリプトを使って録音する
Raspberry Pi 3、Python3を使ってマイクから取得した音をWaveファイルとして書き出す方法について説明します。今回は簡単な録音までを紹介しますが、発展として波形の可視化や合成、周波数の解析ができます。
なお、こちらの記事ではRaspberry Piの初期化やネットワーク接続が終わり、Raspberry Piのターミナル操作ができる状態になっていることを前提としております。
Raspberry Piのセットアップ
Raspberry Piにはオーディオ入力がないため、マイクを使う場合はUSBマイクやUSBオーディオ変換アダプタが必要です。記事の中ではPLUGABLE USB オーディオ変換アダプタと市販のコンデンサマイクを使用していますが、その他のUSBデバイスでも構いません。
USBマイクをRaspberry Piに接続し、ターミナルから以下のコマンドを実行します。
$ aplay -l
こちらのコマンドはOSが認識しているサウンドデバイスの一覧を表示します。次のような表示が確認できればデバイスを正しく認識できています。aplayコマンド自体は音源ファイルの再生などに使用されます。(詳細はこちら)
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
ソフトウェアのインストール
Pythonでマイクから入力された信号を処理するために、ソフトウェアのインストール作業を行います。まずPython3をインストールします。
$ sudo apt-get update $ sudo apt-get install python3.4-dev
次にPythonのパッケージマネージャであるpipをインストールします。今回インストールしたPythobn3.4.2ではensurepipが使えないため、以下の方法でインストールしています。
$ wget https://bootstrap.pypa.io/get-pip.py $ sudo python3.4 get-pip.py
マイクからの入力を受け取るためにPyaudioライブラリを使用します。PyaudioはクロスプラットフォームのオーディオAPIであるPortAudioのPythonバインディングです。そのため、PortAudio先にインストールしておく必要があります。
$ sudo apt-get install libportaudio2 libportaudiocpp0 portaudio19-dev
Pyaudioをインストールします。必要に応じてvirtualenvなどで環境を切り分けてください。グローバルにインストールする場合はsudoコマンドが必要になります。
$ pip install pyaudio
マイクから入力された音をwaveファイルに書き出す
最後に、簡単なPythonのスクリプトを作成してマイクからの入力をwaveファイルに書き出します。スクリプトの全体像は以下のようになります。
#-*-coding:utf-8-*- #!/usr/bin/python import pyaudio import wave import sys import time FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 CHUNK = 2**11 RECORD_SECONDS = 3 try: WAVE_FILE = sys.argv[1] except: print('File name is required as an argument.') sys.exit(1) audio = pyaudio.PyAudio() frames = [] def callback(in_data, frame_count, time_info, status): frames.append(in_data) return(None, pyaudio.paContinue) stream = audio.open( format=FORMAT, channels=CHANNELS, rate=RATE, input=True, input_device_index=0, frames_per_buffer=CHUNK, start=False, stream_callback=callback ) if __name__ == '__main__': stream.start_stream() time.sleep(RECORD_SECONDS) stream.stop_stream() stream.close() audio.terminate() wf = wave.open(WAVE_FILE, 'wb') wf.setnchannels(CHANNELS) wf.setsampwidth(audio.get_sample_size(FORMAT)) wf.setframerate(RATE) wf.writeframes(b''.join(frames)) wf.close()
マイクからの入力データは別スレッドとして実行されるcallback関数に渡されます。用意した配列にデータを追加していき、入力が終わった後連結してwaveファイルとして書き出しています。引数に保存するファイル名を指定して実行すると、3秒間音声を録音します。
$ python3.4 record.py sample.wav
録音した音声はRaspberry PiのオーディオアウトやGPIOで出力できます。
XSHELLは他にもRaspberryPiで電子ペーパーを動かしたり、音声の方向測位が出来るモジュールを試したり、RaspberryPiを使った様々な開発例をサンプルコード付きでご紹介しています。
RaspberryPiに興味をお持ちの方は是非そちらも合わせてご覧ください。
ブログの更新やイベントのお知らせは随時告知して参ります。ぜひ@xshell_incをフォローしてください。
6件のコメント
青木 和徳 · 2020年8月1日 10:39 AM
こんにち、試してみたのですが。
上手くいかなかったです。
どこかで、教えてもらえたらなぁーと思っています。
ともとも · 2020年8月4日 3:54 PM
青木さん
コメントありがとうございます。具体的に何をしようとしたのか、どんなエラーが発生したのかコメントお願いします🙏
青木 · 2020年8月13日 5:59 PM
こんにちは、ともともさん
メールで、送られてくるかと思いこんでいました。
よく考えれば、こちらに載っていてもおかしく無いですよね。
スクリプト扱い方をよく知りません。
raspberrypiのThonnyで書いて、desktopに保存してみたのですが。
RunさせるとSyntaxErrorとなります。
青木 · 2020年8月23日 1:09 PM
こんにちは。
Youtubeのai見守りカメラは、2までいきました。
上手く動かせました、感動です。
コロナ過で始めたraspberry pi。分からない事だらけで、購入した本でやってみても上手くうごかず。
調べても、良い答えにはたどりつけませんでした。
御社の取り組みは、すばらしく、コピペで出来てしまうところなどは画期的ですね。私には深層学習のプログラム作ることはハードルが高く、御社の教材で理解を深める事が出来て有り難く思っております。
snsは全然しない(見る専門)ツクレルをフォローはしました。
投稿の仕方をよく知らないので、こちらからしつれしてます。
質問してもよしいですか?
record.pyの保存先を教えてください。
片山裕太 · 2020年8月24日 5:03 PM
こんにちは、青木さん
そう言っていただけると教材作りの励みになります。ありがとうございます!
record.pyの保存先ですが、記事の場合はプログラムを実行できればどこに作成しても大丈夫かと思います。
さしあたりホームディレクトリ(/home/pi)に作るのはいかがでしょうか。
青木 · 2020年8月25日 12:05 AM
こんにちは、片山さん
動作、sample.wavはつくられました。
もともとは、Googleドキュメントを開き音声入力をしたくて調べ始めて、御社の存在を知りました。
それまでは、pythonを使わずにやろうとしていましが。
これからは、pythonを使ってに変えらるかもしれません。高い山ですけど(笑)
ありがとうございました。