本文最早发表于电子发烧友论坛:【新提醒】【正点原子i.MX93开发板试用连载体验】基于深度学习的语音本地控制 - 正点原子学习小组 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)
接下来我就想把录音和关键词识别整合在一个程序里面。
Python中进行语音操作首先想到的是PyAudio。不过在板子上安装PyAudio遇到一点麻烦。Python仓库里面并没有现成的对应这个板子的软件包,需要在板子上编译生成软件包,而PyAudio又依赖PortAudio,而PortAudio在板子上没有移植,所以PyAudio暂时用不了,这个问题以后再想办法解决。 我采用的临时办法是修改前面提到的测试音频的shell脚本,由它录制1秒的语音,然后调用Python程序进行关键字识别,如果是YES就打开开发板上的LED灯,如果是NO就关闭开发板上的LED灯,开灯或关灯完成之后会播放相应的提示音。为了方便调试,在录音之后会自动播放录音结果,以确定录音是否正确。 #!/bin/bash
INIT_FLAG="/home/root/shell/audio/.initialized_audio_device"
RECORD_FILE="test.wav"
PLAY_FILE="/home/root/shell/audio/short.mp3"
RC_LOCAL_FILE="/etc/rc.local"
DELETE_COMMAND="rm -f $INIT_FLAG"
# 将开机自动删除音频初始化标志文件命令加入到开机自启中
add_command() {
if ! grep -qFx "$DELETE_COMMAND" "$RC_LOCAL_FILE"; then
echo "$DELETE_COMMAND" >> "$RC_LOCAL_FILE"
sync
fi
}
# 检查命令是否存在
check_command() {
command -v "$1" > /dev/null 2>&1
}
# 初始化音频设备
init_audio_device() {
amixer cset name='PCM Volume' 192
amixer cset name='Mono Mux' 'Stereo'
amixer cset name='Playback De-emphasis' 2
amixer cset name='Capture Digital Volume' 192
amixer cset name='Capture Mute' 'on'
amixer cset name='Capture Polarity' 'Normal'
amixer cset name='3D Mode' 'No 3D'
amixer cset name='ALC Capture Attack Time' 5
amixer cset name='ALC Capture Decay Time' 2
amixer cset name='ALC Capture Function' 'Stereo'
amixer cset name='ALC Capture Hold Time' 2
amixer cset name='ALC Capture Max PGA' 3
amixer cset name='ALC Capture Min PGA' 6
amixer cset name='ALC Capture NG Switch' 'on'
amixer cset name='ALC Capture NG Threshold' 9
amixer cset name='ALC Capture NG Type' 'Mute ADC Output'
amixer cset name='ALC Capture Target Volume' 15
amixer cset name='ALC Capture ZC Switch' 'on'
amixer cset name='Left Channel Capture Volume' 100%
amixer cset name='Right Channel Capture Volume' 100%
amixer cset name='Left Mixer Left Bypass Volume' 100%
amixer cset name='Right Mixer Right Bypass Volume' 100%
amixer cset name='Output 1 Playback Volume' 100%
amixer cset name='Output 2 Playback Volume' 100%
amixer cset name='ZC Timeout Switch' 'on'
amixer cset name='Left PGA Mux' 'DifferentialL'
amixer cset name='Right PGA Mux' 'DifferentialR'
# touch "$INIT_FLAG"
}
# 检查是否已初始化
check_initialized() {
[ -e "$INIT_FLAG" ]
}
function init_board_mic() {
# 初始化板载麦克风
check_command amixer && {
amixer -q cset name='Differential Mux' 'Line 2'
amixer -q cset name='Left Line Mux' 'Line 2L'
amixer -q cset name='Right Line Mux' 'Line 2R'
}
}
function init_headphone_mic() {
# 初始化耳机麦克风
check_command amixer && {
amixer cset name='Differential Mux' 'Line 1'
amixer cset name='Left Line Mux' 'Line 1L'
amixer cset name='Right Line Mux' 'NC'
}
}
function cleanup() {
# 清理并退出
printf "\n清理并退出...\n"
stty sane # 还原终端状态
exit 0
}
function switch_mode() {
# 录音/播音模式切换
case $1 in
1)
# 进入录音模式
check_command amixer && {
amixer -q cset name='Left Mixer Left Bypass Switch' 'on'
amixer -q cset name='Right Mixer Right Bypass Switch' 'on'
amixer -q cset name='Left Mixer Left Playback Switch' 'off'
amixer -q cset name='Right Mixer Right Playback Switch' 'off'
}
;;
2)
# 进入播音模式
check_command amixer && {
amixer -q cset name='Left Mixer Left Bypass Switch' 'off'
amixer -q cset name='Right Mixer Right Bypass Switch' 'off'
amixer -q cset name='Left Mixer Left Playback Switch' 'on'
amixer -q cset name='Right Mixer Right Playback Switch' 'on'
}
;;
3)
# 关闭录音和播音模式
check_command amixer && {
amixer -q cset name='Left Mixer Left Bypass Switch' 'off'
amixer -q cset name='Right Mixer Right Bypass Switch' 'off'
amixer -q cset name='Left Mixer Left Playback Switch' 'off'
amixer -q cset name='Right Mixer Right Playback Switch' 'off'
amixer -q cset name='Left Line Mux' 'NC'
amixer -q cset name='Right Line Mux' 'NC'
}
;;
esac
}
function apply_config() {
# printf "\n可选麦克风测试项目:\n"
# printf "1. 耳机麦克风\n"
# printf "2. 板载麦克风\n"
# while true; do
# read -r -p "请输入您的选择: " choice
# if [[ "$choice" == "1" || "$choice" == "2" ]]; then
# break
# else
# printf "无效输入。请输入1或2。\n"
# fi
# done
choice=2
printf "\n应用麦克风配置项 %s\n" "$choice"
case $choice in
1)
switch_mode 1
init_headphone_mic
;;
2)
switch_mode 1
init_board_mic
;;
*)
printf "无效选项\n"
;;
esac
}
# 捕获Ctrl+C信号,并调用cleanup函数
trap cleanup SIGINT
# 检查是否已初始化,如果没有,则进行初始化
# if ! check_initialized; then
# printf "第一次运行,执行音频设备初始化...\n"
init_audio_device
# add_command
# fi
while true; do
while true; do
command=1
case $command in
1)
apply_config
printf "\n开始录音...\n"
#sleep 1
check_command arecord && arecord -f cd -d 1 -r 16000 "$RECORD_FILE"
switch_mode 2
printf "\n播放录音...\n"
check_command aplay && aplay "$RECORD_FILE"
switch_mode 3
# 调用Python程序并捕获其输出
output=$(python3 simple_audio.py --input=test.wav)
echo "$output"
# 检查输出是否包含">>> YES"
if echo "$output" | grep -q ">>> YES"; then
echo "Python程序输出YES,执行相应代码..."
echo 1 > /sys/class/leds/sys-led/brightness
echo heartbeat > /sys/class/leds/sys-led/trigger
# 在这里添加当输出为YES时需要执行的代码
switch_mode 2
#gst-play-1.0 haodeyiweinindakai.mp3
aplay haodeyiweinindakai.wav
switch_mode 3
elif echo "$output" | grep -q ">>> NO"; then
echo "Python程序输出NO,执行其他代码..."
echo none > /sys/class/leds/sys-led/trigger
echo 0 > /sys/class/leds/sys-led/brightness
# 在这里添加当输出为NO时需要执行的代码
switch_mode 2
#gst-play-1.0 haodeyiweininguanbi.mp3
aplay haodeyiweininguanbi.wav
switch_mode 3
else
echo "Python程序输出未知结果,或者没有输出结果。"
# 可以选择添加处理未知输出的代码
fi
#break
;;
2)
switch_mode 2
printf "\n开始播音,按 Ctrl+C 可退出播音\n"
gst-play-1.0 --audiosink="alsasink" "$PLAY_FILE"
switch_mode 3
#break
;;
*)
cleanup
;;
esac
done
break
done 完整的程序见压缩包*附件:yes-no-test.zip。核心的脚本代码如下: 从下面的视频看,基本实现了所需要的效果。原来担心板子的麦克风录音效果会影响识别,目前看问题不大。由于采用的是先录音成文件的方法,而且时间仅有1秒,所以使用时还是比较麻烦的,有的时候说话稍微慢了点就没有录制完全。这个需要后续优化一下Python的语音处理。
【正点原子i.MX93开发板试用】使用语音说出YES或NO控制LED灯
另外,目前使用的模型是预训练好的,后面计划会训练中文的提示词,以方便使用。 |