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

微信语音arm转讯飞听写wav过程参考资料

2017-01-13 11:25 260 查看
讯飞接口:讯飞听写(java平台),

1.讯飞接口部署常见问题

Q1:集成sdk后运行,出现java.lang.Unsatisfie.lang.UnsatisfiedLinkError
no injava.library.path,或报20021的错误?

A:Java SDK 使用了 JNI 形式,在初始化 SDK 时,SDK 将加载共享库(Windows下为msc32.dll或msc64.dll文件,Linux下libmsc32.so或libmsc64.so文件),报错是因为系统找不到共享库。

一般来说,在 Windows 下,系统加载共享库时的优先级将按以下的顺序:

1,应用的当前运行目录;

2,由系统环境参数 Path 指定的目录;

3,System32 目录;

而在Linux下,系统加载共享库时的优先级将按以下顺序:

1,LD_LIBRARY_PATH指定的目录;

2,/lib/ 和 /lib64/ 目录;

根据上面:

在Windows下,把 dll 文件,放在应用的当前运行目录(一般为应用所在的目录),或在 Path 把 dll 所在目录加入此环境参数中,或者把dll复制到 System32 目录(不建议);

在Linux下,则把 .so 所在目录,通过 export 加入 LD_LIBRARY_PATH 中(在Terminal或在“.bashrc”等启动时会加载的脚本中),或把
.so 文件复制到 lib 文件夹中(不建议);(另外,确保linux的glibc版本为2.11以上;可以执行命令 ldd  libmsc32.so <如64位系统,则
15e19
命令为 ldd libmsc64.so>,如果有执行结果有`GLIBC_2.11' not found,则需要把 glibc 版本升级到2.11版)

◆一般来说,web项目的当前运行目录,并不项目的根目录,而是由tomcat等
server 指定的目录。所以具体当前运行目录应视 server 而定——即使在 windows 下,也不能把dll文件简单的放在项目根目录下就完事。同时,根据 server 把库文件配置好后,应重启 WebServer 才会生效。

另外,在 Linux 下 eclipse 调试时,可能通过Terminal 来 export LD_LIBRARY_PATH  并不起作用,此时,因为运行的调试环境不在
Terminal 中,需要在项目属性中,设置调试和运行的环境参数,在其中,增加 LD_LIBRARY_PATH ,并指定
so 文件所在的目录,如下图为指定 so 所在目录为当前运行的目录:



关于JNI的更多说明,请通过各大搜索引擎获取更多的资料。

------------------------------------------------------------------------------------

Q2:Java
sdk是否可以实现Web形式?

A:一般情况下是Java是适用web项目;不过功能都是基于本地的,比如本地写音频流识别、合成生成本地音频;即两个需要注意的问题,sdk无法直接录取到Web客户端声音进行听写或识别,也无法将合成的声音直接输出播放到Web客户端,所以一般推荐适用Web项目的还有讯飞云平台的flash
sdk和html5 sdk;

------------------------------------------------------------------------------------

Q3:java
sdk支持同时多路会话吗?

A:不支持,sdk都是单路的,其它平台sdk也都是单路的。

注意:多路并发运行会话会报20019的错误。

------------------------------------------------------------------------------------

Q4:识别能支持多长的会话时间?

A:无论是录音听写或是音频流听写,默认都是最长60秒,超过该时间长度会自行进行vad截断,只能以大音频进行分段,并分次以队列的方式进行识别。

------------------------------------------------------------------------------------

Q5:java
sdk支持多少种音频格式,能否生成mp3格式的音频?

A:目前sdk只支持采样率为16K或8K,采样精度为16位,单声道,字序为Little-Endian的 Windows pcm 或wav,暂不支持其它格式。

------------------------------------------------------------------------------------

Q6:java
sdk能否直接使用音频文件进行听写或识别?

A:可以。Sdk进行听写或识别的音频输入方式有两种,一种为通过实时录音方式,另一种为音频文件流写入方式;音频流文件写入方式使用sdk的writeAudio接口,具体使用方法的代码示例详见SDK中MscInvisibleDemo示例demo。

------------------------------------------------------------------------------------

Q7:java
sdk合成功能否可以只生成合成的音频而不播放声音吗?

A:可以,java sdk 1014版本中新的API接口synthesizeToUri(无声合成)正为该功能而生的,具体使用方法的代码示例详见SDK中MscInvisibleDemo示例demo。

------------------------------------------------------------------------------------

Q8: sdk运行发生错误,如何打印或生成sdk的日志?

A:1、打印控制台的日志:在代码中设置,Setting.setShowLog(true);

2、生成log文件;将msc.cfg(cfg文件请与讯飞人员索取)配置文件放置在项目根目录下的msc文件夹下,重新运行项目即可;

2.微信arm转码

讯飞语音平台的语音识别接口,只支持pcm和wav的16位,采样率16000或者8000的语音文件,微信开发平台的语音格式是arm,不能直接用来识别,所以要先转换。 
jave-1.0.2.jar

package com.iflytek;

import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.AudioInfo;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.EncodingAttributes;
import it.sauronsoftware.jave.InputFormatException;
import it.sauronsoftware.jave.MultimediaInfo;

import java.io.File;

import com.config.XDGlobal;

public class AmrToWav{

/**
* @param args
* @throws EncoderException
* @throws InputFormatException
* @throws IllegalArgumentException
*/
public static void main(String args[]) {
String sourcePath = "./1.amr";
String targetPath = "./1.wav";
translate(sourcePath,targetPath);
}
public static void translate(String sourcePath,String targetPath){
// TODO Auto-generated method stub

File source = new File(sourcePath);
File target = new File(targetPath);
AudioAttributes audio = new AudioAttributes();
audio.setCodec("pcm_s16le");
audio.setBitRate(new Integer(256));
audio.setChannels(new Integer(1));
audio.setSamplingRate(new Integer(16000));
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("wav");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
try {
encoder.encode(source, target, attrs);
} catch (Exception e) {
XDGlobal.log.info(e.getMessage());
}
}

}
12
3
4
5
6
7
8
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
26
27
28
29
30
3132
33
34
35
36
37
38
39
40
4142
43
44
45
46
47
48
49
50
12
3
4
5
6
7
8
9
10
1112
13
14
15
16
17
18
19
20
2122
23
24
25
26
27
28
29
30
3132
33
34
35
36
37
38
39
40
4142
43
44
45
46
47
48
49

3.此方法存在一个it.sauronsoftware.jave.EncoderException:
Duration: N/A, bitrate: N/A的bug,因为jave已经不再维护,目前不影响转码

4.此方法部署到服务器上的问题解决

因项目需求,需要将 amr 格式的文件转成 mp3格式。

网络上提供的思路大多是使用jave-x-x.jar。

这个包确实有用,因为开发时是在windows环境中,测试转换虽然报了异常:

1

it.sauronsoftware.jave.EncoderException:   Duration: N/A, bitrate: N/A

但也确实转换成功了,可以播放。

可是一旦部署到Linux环境当中,不是转换失败,就是转换的文件为大小 0 k。百思不得其解。


原因

经过一些资料和源码跟踪,终于找到了原因。

jave的能转换的原理其实就是调用外部的二进制可执行文件 
ffmpeg
,打开它的jar包就可以发现,它里面内置了:


jave原jar包截图



所以实际上,jave就是封装了一层对外部
ffmpeg
的调用。

而windows上能转换是因为:ffmpeg.exe 这个程序没问题。

而Linux上转换失败也是因为 ffmpeg 这个可能版本太老或依赖库缺失。

起初我以为是调用外部的ffmpeg,所以重新安装编译了Linux的ffmpeg,然并卵。

所以只能再想其他解决方案。


解决

知道原因之后,解决思路有两种。
不使用jave ,将jave一些核心的代码抽取出来,自己调用系统外部。
下载最新的ffmpeg,替换掉原先的ffmpeg。

第二种比较简单,就直接用第二种吧。


下载和替换

下载站点:http://ffmpeg.org/download.html



下载

然后选择一个32位还是64位:



下载

下载之后解压,选择其中的ffmpeg,替换掉。



ffmpeg替换之后


其他!失败看这里!

如果没成功,或者转换失败,看这里。

在操作的时候,为了验证服务器支持这种方式,你可以将下载回来的ffmpeg拷贝到你的服务器上,手动进行转换一次,如果失败,可以留言哦。

可以操作如下:
解压文件(可以自己下载,也可以下载博主在最后提供的现成的jar包,直接解压jar也,打开
.it/sauronsoftware/jave
 目录,也可以看到这个ffmpeg

进入目录,看到ffmpeg文件后,将其拷贝到Linux环境下。
准备一个amr文件,将两个文件都拷贝到同一个目录下,进行测试。如果准备好了,如图:


arm和ffmpeg

接着先给ffmpeg加个执行权限
1

chmod +x ffmpeg

接着调用 ffmpeg 执行转换下
1

./ffmpeg  -i test.amr  test.mp3

然后你会看到一堆的日志,并且可能还有提示,“test.amr: Input/output error”,但不要担心,先不管,你查看下这个目录下是否多了一个test.mp3 文件。如果有了,恭喜你,转换成功了,尝试播放下MP3

你可能得到的日志如下:


日志和执行


成品下载

这是博主制作好的jave.jar 包,亲们需要的直接下载:

64位:jave-1.0.2-x64.jar
http://7xkxil.com1.z0.glb.clouddn.com/jave-ffmpegjave-1.0.2.jar


其他问题

很多反馈在命令下可以用,但放到项目里面就不能了。

如果遇到这种情况,请先清除 
./tomcat/temp/jave-/
 里面的东西文件,因为tomcat会缓存一些库文件。
update 2016-9-9


吐槽

吐槽,之前自己自己编译,浪费好多时间,虽然也可以成功。但每换一个Linux环境就要重新编译。

5.转码备用方案,配合ffmpeg命令参数说明查看
/**
* 以下当做备用,有空再搞
*/

private final static String FFMPEG_PATH;
static {
FFMPEG_PATH = JaveUtils.class.getResource("ffmpeg.exe").getFile();
}

/**
* 将一个amr文件转换成wav文件
*
* @param amrFile
* @throws IOException
*/
public static File amrToWav(File source) throws IOException {
File target = new File(source.getAbsolutePath().replace(".amr", ".wav"));
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(FFMPEG_PATH + " -i " + source.getAbsolutePath() + " -ar 16000 -vcodec pcm_s16le -f wav -ac 0 -y -ab 256 " + target.getAbsolutePath());
InputStream in = process.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
try {
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
if (process.exitValue() != 0) {
// 如果转换失败,这里需要删除这个文件(因为有时转换失败后的文件大小为0)
target.delete();
throw new RuntimeException("转换失败!");
}
} finally {
// 为了避免这里抛出的异常会覆盖上面抛出的异常,这里需要用捕获异常。
try {
in.close();
return target;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: