java 微信小程序 语音识别成文字 音频格式转换 silk pcm wav

原创 2017年07月15日 15:49:17

最近有需求要把微信小程序里面的语音进行语音识别,然后搜搜,微信小程序的语音格式是silk

1、上传silk文件

2、下载silk-v3-decoder,通过名称把silk转换成讯飞可识别的wav文件

3、获取讯飞转换后的文字信息

	/**
	 * 获取wav文件 并返回路径
	 * @param wavFileName
	 * @return
	 * @throws Exception
	 */
	public String getWav(String wavFileName) throws Exception {//之前别人写的代码,可以改为java直接执行shell脚本的方式

		StringBuilder command = new StringBuilder(Constant.FFMPEG);
		command.append(Constant.CONVERTER);
		command.append(Constant.OXM_VOICE_UPLOAD_BASE_PTAH);
		command.append(wavFileName);
		command.append(" wav ");
		Session session = jschSessionService.getSession();
		jschSessionService.getChannelAndExec(session, command.toString());
		Thread.sleep(2000);
		String name = wavFileName.replace("silk", "wav");
		return name;
	}


public static final String FFMPEG = " export PATH=/usr/local/ffmpeg/bin/:$PATH; source /etc/profile;";
public static final String CONVERTER = " sh /home/deployer/silk-v3-decoder-master/converter.sh ";
public static final String OXM_VOICE_UPLOAD_BASE_PTAH = "/home/deployer/tomcat7/webapps/xxxx/";

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Properties;

import org.springframework.stereotype.Service;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.shanjin.oxm.common.util.Constant;

/**
 *  java  ssh 服务
 *
 */
@Service("JschSessionService")
public class JschSessionService {

	public Session getSession() throws JSchException {
		Properties sshConfig = new Properties();
		sshConfig.put("StrictHostKeyChecking", "no");
		JSch jsch = new JSch();
		Session session = jsch.getSession(Constant.SSH_USER,Constant.SSH_IP,Constant.SSH_PORT);
		session.setPassword(Constant.SSH_PASSWORD);
		session.setConfig(sshConfig);
		session.connect();
		return session;
	}

	public void closeSession(Session session) {
		if (session.isConnected()) {
			session.disconnect();
		}
	}

	
	public String getChannelAndExec(Session session, String command) throws JSchException, IOException {
		Channel channel = session.openChannel("exec");
		((ChannelExec) channel).setCommand(command);

		channel.setInputStream(null);

		((ChannelExec) channel).setErrStream(System.err);

		channel.connect();

		int state = channel.getExitStatus();
		/*if (state != 0) {
			return "exec is error ,exit code is :" + state;
		}*/
		((ChannelExec) channel).setErrStream(System.err);

		//String msg = getExitMessage(channel);
		closeChannel(channel);
		closeSession(session);
		return state + "";
	}

	public void closeChannel(Channel channel){
		if(channel.isConnected()){
			channel.disconnect();
		}
	}
	
	
	public String getExitMessage(Channel channel) throws IOException {
		StringBuilder message = new StringBuilder("exit message is : ");
		InputStream in = channel.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(in,
				Charset.forName("utf-8")));
		String buf = null;
		while ((buf = reader.readLine()) != null) {
			message.append(buf);
		}

		return message.toString();
	}
	

}

	/**
	 * 获取语音信息
	 */
	public String getVoiceText(String filePath,String wavName) throws Exception {
		IflyTekServiceImpl iflytekService = new IflyTekServiceImpl();//TODO 注解方式,会产生缓存,一直都是第一次识别的语音
        	File ff = null;
		String text = null;
		File file = new File(filePath+wavName);
		InputStream in = new FileInputStream(file);
		byte[] bb = VoiceSplitUtil.getbytes(in);
		System.out.println(bb);
		text = iflytekService.RecognizePcmfileByte(bb);
//		text = this.getText(fly);
		in.close();
		return text;
	}

	public String getText(IflyTekServiceImpl fly) {

		StringBuilder text = new StringBuilder();

		JSONObject json = null;
		JSONArray wss = null;
		JSONObject ws = null;
		JSONArray cw = null;
		JSONObject c = null;
        long begin = System.currentTimeMillis();
		while (true) {
			 long end = System.currentTimeMillis();
			 if((end - begin) >3000){
				 break;
				
			 }
			if (fly.recognizer.isListening() && fly.mIsEndOfSpeech == true) {
System.out.println(fly.sn);
				json = JSONObject.fromObject(fly.sn.toString());
				wss = json.getJSONArray("ws");
				text = new StringBuilder();
				for (int i = 0; i < wss.size(); i++) {
					ws = wss.getJSONObject(i);
					cw = ws.getJSONArray("cw");
					c = cw.getJSONObject(0);
					text.append(c.getString("w"));
				}

				break;
			}

		}

		
		if(text.length() <= 0){
			text.append("对不起,我没听清您在说什么");
		}
		return text.toString();
	}


用到了讯飞的jar:json-jena-1.0-1.0.jar、Msc-1.0.jar

讯飞的插件:libmsc32.so、libmsc64.so、msc32.dll、msc64.dll,插件我全部放在了工程的根目录下


