なんでやろうと思ったか
ensekitt.hatenablog.com
これはこれでいいとして、変な音がしたら後で聞きたくなる。
全録しても聞くのがめんどくさいので、大きい音がしたときだけにする。
録音のルール
- 大きい音がしたら録音を始める
- 録音中に大きい音がしたら録音時間を伸ばす(開始時刻を更新する)
- 録音中で大きい音がしなかったら10秒で録音を停止する
録音するファイル名はyyyymmdd_hhmmss_audio.wavとする
ensekitt.hatenablog.com
ルールをもとに以下のコードを書いてみた
コード
import pyaudio import numpy as np import wave import time from datetime import datetime class AudioLight(): def __init__(self): # オーディオに関する設定 self.p = pyaudio.PyAudio() self.channels = 1 # ステレオの場合は2 self.rate = 16000 self.format = pyaudio.paInt16 self.stream = self.p.open( format=self.format, channels=self.channels, rate=self.rate, output=True, input=True, stream_callback=self.callback) self.threshold = 10000 self.wf = None self.status = 0 # 0: norec, 1: rec self.start_at = time.time() # コールバック関数 def callback(self, in_data, frame_count, time_info, status): if self.wf is not None: self.wf.writeframes(in_data) amp = np.fromstring(in_data, np.int16) self.rec_check(amp) out_data = in_data return (out_data, pyaudio.paContinue) def rec_check(self, amp): # 停止中で大きい音がしたら、新しいファイルを作成して開始時刻を設定 if (self.status == 0) and (amp.max() > self.threshold): self.status = 1 time_stamp = datetime.now().strftime("%Y%m%d_%H%M%S") self.open_file(time_stamp) self.start_at = time.time() print("Start Rec") # 録音中で大きい音がしたら、開始時刻を更新 elif (self.status == 1) and (amp.max() > self.threshold): self.start_at = time.time() print("Update rec time") # 録音中で大きい音がしなくなってから10秒経ったら、ファイルを閉じる elif (self.status == 1) and (amp.max () <= self.threshold): if (time.time() - self.start_at) > 10: self.status = 0 self.close_file() print("Rec is done.") def open_file(self, time_stamp): self.wf = wave.open(time_stamp + "_audio.wav", "wb") self.wf.setnchannels(self.channels) self.wf.setsampwidth(2) self.wf.setframerate(self.rate) def close_file(self): self.wf.close() self.wf = None def close(self): self.p.terminate() if __name__ == "__main__": # AudioFilterのインスタンスを作る場所 af = AudioLight() # ストリーミングを始める場所 af.stream.start_stream() # ノンブロッキングなので好きなことをしていていい場所 while af.stream.is_active(): try: time.sleep(0.1) except KeyboardInterrupt: break # ストリーミングを止める場所 af.stream.stop_stream() af.stream.close() af.close()
実行した結果
あっ!とか手を叩いたりすると録音が始まった。
あとは録音開始レベルを適切にすれば良さそう。