热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

科大讯飞语音识别(获取音频流文件中文字)

项目中需要获取视频中的文字,将过程记录下,方便以后使用!为了确保项目在公司内网也能使用语音识别,需要确保内网可以通过HTTP访问dev.voicecloud.cn该网址不是在

项目中需要获取视频中的文字, 将过程记录下, 方便以后使用!

 为了确保项目在公司内网也能使用语音识别,需要确保内网可以通过HTTP访问dev.voicecloud.cn   该网址不是在浏览器地址栏中使用的, sdk要连接的

需求:

获取视频中的音频文件

思路:

1. 使用科大讯飞的语音听写sdk,来获取音频中的文字信息

2.科大讯飞,现在(2017年1月)支持且仅支持pcm和wav格式的音频流文件。 

那么我要从视频中获取文字, 所以需要先从视频中提取格式为pcm或wav格式的音频流文件。然后再将音频流文件传送给讯飞的sdk解析。


所需工具:

1.提取视频中的音频流文件,可以使用Linu上的ffmpeg工具完成, 需要先在Linux上安装ffmpeg,通过Java调用提取音频的命令,获取音频文件。 

我提取pcm格式文件失败, 所以提取的wav格式的文件

2. 提取命令: 

       方式一: ffmpeg -i视频文件名-f s16le -ar 16000输出的音频文件名

  命令解释:以16位,16k采样率提取视频文件中的音频文件。

  方式二:ffmpeg -i 视频文件名 -vn -ar 16000 -ac 1 -acodec pcm_s16le -y 音频文件名

提取的音频文件质量对解析结果有很大的影响。

这是他们的建议:上传的识别的音频格式是有要求的,目前支持的格式是 pcmwav格式、音频采样率要是16k或者8k、采样精度16位、单声道音频

(采样率 16k 8k 识别效果要好一些,识别的音频长度最大为60S)。


下面不在啰嗦其他的,直接写我的测试代码:

资源文档:http://download.csdn.net/detail/changerzhuo_319/9729538

1. Java调用Linux命令, 提取视频中的音频文件:

package com.iflytek;

import java.io.File;
import java.io.InputStreamReader;
import java.io.LineNumberReader;

import org.apache.log4j.Logger;

