热门标签 | 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++;
}
}
}





推荐阅读
  • Python第三方库安装的多种途径及注意事项
    本文详细介绍了Python第三方库的几种常见安装方法,包括使用pip命令、集成开发环境(如Anaconda)以及手动文件安装,并提供了每种方法的具体操作步骤和适用场景。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Navicat Premium 15 安装指南及数据库连接配置
    本文详细介绍 Navicat Premium 15 的安装步骤及其对多种数据库(如 MySQL 和 Oracle)的支持,帮助用户顺利完成软件的安装与激活。 ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文介绍了在使用Visual Studio 2015进行项目开发时,遇到类向导弹出“异常来自 HRESULT:0x8CE0000B”错误的解决方案。通过具体步骤和实践经验,帮助开发者快速排查并解决问题。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 在使用Node.js运行时环境的Next.js应用程序部署过程中,遇到了与目录文件数量相关的错误。本文将详细探讨该问题及其解决方案。 ... [详细]
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社区 版权所有