python-3.x - 手动运行时系统运行的语音识别代码不起作用(引发错误 -9997,无效的采样率)
问题描述
我有一个 systemd 服务可以在启动时运行一些语音识别代码。我已将麦克风的采样率从 44,100 Hz 更改为 16,000 Hz,以便运行它的 Raspberry Pi Zero W 可以处理它。当我通过从 SSH 运行代码来测试代码时,它运行良好。但是,当我通过我的 systemd 服务运行它时,它会抛出一个错误 -9997,这是无效的采样率错误。这是我的系统服务:
After=sound.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/speech.py
Restart=on-abort
[Install]
WantedBy=sysinit.target
这是我的 Python 3 代码:
print("INFO: Importing libraries...")
import speech_recognition as sr
import i2c
from gpiozero import LED
from math import ceil
from time import sleep
import sys
import os
import atexit
import traceback
print("INFO: Done.")
r = sr.Recognizer()
m = sr.Microphone(sample_rate=16000)
print(m)
#device_index=1
#GPIO.setmode(GPIO.BCM)
#GPIO.setwarnings(False)
#GPIO.setup(11,GPIO.OUT)
#GPIO.output(11,GPIO.HIGH)
#sleep(2)
#GPIO.output(11,GPIO.LOW)
class ExitHooks(object):
def __init__(self):
self.exit_code = None
self.exception = None
def hook(self):
self._orig_exit = sys.exit
sys.exit = self.exit
sys.excepthook = self.exc_handler
def exit(self, code=0):
self.exit_code = code
self._orig_exit(code)
def exc_handler(self, exc_type, exc, *args):
self.exception = exc
traceback.print_exception(exc_type, exc, args[0], file=open("debug.txt", "w"))
print('ended')
print(traceback.format_exception(exc_type, exc, args[0]))
led.off()
lcd.lcd_clear()
#lcd.lcd_display_string("Program ended", 1)
#lcd.lcd_display_string("Check debug.txt", 2)
hooks = ExitHooks()
hooks.hook()
led = LED(17)
lcd = i2c.lcd()
#def foo():
#print(traceback.format_exc())
#atexit.register(foo)
"""
def exit_handler():
print('ended')
led.off()
lcd.lcd_clear()
lcd.lcd_display_string("Program ended", 1)
lcd.lcd_display_string("Check debug.txt", 2)
errorr = "unexpected program exit\n"
if hooks.exception is not None:
errorr += "exception: "
print(hooks.exception)
errorr += str(hooks.exception)
print(str(hooks.exception) + " string test wowowow")
f = open("debug.txt", "w")
f.write(errorr)
f.close()
atexit.register(exit_handler)"""
lcd.lcd_display_string("DEBUG: ver " + str(sys.version_info.major))
"""Sets parameters to stop recognizer.listening faster.
Parameters:
"r.pause_threshold": an integer in seconds for how long the recognizer needs of silence to stop recording
"r.non_speaking_duration: seconds of non-speaking audio to keep on both sides of the recording, changed because it cannot be higher than `r.pause_threshold`
"""
r.pause_threshold = 0.3
r.non_speaking_duration = 0.3
done = False
def speech(recognizer, microphone):
"""Transcribe speech from recorded from `microphone`.
Returns a dictionary with three keys:
"success": a boolean indicating whether or not the API request was
successful
"error": `None` if no error occured, otherwise a string containing
an error message if the API could not be reached or
speech was unrecognizable
"transcription": `None` if speech could not be transcribed,
otherwise a string containing the transcribed text
"""
# check that recognizer and microphone arguments are appropriate type
if not isinstance(recognizer, sr.Recognizer):
raise TypeError("`recognizer` must be `Recognizer` instance")
if not isinstance(microphone, sr.Microphone):
raise TypeError("`microphone` must be `Microphone` instance")
# adjust the recognizer sensitivity to ambient noise and record audio
# from the microphone
audio = None
with microphone as source:
global done
if done is not True:
recognizer.adjust_for_ambient_noise(source)
done = True
print("INFO: Recording...")
led.on()
audio = recognizer.listen(source)
led.off()
rawwavdata = audio.get_wav_data()
f = open("debug.wav", "w")
f.write(str(rawwavdata))
f.close()
print(audio)
print("INFO: Recognizing...")
try:
return recognizer.recognize_google(audio)
except sr.RequestError:
print("uh-ojh")
except sr.UnknownValueError:
print("uh-ojh")
while True:
print("INFO: Ready for speech.")
trans = speech(r, m)
if trans == "exit":
exit()
if trans == None:
continue
print(trans);
lcd.lcd_clear()
if len(trans) > 32:
print("INFO: Larger than 32")
lcd.lcd_display_string(trans[:17], 1)
lcd.lcd_display_string(trans[16:33], 2)
sleep(2)
if int(ceil(float(len(trans)))) - 32 > 32:
for i in range(int(ceil(float(len(trans) - 32) / 32)) + 1):
lcd.lcd_clear()
lcd.lcd_display_string(trans[i*32:i*32+17], 1)
lcd.lcd_display_string(trans[i*32+16:i*32+33], 2)
print("INFO: Sleeping")
sleep(2)
print("INFO: Done sleeping")
else:
lcd.lcd_clear()
lcd.lcd_display_string(trans[1*32:1*32+17], 1)
print("INFO: First line:", trans[1*32:1*32+17])
lcd.lcd_display_string(trans[1*32+16:1*32+33], 2)
print("INFO: Second line:", trans[1*32+16:1*32+33])
print("INFO: Sleeping")
sleep(2)
print("INFO: Done sleeping")
elif len(trans) > 16:
print("INFO: Larger than 16")
lcd.lcd_display_string(trans[:17], 1)
lcd.lcd_display_string(trans[16:len(trans)], 2)
else:
print("INFO: Short")
lcd.lcd_display_string(trans)
我也尝试过使用这样的 bash 文件:
系统文件:
[Unit]
Description=Create test directory
After=pulseaudio.service
[Service]
Type=simple
ExecStart=/usr/bin/sh /home/pi/run.sh
Restart=on-abort
[Install]
WantedBy=sysinit.target
bash 文件:
/usr/bin/python3 /home/pi/speech.py 2>&1 | tee log.txt
请注意,我是 python 新手,尤其是使用 python 的 IO。另请注意,这只是一个有趣的项目。
解决方案
推荐阅读
- amazon-web-services - 由于配置错误,执行失败:Api Gataway 中路径中的非法字符
- r - R中的更短的顺序表达式
- ios - iOS 应用程序在启动时崩溃并出现 EXC_CORPSE_NOTIFY 异常
- javascript - 获取路径参数并在下拉列表中以 2/4/5 角度显示默认值,并带有翻译(ngx-translate)
- reactjs - Reactjs:将 Jquery 应用程序重写为 Reactjs 以删除内容
- python - 模拟另一个函数使用的python函数
- angular - 如何获取输入值并将其传递给角度组件?
- javascript - 单击地图控件或关闭弹出窗口时,整个页面进行回发,导致地图位置和点丢失
- php - MYSQL 错误:用户 'root'@'localhost' 的访问被拒绝 (1045)
- python - 查找数字^(数字位置)==原始数字即(89 = 8^1 + 9^2)的数字,但代码不会返回高于1306的任何数字?