您的位置:首页 > 移动开发 > 微信开发

小程序语音与讯飞语音识别踩坑过程

2017-02-02 23:54 323 查看
公司要在微信小程序上面实现语音识别的功能,后端的踩坑功能就落到了我的头上了。本着好好学习,努力研究的精神,二话不说就接下了这个任务了。
我在公司的开发环境是在Window上面的,而生产环境是在Ubuntu上面的,所以有的时候开发出来的东西会有一点兼容的问题,这个见怪不怪了。在Window环境上面研究的过程中规中矩,没有碰到上面太多或者太大的坑。下面先说一下实现的大概思路,接着在说一下遇到的坑。
我们是在微信的小程序上面调用微信的录音接口,把录音上传到我们后端进行处理,我们后端接收到微信小程序传回来的语音文件,这个语音文件是SILK格式的,我们收到SILK格式的文件后,先要将SILK文件转换为WAV格式或者PCM(音频采样率要是 16k 或者 8k,16 位,单声道音频),在文件转换成功后,然后调用讯飞的语音识别的接口,把语音转换为文字的格式,然后使用这个文字进行相对应的逻辑操作。
微信用的SILKv3编码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器,Skype后来将其开源。反正录音的文件很小,发回来的都是几K的,转换为PCM或者WAV都是100K左右。下面说一下遇到的坑和爬坑过程:
坑一:libmsc64.so文件不生效。花费了一天的时间看文档那些,已经在Window上面把整体的流程跑通了,程序的识别率还是挺高的,接下来要做的是把这个程序配置到测试服务器上面,看能不能给前端的小程序跑通。因为讯飞的服务要用到动态库的,而在Window上面的动态库可以直接放到项目的根目录或者System32 目录,但是Ubuntu要自己手动指定LD_LIBRARY_PATH的目录,虽然之前Linux系统用了很久,但是至少一些基础得操作,LD_LIBRARY_PATH这个之前是没有搞过。。。,百度了好久,按照百度的教程配置了一下,发现配置成功了,但是程序却死活说缺包,实在不行,所以我就把libmasc64.so文件放到/lib/
和 /lib64/ 目录,发现也不行,打印了一些动态库的地址,/lib/ 和 /lib64/ 目录是有配置了的,可以直接把so文件放进去的,很无奈,搞了半天,死活不生效,测试服上面有很多东西,是不能重启的。最后只能在代码里面执行System.load(/xxxx/libmac64.so),这样把文件加载进去,这个是没有办法的办法。
坑二:语音转换功能public static void RecognizePcmfileByte(String uuid,String filePath)功能要在讯飞的注册SpeechUtility.createUtility("appid=" + APPID) 成功后才能只能,不然也会报错,大概的意思是缺动态库包,所以我把讯飞的注册功能在在项目运行的ServletContentListener里面,这样就可以保在调用转换语音功能前一定注册成功了。

坑三:微信小程序文件上传BUG,因为这个BUG是微信的锅,但是也影响到了我们功能的实现了,在我们把功能实现差不多了,前端也把小程序的文件上传上来了,识别率还是不错的,在我们接受的范围内,然后我就用我的手机扫码尝鲜一下,却发现预约文件上传失败,说是上传的文件为空。这个问题就很怪了,我们刚刚才在其他的手机上面测试是没有什么问题的,在我这里却又问题,难道是我的信仰有问题?试了多部手机才发现:在IPhone上面微信的上传文件是没有什么问题的,但是在Android上面上传文件是不行的,IPhone上面最新的微信是6.5多,Android的最新版本是6.3多,所以上传文件有问题,百度了一下,很多人都有这个问题【我们上传文件是直接用File上传的,还没有试过把文件转为base64再上传】

坑四:讯飞识别率低的问题。我们在拿到微信的文件后,是通过ffmpeg来进行转码的,转码的功能我是参考了这个开源项目https://github.com/kn007/silk-v3-decoder进行转换的,该项目是用到了Ffmpeg和Gcc,他在转换的脚本里面

#!/bin/bash

# File: converter.sh

# Date: August 19th, 2016

# Time: 18:56:52 +0800

# Author: kn007 <kn007@126.com>

# Blog: https://kn007.net
# Link: https://github.com/kn007/silk-v3-decoder
# Usage: sh converter.sh silk_v3_file/input_folder output_format/output_folder flag(format)

# Flag: not define ---- not define, convert a file

# other value ---- format, convert a folder, batch conversion support

# Requirement: gcc ffmpeg

# Colors

RED="\e[31;1m"

GREEN="\e[32;1m"

YELLOW="\e[33;1m"

WHITE="\e[37;1m"

RESET="\e[0m"

# Main

cur_dir=$(cd `dirname $0`; pwd)

if [ ! -r "$cur_dir/silk/decoder" ]; then

echo -e "${WHITE}[Notice]${RESET} Silk v3 Decoder is not found, compile it."

cd $cur_dir/silk

make && make decoder

[ ! -r "$cur_dir/silk/decoder" ]&&echo -e "${RED}[Error]${RESET} Silk v3 Decoder Compile False, Please Check Your System For GCC."&&exit

