讯飞接口:讯飞听写(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位系统,则命令为 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){
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());
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 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加个执行权限
-
接着调用 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;
}