后来又要求文字需要转换成,一个痛苦的过程啊,各种文件格式转换

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

public class ShellExec {

	public static void execShell(String command) {
		InputStreamReader stdISR = null;
		InputStreamReader errISR = null;
		Process process = null;
//		String command = "/home/Lance/workspace/someTest/testbash.sh";
		long timeout = 10 * 1000;
		try {
			process = Runtime.getRuntime().exec(command);

//			CommandStreamGobbler errorGobbler = new CommandStreamGobbler(
//					process.getErrorStream(), command, "ERR");
//			CommandStreamGobbler outputGobbler = new CommandStreamGobbler(
//					process.getInputStream(), command, "STD");

//			errorGobbler.start();
			// 必须先等待错误输出ready再建立标准输出
//			while (!errorGobbler.isReady()) {
//				Thread.sleep(10);
//			}
//			outputGobbler.start();
//			while (!outputGobbler.isReady()) {
//				Thread.sleep(10);
//			}

			CommandWaitForThread commandThread = new CommandWaitForThread(
					process);
			commandThread.start();

			long commandTime = new Date().getTime();
			long nowTime = new Date().getTime();
			boolean timeoutFlag = false;
			while (!commandThread.isFinish()) {
				if (nowTime - commandTime > timeout) {
					timeoutFlag = true;
					break;
				} else {
					Thread.sleep(1000);
					nowTime = new Date().getTime();
				}
			}
			if (timeoutFlag) {
				// 命令超时
//				errorGobbler.setTimeout(1);
//				outputGobbler.setTimeout(1);
				System.out.println("正式执行命令:" + command + "超时");
			}

//			while (true) {
//				if (errorGobbler.isReadFinish() && outputGobbler.isReadFinish()) {
//					break;
//				}
//				Thread.sleep(10);
//			}
		} catch (IOException | InterruptedException e) {
			e.printStackTrace();
		} finally {
			if (process != null) {
				process.destroy();
			}
		}
	}
	
	public static void convertAudio(String sourcePath,int sourceHZ,String targetPath,int targetHZ){//ffmpeg参数设置的坑好大啊
		Properties props=System.getProperties(); //获得系统属性集    
		String osName = props.getProperty("os.name"); //操作系统名称
		String command = null;
		if(osName.contains("Windows")){
//			ffmpeg -y -f s16le -ar 24000 -ac 1 -i "$1.pcm" -f wav -ar 16000 -b:a 16 -ac 1 "${1%.*}.$2"
			command = "C:\\ffmpeg.exe -y -f s16le -ar "+sourceHZ+" -i "+sourcePath+" -f wav -ar "+targetHZ+" -b:a 8 -ac 1 "+targetPath;			
		}else{
			command = "/usr/local/ffmpeg/bin/ffmpeg -y -f s16le -ar "+sourceHZ+" -ac 1 -i "+sourcePath+" -f wav -ar "+targetHZ+" -b:a 8 -ac 1 "+targetPath;
		}
		System.out.println("格式转换:"+command);
		ShellExec.execShell(command);
	}
	
	public static void pcmToSilk(String pcmPath,String silkPath) throws InterruptedException{
		//首先 pcm转换成8000的wav,然后wav转成silk
//		ShellExec.convertAudio(pcmPath, 16000, pcmPath+".wav", 16000);
//		Thread.sleep(1000);
//		ShellExec.convertAudio(pcmPath+".wav", 16000, silkPath, 8000);
		

		ShellExec.convertAudio(pcmPath, 16000, silkPath, 8000);
	}
	
	public static void pcmToWav(String pcmPath,String wavPath){
		Properties props=System.getProperties(); //获得系统属性集    
		String osName = props.getProperty("os.name"); //操作系统名称
		String command = null;
		if(osName.contains("Windows")){
			command = "C:\\ffmpeg.exe -f s16le -ar 16000 -i "+pcmPath+" -f wav -ar 16000 -b:a 8 -ac 1 "+wavPath;			
		}else{
			command = "/usr/local/ffmpeg/bin/ffmpeg -f s16le -ar 16000 -i "+pcmPath+" -f wav -ar 16000 -b:a 16 -ac 1 "+wavPath;
		}
		System.out.println("格式转换:"+command);
		ShellExec.execShell(command);
	}
	
	public static void silkToWav(String silkPath,String wavPath){
		Properties props=System.getProperties(); //获得系统属性集    
		String osName = props.getProperty("os.name"); //操作系统名称
		String command = null;
		if(osName.contains("Windows")){
//			ffmpeg -y -f s16le -ar 24000 -ac 1 -i "$1.pcm" -f wav -ar 16000 -b:a 16 -ac 1 "${1%.*}.$2"
			command = "C:\\ffmpeg.exe -y -f s16le -ar 8000 -ac 1 -i "+silkPath+" -f wav -ar 16000 -b:a 16 -ac 1 "+wavPath;			
		}else{
			command = "/usr/local/ffmpeg/bin/ffmpeg -y -f s16le -ar 8000 -ac 1 -i "+silkPath+" -f wav -ar 16000 -b:a 16 -ac 1 "+wavPath;
		}
		System.out.println("格式转换:"+command);
		ShellExec.execShell(command);
	
	}
	
