こんにちは、えんせきです。
Alexaと暮らしていますが、音声で指示できるの良いですよね。なんだかんだで対応家電を増やしたくなっています。
つまりなにしたの?
ロジクールのウェブカメラ(HD Pro Webcam C920)には通話用のマイクがついているので
そのマイクのオーディオを取得してPyAudioで処理した。
今日はカメラの話はしない。
RasPiのカメラどうしたの?
昨日取り付けたディスプレイ、若干カメラつけにくくなるんですよね。
ってことで余ってたロジクールのウェブカメラをつけました。
大まかな手順
- 依存関係のインストール
- オーディオデバイスを確認
- オーディオを取得して標準出力にレベルメータ的な物を表示する
依存関係のインストール
インストール直後のRaspbianを想定している。
sudo apt install libasound-dev sudo apt install libportaudio-dev sudo apt install portaudio19-dev sudo apt install python3-pyaudio python-pyaudio
今回はPython3.5.2のRaspbianにデフォルトで入っている物を想定しているけど、
一応Python-pyaudio(2.x系向け)も入れた。
numpyを少し使うので
sudo apt install libatlas-base-dev
もインストール
動作確認
$ python3 >>> import pyaudio >>> pyaudio.__version__ '0.2.11'
オーディオデバイスの確認
lsusbで認識されていることを確認する
$ lsusb Bus 001 Device 006: ID 046d:082d Logitech, Inc. HD Pro Webcam C920
PyAudioから見えているかを確認する
入力チャンネル数が0じゃなければ入力デバイスとして確認できるのでIDと名前を表示する
(Host APIは一つしか無い(0番)という前提で進めている)
import pyaudio p = pyaudio.PyAudio() info = p.get_host_api_info_by_index(0) n_dev = info.get('deviceCount') for i in range(n_dev): if (p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')): print("Input Device id: {0}, {1}".format(i, p.get_device_info_by_host_api_device_index(0, i).get('name')))
これで確認しておけば他のオーディオデバイスを繋いでいても選んで使うことができる
実行結果はこちら
# ALSA libのワチャワチャしたものがいっぱい出る. # 最後あたりにInput Deviceの情報が出る Input Device id: 2, HD Pro Webcam C920: USB Audio (hw:1,0)
オーディオを取得して標準出力にレベルメータ的な物を表示する
オーディオを取得して(callback関数内のin_data)、Int16形式に変換して、Numpyの配列にする。
その配列の中で最も大きい値÷1000個の#を表示すればレベルメータっぽくなった。
import pyaudio import numpy as np import time WIDTH = 2 CHANNELS = 2 RATE = 16000 p = pyaudio.PyAudio() def callback(in_data, frame_count, time_info, status): numpydata = np.fromstring(in_data, dtype=np.int16) print("#" * int(np.max(numpydata) / 1000)) return (in_data, pyaudio.paContinue) stream = p.open(format=p.get_format_from_width(WIDTH), channels=CHANNELS, rate=RATE, input_device_index=2, input=True, output=False, stream_callback=callback) stream.start_stream() while stream.is_active(): time.sleep(0.1) stream.stop_stream() stream.close() p.terminate()
これは実行している時に指パッチンしてみた。
ちゃんと取れているっぽい。
止める時はCtrl+c
必要に応じてCallbackのところで処理したりQueueに突っ込んで他のところで処理したりすれば、
音で遊べそう。