echo -e "${WHITE}========= Silk v3 Decoder Compile Finish =========${RESET}"

fi

cd $cur_dir

while [ $3 ]; do

pidof /usr/bin/ffmpeg&&echo -e "${RED}[Error]${RESET} ffmpeg is occupied by another application, please check it."&&exit

[ ! -d "$1" ]&&echo -e "${RED}[Error]${RESET} Input folder not found, please check it."&&exit

TOTAL=$(ls $1|wc -l)

[ ! -d "$2" ]&&mkdir "$2"&&echo -e "${WHITE}[Notice]${RESET} Output folder not found, create it."

[ ! -d "$2" ]&&echo -e "${RED}[Error]${RESET} Output folder could not be created, please check it."&&exit

CURRENT=0

echo -e "${WHITE}========= Batch Conversion Start ==========${RESET}"

ls $1 | while read line; do

let CURRENT+=1

$cur_dir/silk/decoder "$1/$line" "$2/$line.pcm" > /dev/null 2>&1

if [ ! -f "$2/$line.pcm" ]; then

ffmpeg -y -i "$1/$line" "$2/${line%.*}.$3" > /dev/null 2>&1 &

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

[ -f "$2/${line%.*}.$3" ]&&echo -e "[$CURRENT/$TOTAL]${GREEN}[OK]${RESET} Convert $line to ${line%.*}.$3 success, ${YELLOW}but not a silk v3 encoded file.${RESET}"&&continue

echo -e "[$CURRENT/$TOTAL]${YELLOW}[Warning]${RESET} Convert $line false, maybe not a silk v3 encoded file."&&continue

fi

ffmpeg -y -f s16le -ar 24000 -ac 1 -i "$2/$line.pcm" "$2/${line%.*}.$3" > /dev/null 2>&1 &

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

rm "$2/$line.pcm"

[ ! -f "$2/${line%.*}.$3" ]&&echo -e "[$CURRENT/$TOTAL]${YELLOW}[Warning]${RESET} Convert $line false, maybe ffmpeg no format handler for $3."&&continue

echo -e "[$CURRENT/$TOTAL]${GREEN}[OK]${RESET} Convert $line To ${line%.*}.$3 Finish."

done

echo -e "${WHITE}========= Batch Conversion Finish =========${RESET}"

exit

done

$cur_dir/silk/decoder "$1" "$1.pcm" > /dev/null 2>&1

if [ ! -f "$1.pcm" ]; then

ffmpeg -y -i "$1" "${1%.*}.$2" > /dev/null 2>&1 &

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

[ -f "${1%.*}.$2" ]&&echo -e "${GREEN}[OK]${RESET} Convert $1 to ${1%.*}.$2 success, ${YELLOW}but not a silk v3 encoded file.${RESET}"&&exit

echo -e "${YELLOW}[Warning]${RESET} Convert $1 false, maybe not a silk v3 encoded file."&&exit

fi

ffmpeg -y -f s16le -ar 24000 -ac 1 -i "$1.pcm" "${1%.*}.$2" > /dev/null 2>&1

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

rm "$1.pcm"

[ ! -f "${1%.*}.$2" ]&&echo -e "${YELLOW}[Warning]${RESET} Convert $1 false, maybe ffmpeg no format handler for $2."&&exit

echo -e "${GREEN}[OK]${RESET} Convert $1 To ${1%.*}.$2 Finish."

exit

批量脚本的执行命令:sh converter.sh input ouput wav
单个转换脚本:sh converter.sh input wav
上面的脚本开源直接转换单个文件,也可以批量转换一个文件夹,但是他单个转换的执行命令只能指定文件输入的目录,不能指定文件输出的的文件,所以我根据他的脚步修改一下脚本的:
#!/bin/bash
# File: converter.sh
# Date: August 19th, 2016
# Time: 18:56:52 +0800
# Author: kn007 <kn007@126.com>
# Blog: https://kn007.net # Link: https://github.com/kn007/silk-v3-decoder # Usage: sh converter.sh silk_v3_file/input_folder output_format/output_folder flag(format)
# Flag: not define ---- not define, convert a file
# other value ---- format, convert a folder, batch conversion support
# Requirement: gcc ffmpeg

# Colors
RED="\e[31;1m"
GREEN="\e[32;1m"
YELLOW="\e[33;1m"
WHITE="\e[37;1m"
RESET="\e[0m"

# Main
cur_dir=$(cd `dirname $0`; pwd)
echo ===${cur_dir}

if [ ! -r "$cur_dir/silk/decoder" ]; then
echo -e "${WHITE}[Notice]${RESET} Silk v3 Decoder is not found, compile it."
cd $cur_dir/silk
make && make decoder
[ ! -r "$cur_dir/silk/decoder" ]&&echo -e "${RED}[Error]${RESET} Silk v3 Decoder Compile False, Please Check Your System For GCC."&&exit
echo -e "${WHITE}========= Silk v3 Decoder Compile Finish =========${RESET}"
fi

