Translate

2022年4月26日火曜日

Raspberry Pi4B上でPyAudioを使っていたら、途中 OSError [Errorno -9981] で落ちる

 Raspberry Pi4B にUSBマイクを刺し、

マイク入力をPython で扱いたくて PyAudio で以下のようなコードを記述した。

 

import pyaudio

# PyAudio インスタンス化
audio = pyaudio.PyAudio()

# 引数情報に従って、PyAudio ストリーム生成・開始
stream = audio.open(
format=pyaudio.paInt16, # 振幅:ビット解像度
rate = 44100, # サンプリング周波数
channels = 1, # モノラル
input_device_index = 1, #USBインデックス1にUSBマイク
input = True, # マイク入力
frames_per_buffer=4096) # チャンクサイズ:1フレーム4096バイト
stream.start_stream()

# 指定秒数の音声をchunkサイズごとに取得し、配列framesへ追加
for _ in range(0, 3600): # 6分間読み込み
# チャンクサイズ分読み込み
buf = stream.read(4096)
:

:

# クローズ
stream.stop_stream()
stream.close()
audio.terminate()  


Windows10 上で実行すると問題なく動作するのだけど、

Raspberry Pi4B(8GBmem/bullseye64bit)で動かすと、

buf = stream.read(4096) の行で

OSError: [Errorno -9981] Input overflowed

というエラーで止まってしまった。

発生する箇所は、毎回違うが4分以降5分半くらいでだいたい止まってしまう..

 

エラーの内容が Input overflowed となっており、例外が出ているので

overflow時に例外を発生させないように

buf = stream.read(4096, exception_on_overflow=False)

として実行したら発生しなくなった。


p.s.

あとで調べたら、StackOverflowにも同じ内容が出てました。

2022年4月14日木曜日

2022/4/4 版 Raspberry Pi OSからイメージコピーから直接SSH接続できなくなった

 2022/4/4 にRaspberry Pi OS 64bit版が更新された。

この更新でデフォルトで用意されていたpiアカウントがなくなった。

で、この更新で困るのがセットアップ。

 これまで

  1. SDカードをフォーマット
  2.  Image Writer でRaspberry Pi OS イメージをコピー
  3. SDカードにwpa_supplicant.confを作成し、WiFi設定を記述
  4. SDカードに空のsshファイルを作成
  5. SDカードをRaspberry Pi本体に刺してACアダプタへ接続
  6. 同じWiFiにつながっている新規デバイスをpingで総当りしてIPアドレスを特定
  7. PuttyなどからpiユーザでSSH接続

という手順でセットアップしていたが、できなくなった。


この方法を使っていたのはUSBキーボードやモニタをつながなくていいこと。

とくにRaspberry Pi 4になってからはHDMIコネクタがmicroなので、変換コネクタが必要になってめんどくさい。

なので、この方法でやっていたのだけど..

 

それにしても..みんなびっくりしてないなあ..

コロナ→ロシア情勢などで品薄が続いていて新規のRaspberry Piセットアップが途絶えているのだろうか..

 

この対処法のひとつとして、Raspberry Pi Imagerを使うこと。

 

このImagerをPCにインストールして、このアプリケーションを使ってSDカードを作成する。

 

ただし、注意が1点。

SDカードに書き込む前に歯車ボタンを押して、SSIDやデフォルトユーザ情報を設定しておくことだけ。

これでとりあえず対処した。

 

あと..これは自分だけかもしれないけど、プロクシ設定をのこしたまま、プロクシなし環境でImagerを使うとプロクシにつながらないというエラーが出る。

最近ではリモート勤務もおおくなりProxyを設定したりはずしたりして使用しているPCでは注意が必要だ。

Windows10の場合、環境変数HTTP_PROXY/HTTPS_PROXY、OS側のインターネット接続設定変更だけではだめだった。

Proxyを使ったりやめたりしている人はProxy環境でImagerを使わないといけないらしい(自分は別のPCで実行している)。

 


2022年4月6日水曜日

Raspberry Pi に接続したUSBマイクからの音声入力をpyaudioで操作する

Raspberry Piで音声を入力としたシステムを組もうとしたが、 音声出力用ジャックコネクタはあるけどマイクがないことにきづいた。

なのでUSBコネクタに「Sound Blaster Play! 3」をさしてコネクタにピンマイクをつけてみた。

このピンマイクから音声入力するとき、どうやってデバイスを認識するのか、ちょっとしらべてみた。

ここでの前提は Python プログラムで、とする。

まずPythonからこのマイクの入力を操作するには pyaudio パッケージがあるのでこれをインストールする。

ただし pyaudio は portaudio というライブラリを使っているらしいので先にapt-getしておく必要がある。

sudo apt install libportaudio0 libportaudio2 libportaudiocpp0 portaudio19-dev
pip install pyaudio


pyaudio でマイクデバイスを指定するには input_device_index が必要になる。

なので Raspberry Pi にSound Blaster Play! 3を刺して以下のコードを実行する。

import pyaudio
audio = pyaudio.PyAudio()
for i in range(audio.get_device_count()):
    print(audio.get_device_info_by_index(i))

するとずらずらっと、USB接続されたデバイスが表示される。以下実行例:

{'index': 0, 'structVersion': 2, 'name': 'bcm2835 Headphones: - (hw:0,0)', 'hostApi': 0, 'maxInputChannels': 0, 'maxOutputChannels': 8, 'defaultLowInputLatency': -1.0, 'defaultLowOutputLatency': 0.0016099773242630386, 'defaultHighInputLatency': -1.0, 'defaultHighOutputLatency': 0.034829931972789115, 'defaultSampleRate': 44100.0}
{'index': 1, 'structVersion': 2, 'name': 'Sound Blaster Play! 3: USB Audio (hw:1,0)', 'hostApi': 0, 'maxInputChannels': 2, 'maxOutputChannels': 2, 'defaultLowInputLatency': 0.008684807256235827, 'defaultLowOutputLatency': 0.008684807256235827, 'defaultHighInputLatency': 0.034829931972789115, 'defaultHighOutputLatency': 0.034829931972789115, 'defaultSampleRate': 44100.0}
:


上記の例だと、index1であるデバイスに「Sound Blaster Play! 3: USB Audio (hw:1,0)」とあるので、input_device_index1を指定すれば良い。

あとはいろんなブログ記事に乗っかっているサンプルを少し加工して実行してやれば良い。

import pyaudio
import wave
import sys
import time
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 2**11
MIC_INDEX = 1 # ここに指定
RECORD_SECONDS = 5 # 録音秒数

try:
    WAVE_FILE = sys.argv[1]
except:
    print('no output file name')
    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=MIC_INDEX,
    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()



マイクに「あー」といいながら以下のコマンドが終了するまでいいつづける。

python sample.py ah.wav


できあがったah.wavを再生し録音できていればOK。

 

#一応、Pi4/Bullseye 64bit で動作確認しました

AWS Glueジョブ(Python/Spark)にPythonパッケージを追加する方法

 AWS Glueジョブには2つの種類が存在します。 ETLジョブ(Spark) PySparkコードが実行できるジョブ。 最低でも10並列で実行するので、DynamicFrame/DataFrame操作以外の処理はPython Shellジョブを使ったほうがよい。 Python...