public class Video2Voice {

private static Logger logger = Logger.getLogger(Video2Voice.class);
/**
* 提取视频中的音频文件
* @param fileName
* @return 音频文件名
* @throws Exception
*/
public static String transform(String fileName) throws Exception {

File file = new File(fileName);
if(!file.exists()) {
logger.error("文件不存在:"+fileName);
throw new RuntimeException("文件不存在:"+fileName);
}

//讯飞现在支持pcm,wav的语音流文件
String name = fileName.substring(0, fileName.lastIndexOf(".")) + ".wav";
logger.info("获取到的音频文件:"+name);

// 提取视频中的音频文件。 根据讯飞要求设置采样率, 位数,
String cmd = "ffmpeg -i "+ fileName +" -f s16le -ar 16000 "+ name;
Process process = Runtime.getRuntime().exec(cmd);//执行命令

//
InputStreamReader ir = new InputStreamReader(process.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
String line;
//输出结果,需要有这部分代码, 否则不能生产抽取的音频文件
while ((line = input.readLine()) != null) {
System.out.println(line);
}
process.destroy();
return name;
}

public static void main(String[] args) {
try {
transform(args[0]);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

2. 从音频文件中获取文字信息, 这段代码是修改的讯飞demo中的代码,仅保留了语音识别的代码

package com.iflytek;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import com.iflytek.cloud.speech.DataUploader;
import com.iflytek.cloud.speech.LexiconListener;
import com.iflytek.cloud.speech.RecognizerListener;
import com.iflytek.cloud.speech.RecognizerResult;
import com.iflytek.cloud.speech.Setting;
import com.iflytek.cloud.speech.SpeechConstant;
import com.iflytek.cloud.speech.SpeechError;
import com.iflytek.cloud.speech.SpeechListener;
import com.iflytek.cloud.speech.SpeechRecognizer;
import com.iflytek.cloud.speech.SpeechSynthesizer;
import com.iflytek.cloud.speech.SpeechUtility;
import com.iflytek.cloud.speech.SynthesizeToUriListener;
import com.iflytek.cloud.speech.UserWords;

public class MscTest {

private static final String APPID = "5860ec57";

private StringBuffer mResult = new StringBuffer();

/** 最大等待时间, 单位ms */
private int maxWaitTime = 500;
/** 每次等待时间 */
private int perWaitTime = 100;
/** 出现异常时最多重复次数 */
private int maxQueueTimes = 3;
/** 音频文件 */
private String fileName = "";

static {
Setting.setShowLog( false );
SpeechUtility.createUtility("appid=" + APPID);
}

public String voice2words(String fileName) throws InterruptedException {
return voice2words(fileName, true);
}

/**
*
* @desc: 工具类,在应用中有一个实例即可, 但是该实例是有状态的, 因此要消除其他调用对状态的修改,所以提供一个init变量
* @auth: zona
* 2017年1月4日 下午4:38:45
* @param fileName
* @param init 是否初始化最大等待时间。
* @return
* @throws InterruptedException
*/
public String voice2words(String fileName, boolean init) throws InterruptedException {
if(init) {
maxWaitTime = 500;
maxQueueTimes = 3;
}
if(maxQueueTimes <= 0) {
mResult.setLength(0);
mResult.append("解析异常!");
return mResult.toString();
}
this.fileName = fileName;

return recognize();
}


// *************************************音频流听写*************************************

/**
* 听写
* @return
* @throws InterruptedException
*/
private String recognize() throws InterruptedException {
if (SpeechRecognizer.getRecognizer() == null)
SpeechRecognizer.createRecognizer();
return RecognizePcmfileByte();
}

/**
* 自动化测试注意要点 如果直接从音频文件识别,需要模拟真实的音速,防止音频队列的堵塞
* @throws InterruptedException
*/
private String RecognizePcmfileByte() throws InterruptedException {
// 1、读取音频文件
FileInputStream fis = null;
byte[] voiceBuffer = null;
try {
fis = new FileInputStream(new File(fileName));
voiceBuffer = new byte[fis.available()];
fis.read(voiceBuffer);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != fis) {
fis.close();
fis = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 2、音频流听写
if (0 == voiceBuffer.length) {
mResult.append("no audio avaible!");
} else {
//解析之前将存出结果置为空
mResult.setLength(0);
SpeechRecognizer recognizer = SpeechRecognizer.getRecognizer();
recognizer.setParameter(SpeechConstant.DOMAIN, "iat");
recognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
recognizer.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
//写音频流时,文件是应用层已有的,不必再保存
// recognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH,
// "./iflytek.pcm");
recognizer.setParameter( SpeechConstant.RESULT_TYPE, "plain" );
recognizer.startListening(recListener);
ArrayList buffers = splitBuffer(voiceBuffer,
voiceBuffer.length, 4800);
for (int i = 0; i // 每次写入msc数据4.8K,相当150ms录音数据
recognizer.writeAudio(buffers.get(i), 0, buffers.get(i).length);
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
recognizer.stopListening();

// 在原有的代码基础上主要添加了这个while代码等待音频解析完成,recognizer.isListening()返回true,说明解析工作还在进行
while(recognizer.isListening()) {
if(maxWaitTime <0) {
mResult.setLength(0);
mResult.append("解析超时!");
break;
}
Thread.sleep(perWaitTime);
maxWaitTime -= perWaitTime;
}
}
return mResult.toString();
}

/**
* 将字节缓冲区按照固定大小进行分割成数组
*
* @param buffer
* 缓冲区
* @param length
* 缓冲区大小
* @param spsize
* 切割块大小
* @return
*/
private ArrayList splitBuffer(byte[] buffer, int length, int spsize) {
ArrayList array = new ArrayList();
if (spsize <= 0 || length <= 0 || buffer == null
|| buffer.length return array;
int size = 0;
while (size int left = length - size;
if (spsize byte[] sdata = new byte[spsize];
System.arraycopy(buffer, size, sdata, 0, spsize);
array.add(sdata);
size += spsize;
} else {
byte[] sdata = new byte[left];
System.arraycopy(buffer, size, sdata, 0, left);
array.add(sdata);
size += left;
}
}
return array;
}

/**
* 听写监听器
*/
private RecognizerListener recListener = new RecognizerListener() {

public void onBeginOfSpeech() { }

public void onEndOfSpeech() { }

public void onVolumeChanged(int volume) { }

public void onResult(RecognizerResult result, boolean islast) {
mResult.append(result.getResultString());
}

public void onError(SpeechError error) {
try {
voice2words(fileName);
maxQueueTimes--;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}

public void onEvent(int eventType, int arg1, int agr2, String msg) { }

};

}

3. main代码:

package com.iflytek;

import java.util.Scanner;


/**
* @desc:
* @auth: zona
* 2017年1月4日 上午10:08:21
*/
public class Test {

private static String fileName = "1481023006148.wav";
public static void main(String[] args) throws InterruptedException {

Scanner scanner =new Scanner(System.in);

MscTest mObject = new MscTest();
int a = 1;
boolean flag = true;
for(int i=0; i<200; i++) {
// MscTest mObject = new MscTest();
if(flag) {
System.out.print("place input num:");
int num = scanner.nextInt();
if(num > 10) {
flag = false;
}
}
//语音识别, 并给mResult赋值, 在获取音频文件中的文字代码中添加while就是为了确保该行代码执行完成时,
// 语音识别解析工作已经完成,否则可能获取不到识别结果, 或仅仅是获取到识别结果的一部分
String result = mObject.voice2words(fileName);
System.out.println(a+"--->MscTest.main()--"+result);
a++;
}
}
}





推荐阅读
  • 探讨如何在映射文件中处理重复的属性字段,以避免数据操作时出现错误。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • 电商常用同义词库_【福利】不可错过的电商设计神器,提高工作效率
    开启高效设计,拒绝每天加班,设计助理插件,设计师高效设计神器,让你早下班的设计神器;今天介绍一款非常人性化的插 ... [详细]
  • 宝塔面板下启用HTTPS的详细指南
    本文提供了在宝塔面板环境中配置HTTPS的具体步骤,确保您的网站通信更加安全可靠。 ... [详细]
  • 本文详细介绍了Socket在Linux内核中的实现机制,包括基本的Socket结构、协议操作集以及不同协议下的具体实现。通过这些内容,读者可以更好地理解Socket的工作原理。 ... [详细]
  • 本文介绍了一种在 Android 开发中动态修改 strings.xml 文件中字符串值的有效方法。通过使用占位符,开发者可以在运行时根据需要填充具体的值,从而提高应用的灵活性和可维护性。 ... [详细]
  • 轮播图(Carousel)是网页设计中常见的元素,用于展示图片或内容滚动。本文精选了超过40个高质量的jQuery轮播图插件及教程,帮助开发者实现各种动态展示效果。 ... [详细]
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 本文详细介绍了Apache Spark 2.2.0版本中集群模式的基本概念和工作流程,包括如何通过集群管理器分配资源,以及Spark应用程序在集群中的运行机制。链接:http://spark.apache.org/docs/2.2.0/cluster-overview.html ... [详细]
  • 在CentOS 7中部署Nginx并配置SSL证书
    本文详细介绍了如何在CentOS 7操作系统上安装Nginx服务器,并配置SSL证书以增强网站的安全性。适合初学者和中级用户参考。 ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本项目基于网络上找到的一个启动动画包,针对Sony手机上的Miku启动动画进行了个性化调整,并重新打包以适应CM(CyanogenMod)系统。此版本旨在为CM用户提供更加个性化的启动体验。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
author-avatar
我是风一样的我们
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有