cd $cur_dir
echo 输入文件: $1
echo 输出文件: $2
echo 输出格式: $3

pidof /usr/bin/ffmpeg&&echo -e "${RED}[Error]${RESET} ffmpeg is occupied by another application, please check it."&&exit
[ ! -f "$1" ]&&echo -e "${RED}[Error]${RESET} Input file not found, please check it."&&exit
TOTAL=$(ls $1|wc -l)
# [ ! -f "$2" ]&&echo -e "${WHITE}[Notice]${RESET} Output file not found."&&exit
$cur_dir/silk/decoder "$1" "$2.pcm" > /dev/null 2>&1
if [ ! -f "$2.pcm" ]; then
ffmpeg -y -i "$1" "$2.$3" > /dev/null 2>&1 &
ffmpeg_pid=$!
while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1
fi
ffmpeg -y -f s16le -ar 16000 -ac 1 -i "$2.pcm" "$2.$3" > /dev/null 2>&1 &
ffmpeg_pid=$!
while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

# 删除中间pcm文件
# rm "$2.pcm"

echo -e "输出文件:$2.$3"
echo -e "${WHITE}========= Conversion Finish =========${RESET}"
exit
如果我再linux上面执行sh converter.sh input wav 这样就可以直接指定输入输出文件的目录
但是有一个问题,用我的脚本会输出两个文件,一个是xx.pcm,一个是xx.wav文件,我听了一下wav文件,发现是没有什么问题的,识别率也不会很差,但是pcm文件的识别率就有问题了,因为上面的脚本根本没有把pcm文件转换为采样率要是 16k 或者 8k,16 位,单声道音频的文件,所以识别率很低,但是wav转换为了符合要求的格式,用wav转码还是不错的,我是用了这里没有符合要求的pcm识别率才这么低的。

后来找了一些资料,发现一位大哥有过相关的研究了,地址为:http://www.iosre.com/t/topic/3199 参考了上面的执行转码命令,把转码的脚本修改为

#!/bin/bash

# File: converter.sh

# Date: August 19th, 2016

# Time: 18:56:52 +0800

# Author: kn007 <kn007@126.com>

# Blog: https://kn007.net
# Link: https://github.com/kn007/silk-v3-decoder
# Usage: sh converter.sh silk_v3_file/input_folder output_format/output_folder flag(format)

# Flag: not define ---- not define, convert a file

# other value ---- format, convert a folder, batch conversion support

# Requirement: gcc ffmpeg

# Colors

RED="\e[31;1m"

GREEN="\e[32;1m"

YELLOW="\e[33;1m"

WHITE="\e[37;1m"

RESET="\e[0m"

# Main

cur_dir=$(cd `dirname $0`; pwd)

echo ===${cur_dir}

if [ ! -r "$cur_dir/silk/decoder" ]; then

echo -e "${WHITE}[Notice]${RESET} Silk v3 Decoder is not found, compile it."

cd $cur_dir/silk

make && make decoder

[ ! -r "$cur_dir/silk/decoder" ]&&echo -e "${RED}[Error]${RESET} Silk v3 Decoder Compile False, Please Check Your System For GCC."&&exit

echo -e "${WHITE}========= Silk v3 Decoder Compile Finish =========${RESET}"

fi

cd $cur_dir

echo 输入文件: $1

echo 输出文件: $2

echo 输出格式: $3

pidof /usr/bin/ffmpeg&&echo -e "${RED}[Error]${RESET} ffmpeg is occupied by another application, please check it."&&exit

[ ! -f "$1" ]&&echo -e "${RED}[Error]${RESET} Input file not found, please check it."&&exit

TOTAL=$(ls $1|wc -l)

# [ ! -f "$2" ]&&echo -e "${WHITE}[Notice]${RESET} Output file not found."&&exit

$cur_dir/silk/decoder "$1" "$2.pcm" > /dev/null 2>&1

if [ ! -f "$2.pcm" ]; then

ffmpeg -y -i "$1" "$2.$3" > /dev/null 2>&1 &

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

fi

#ffmpeg -y -f s16le -ar 16000 -ac 1 -i "$2.pcm" "$2.$3" > /dev/null 2>&1 &

ffmpeg -f s16le -ar 12k -ac 2 -i "$2.pcm" -f wav -ar 16k -ac 1 "$2.$3" > /dev/null 2>&1 &

ffmpeg_pid=$!

while kill -0 "$ffmpeg_pid"; do sleep 1; done > /dev/null 2>&1

# 删除中间pcm文件

# rm "$2.pcm"

echo -e "输出文件:$2.$3"

echo -e "${WHITE}========= Conversion Finish =========${RESET}"

exit

执行命令改为:sh converter.sh input wav

这样识别率真的是不错的,多谢上面两位大哥帮忙的分享,这样识别率就很不错了。

后面可能还会有坑,打算用讯飞的私有语义实现功能,但是私有语义还在申请中,坑爹。暂时坑就怎么多了。

踩坑的过程要保持一个好的心态,坚持住,不要要哭,遇到坑,有时候睡一觉就会发现问题了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息