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

    【由于CSDN的markdown的排版不是很好,所以整理了一下,新的地址:http://blog.csdn.net/c910511/article/details/54839160】


    公司要在微信小程序上面实现语音识别的功能,后端的踩坑功能就落到了我的头上了。本着好好学习,努力研究的精神,二话不说就接下了这个任务了。
    我在公司的开发环境是在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 [email protected]

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 “ curdir/silk/decoder];thenechoe {WHITE}[Notice] RESETSilkv3Decoderisnotfound,compileit.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 ========== RESETls 1 | while read line; do
let CURRENT+=1
curdir/silk/decoder" 1/ line"" 2/line.pcm” > /dev/null 2>&1  
        if [ ! -f “
2/ line.pcm];thenffmpegyi 1/ line 2/{line%.*}.3” > /dev/null 2>&1 &
ffmpeg_pid= !whilekill0 ffmpeg_pid”; do sleep 1; done > /dev/null 2>&1
[ -f “ 2/ {line%.*}.3" ]&&echo -e "[CURRENT/ TOTAL] {GREEN}[OK] RESETConvert line to {line%.*}.3 success, YELLOWbutnotasilkv3encodedfile. {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= !whilekill0 ffmpeg_pid”; do sleep 1; done > /dev/null 2>&1
rm “ 2/ line.pcm”
[ ! -f “ 2/ {line%.*}.3" ]&&echo -e "[CURRENT/ TOTAL] {YELLOW}[Warning] RESETConvert line false, maybe ffmpeg no format handler for 3.”&&continue  
        echo -e “[
CURRENT/ TOTAL] {GREEN}[OK] RESETConvert line To {line%.*}.3 Finish.”
done
echo -e “ WHITE=========BatchConversionFinish========= {RESET}”
exit
done

curdir/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] RESETConvert 1 to {1%.*}.2 success, YELLOWbutnotasilkv3encodedfile. {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= !whilekill0 ffmpeg_pid”; do sleep 1; done > /dev/null 2>&1
rm “ 1.pcm[!f {1%.*}.2” ]&&echo -e “{YELLOW}[Warning] RESETConvert 1 false, maybe ffmpeg no format handler for 2.”&&exit  
echo -e “
{GREEN}[OK] RESETConvert 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 [email protected]

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 “ curdir/silk/decoder];thenechoe {WHITE}[Notice] RESETSilkv3Decoderisnotfound,compileit.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 curdirecho: 1
echo 输出文件: 2echo: 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

curdir/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= !whilekill0 ffmpeg_pid”; do sleep 1; done > /dev/null 2>&1

删除中间pcm文件

rm “$2.pcm”

echo -e “输出文件: 2. 3”
echo -e “ WHITE=========ConversionFinish========= {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 [email protected]

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 “ curdir/silk/decoder];thenechoe {WHITE}[Notice] RESETSilkv3Decoderisnotfound,compileit.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 curdirecho: 1
echo 输出文件: 2echo: 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

curdir/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"fwavar16kac1" 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=========ConversionFinish========= {RESET}”
exit
执行命令改为:sh converter.sh input wav
这样识别率真的是不错的,多谢上面两位大哥帮忙的分享,这样识别率就很不错了。
后面可能还会有坑,打算用讯飞的私有语义实现功能,但是私有语义还在申请中,坑爹。暂时坑就怎么多了。
踩坑的过程要保持一个好的心态,坚持住,不要要哭,遇到坑,有时候睡一觉就会发现问题了。

猜你喜欢

转载自blog.csdn.net/c910511/article/details/53715202