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

讯飞接口:讯飞听写(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的更多说明,请通过各大搜索引擎获取更多的资料。
------------------------------------------------------------------------------------
Q2Java sdk是否可以实现Web形式?
A:一般情况下是Java是适用web项目;不过功能都是基于本地的,比如本地写音频流识别、合成生成本地音频;即两个需要注意的问题,sdk无法直接录取到Web客户端声音进行听写或识别,也无法将合成的声音直接输出播放到Web客户端,所以一般推荐适用Web项目的还有讯飞云平台的flash sdk和html5 sdk;
------------------------------------------------------------------------------------
Q3java sdk支持同时多路会话吗?
A:不支持,sdk都是单路的,其它平台sdk也都是单路的。
注意:多路并发运行会话会报20019的错误。
------------------------------------------------------------------------------------
Q4:识别能支持多长的会话时间?
A:无论是录音听写或是音频流听写,默认都是最长60秒,超过该时间长度会自行进行vad截断,只能以大音频进行分段,并分次以队列的方式进行识别。
------------------------------------------------------------------------------------
Q5java sdk支持多少种音频格式,能否生成mp3格式的音频?
A:目前sdk只支持采样率为16K或8K,采样精度为16位,单声道,字序为Little-Endian的 Windows pcm 或wav,暂不支持其它格式。
------------------------------------------------------------------------------------
Q6java sdk能否直接使用音频文件进行听写或识别?
A:可以。Sdk进行听写或识别的音频输入方式有两种,一种为通过实时录音方式,另一种为音频文件流写入方式;音频流文件写入方式使用sdk的writeAudio接口,具体使用方法的代码示例详见SDK中MscInvisibleDemo示例demo。
------------------------------------------------------------------------------------
Q7java 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());
        }
    }

}

      
      
  • 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原jar包截图

所以实际上,jave就是封装了一层对外部ffmpeg的调用。
而windows上能转换是因为:ffmpeg.exe 这个程序没问题。
而Linux上转换失败也是因为 ffmpeg 这个可能版本太老或依赖库缺失。
起初我以为是调用外部的ffmpeg,所以重新安装编译了Linux的ffmpeg,然并卵。
所以只能再想其他解决方案。

解决

知道原因之后,解决思路有两种。

  1. 不使用jave ,将jave一些核心的代码抽取出来,自己调用系统外部。
  2. 下载最新的ffmpeg,替换掉原先的ffmpeg。

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

下载和替换

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

下载下载

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

下载下载

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

ffmpeg替换之后ffmpeg替换之后

其他!失败看这里!

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

  1. 解压文件(可以自己下载,也可以下载博主在最后提供的现成的jar包,直接解压jar也,打开.it/sauronsoftware/jave 目录,也可以看到这个ffmpeg )
  2. 进入目录,看到ffmpeg文件后,将其拷贝到Linux环境下。
  3. 准备一个amr文件,将两个文件都拷贝到同一个目录下,进行测试。如果准备好了,如图:
    arm和ffmpegarm和ffmpeg
  4. 接着先给ffmpeg加个执行权限

    1
    chmod +x ffmpeg
  5. 接着调用 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;
	}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值