	public static void main(String[] args) throws Exception{
		ShellExec.pcmToSilk("/home/deployer/tomcat7/webapps/omoFile/gc3e72fbe-1a27-479f-ae4f-d3aacc6276ed.pcm", "/home/deployer/tomcat7/webapps/omoFile/gc3e72fbe-1a27-479f-ae4f-d3aacc6276ed.pcm.silk");
//		ShellExec.pcmToWav("/home/deployer/tomcat7/webapps/omoFile/gdd68fe07-35b3-46f1-af08-97100caba179.pcm", "/home/deployer/tomcat7/webapps/omoFile/gdd68fe07-35b3-46f1-af08-97100caba179.pcm.wav");

	}

public class CommandWaitForThread extends Thread {

	private Process process;
	private boolean finish = false;
	private int exitValue = -1;

	public CommandWaitForThread(Process process) {
		this.process = process;
	}

	public void run() {
		try {
			this.exitValue = process.waitFor();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			finish = true;
		}
	}

	public boolean isFinish() {
		return finish;
	}

	public void setFinish(boolean finish) {
		this.finish = finish;
	}

	public int getExitValue() {
		return exitValue;
	}

最终得到了微信小程序需要的silk格式,然而,他喵的我不知道微信小程序需要什么频率什么规格的silk文件,电脑能够播放我转换了的silk,但是小程序并不能播放,好蛋疼啊。继续蛋疼中........


附两份资料

linux安装ffmpeg

http://blog.csdn.net/wh8_2011/article/details/50666745

ffmpeg命令及案例

http://blog.csdn.net/c910511/article/details/54849048 案例

http://www.cuplayer.com/player/PlayerCode/FFmpeg/2014/0706/1399.html 命令

版权声明:本文为博主原创文章,带上地址可以随意转载。

java 将微信录音amr转换为mp3格式

最近一直都在做微信相关的项目 有个需求是上传录音,然后再播放 实现方法是,调用微信接口,录音,上传到微信服务器,当用户保存的时候,从微信服务器下载下来,然后再转码成为MP3格式,在页面使用audi...
  • zs19940220
  • zs19940220
  • 2016年02月01日 02:34
  • 10602

java实现silk音频文件转换成mp3

在服务端通过java代码执行shell脚本来实现音频转换 int status=Runtime.getRuntime().exec(command).waitFor(); 转换成功状态为0 参考...
  • u012515742
  • u012515742
  • 2017年03月24日 15:40
  • 2650

微信小程序 录音文件格式silk 坑

不好意思,误导大家了,这种将silk解密的方式只是在小程序测试的时候可以,上线以后这种方法是不行的,还是需要使用解密转码。参见:https://github.com/kn007/silk-v3-dec...
  • rjliulei
  • rjliulei
  • 2017年09月02日 15:35
  • 4723

阿里云linux安装ffmpeg支持小程序silk文件转换-续

这是微信开发工具在调试中的录音文件,截图如下: 这是使用手机中小程序体验版,或者发布版本中的录音文件,截图如下: 如果参考     阿里云linux安装ffmpeg...
  • Baijinwen
  • Baijinwen
  • 2017年09月20日 15:32
  • 1167

Java文本语音转换组件JTTS发布

下载地址:http://greenvm.googlecode.com/files/JTTSEngine.7z (含示例与源码,目前仅提供dll封装)   众所周知,所谓TTS即Text T...
  • syl469
  • syl469
  • 2012年10月15日 19:40
  • 8620

java,讯飞语言识别,本地音频转文字

  • 2017年04月27日 09:46
  • 5.46MB
  • 下载

Java文本语音转换组件JTTS发布(eSpeak封装)

下载地址:http://greenvm.googlecode.com/files/JTTSEngine.7z(含示例与源码,目前仅提供dll封装) 众所周知,所谓TTS即Text To Speech的...
  • cping1982
  • cping1982
  • 2010年02月11日 19:57
  • 16914

ffmpeg转码音频为silk格式命令

将 aif 文件转换为 16 位有符号数,小端存储模式,8000 Hz 采样率: ffmpeg -i test.aif -f s16le -ar 8000 test.pcm 将 44.1K...
  • c910511
  • c910511
  • 2017年02月03日 19:35
  • 4512

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

【由于CSDN的markdown的排版不是很好,所以整理了一下,新的地址:[http://blog.csdn.net/c910511/article/details/54839160](%E6%96%...
  • c910511
  • c910511
  • 2016年12月17日 22:26
  • 7377

ffmpeg命令:wav转pcm,pcm转wav

ffmpeg命令:wav转pcm,pcm转wav 1、ffmpeg命令:wav转pcm: ffmpeg -i input.wav -f s16be -ar 8000 -acodec pcm_s1...
  • Cinberella
  • Cinberella
  • 2015年02月15日 09:37
  • 9467
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java 微信小程序 语音识别成文字 音频格式转换 silk pcm wav
举报原因:
原因补充:

(最多只允许输入30个字)