Files
om_arm_control_app/voice.py
T
2026-08-12 13:15:11 +09:00

73 lines
1.9 KiB
Python

import queue
from collections import deque
import numpy as np
import sounddevice as sd
import speech_recognition as sr
RATE = 16000
CHUNK = RATE // 20 # 50 ms
CHUNK_S = CHUNK / RATE
class NothingHeard(Exception):
pass
def _rms(block):
return float(np.sqrt(np.mean(block.astype(np.float32) ** 2)))
def record(wait_for_speech=5.0, max_len=10.0, trailing_silence=0.9):
"""Record from the default mic until the speaker pauses. Returns raw int16 PCM."""
q = queue.Queue()
noise = []
preroll = deque(maxlen=6)
frames = []
quiet = elapsed = 0.0
def on_audio(data, frames_, time_, status):
q.put(data[:, 0].copy())
with sd.InputStream(samplerate=RATE, channels=1, dtype="int16",
blocksize=CHUNK, callback=on_audio):
while elapsed < max_len:
block = q.get(timeout=2)
elapsed += CHUNK_S
level = _rms(block)
if len(noise) < 6:
noise.append(level)
preroll.append(block)
continue
threshold = max(float(np.median(noise)) * 2.5, 250.0)
if not frames:
if level < threshold:
preroll.append(block)
if elapsed > wait_for_speech:
raise NothingHeard()
continue
frames.extend(preroll)
frames.append(block)
quiet = quiet + CHUNK_S if level < threshold else 0.0
if quiet > trailing_silence:
break
if not frames:
raise NothingHeard()
return np.concatenate(frames).tobytes()
def transcribe(pcm, language):
audio = sr.AudioData(pcm, RATE, 2)
try:
return sr.Recognizer().recognize_google(audio, language=language)
except sr.UnknownValueError:
raise NothingHeard()
def listen(language):
return transcribe(record(), language)