想实现一个功能——即通过语音转换为文字进行写博客(个人博客)
百度API很好提供了这个功能——语音技术 (baidu.com)
新用户有五万次的免费请求次数,使用也不难,申请成功之后区控制台添加应用即可看到对应三个码
复制好这三个码,后面有用。
使用步骤:
1.导入依赖
com.baidu.aip
java-sdk
${version}
2.写一个类用来发起请求百度API(官方有提供)
public class Sample {
//设置APPID/AK/SK
public static final String APP_ID = "你的APP_ID ";
public static final String API_KEY = "你的API_KEY ";
public static final String SECRET_KEY = "你的SECRET_KEY ";
public static String basePath;
{
try {
basePath = ResourceUtils.getURL("classpath:"+File.separator+"sounds").getPath();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public String getString(){ //自己根据需求修改的,作用是录音并获得对应的文字结果
String filename= UUID.randomUUID().toString();
File file = new File(basePath+File.separator+filename+".wav");
if(!file.getParentFile().exists()){ //如果文件的目录不存在
file.getParentFile().mkdirs(); //创建目录
System.out.println("创建目录");
}
if (!file.exists()){
try {
file.createNewFile();//创建文件
System.out.println("创建文件-->"+file.getPath());
} catch (IOException e) {
e.printStackTrace();
}
}
// 初始化一个AipSpeech
AipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);
// 可选:设置网络连接参数
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
HashMapmap=new HashMap<>();
map.put("dev_pid",1537);
EngineeCore engineeCore=new EngineeCore(filename);
engineeCore.startRecognize();
if (!engineeCore.success){
return "";
}
// 调用接口
JSONObject res = client.asr(filename, "wav", 16000, map);
Object result = res.get("result");//返回结果是JSON,所以从中取值即可
return StrUtils.getFormatStr(result.toString());//StrUtils是自己写的工具类,转化String
}
}
public class StrUtils {//工具类转化String
public static String getFormatStr(String result){
return result.substring(2,result.length()-2);
}
}
这个类的方法是用来将语音文件转化为文字的,但是我们的语音文件呢?从哪来?我的需求是通过录音实时地将语音转化为文字,所以我需要做两件事:
1.录音 2.将录音文件按照百度API的要求存储格式
很幸运,这两件事网上已经有大佬实现了,参考文章
我根据自己的要求对它修改了一下,改成同步而不是多线程的方式。这显然更符合我的要求:
public class EngineeCore {
private String filePath;
public EngineeCore(String filePath) {
this.filePath = filePath;
}
AudioFormat audioFormat;
TargetDataLine targetDataLine;
boolean flag = true;
public boolean success=false;
int cnt=3;
private void stopRecognize() {
flag = false;
targetDataLine.stop();
targetDataLine.close();
}
private AudioFormat getAudioFormat() {
float sampleRate = 16000;
// 8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
// 8,16
int channels = 1;
// 1,2
boolean signed = true;
// true,false
boolean bigEndian = false;
// true,false
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}// end getAudioFormat
public void startRecognize() {
try {
// 获得指定的音频格式
audioFormat = getAudioFormat();
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
flag = true;
AudioFileFormat.Type fileType = null;
File audioFile = new File(filePath);
fileType = AudioFileFormat.Type.WAVE;
//声音录入的权值
int weight = 2;
//判断是否停止的计数
int downSum = 0;
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AudioInputStream ais = null;
try {
targetDataLine.open(audioFormat);
targetDataLine.start();
byte[] fragment = new byte[1024];
ais = new AudioInputStream(targetDataLine);
while (flag) {
targetDataLine.read(fragment, 0, fragment.length);
//当数组末位大于weight时开始存储字节(有声音传入),一旦开始不再需要判断末位
if (Math.abs(fragment[fragment.length - 1]) > weight || baos.size() > 0) {
baos.write(fragment);
if(cnt>0){
System.out.println("录音中..");
cnt--;
}
// System.out.println("守卫:" + fragment[0] + ",末尾:" + fragment[fragment.length - 1] + ",lenght" + fragment.length);
//判断语音是否停止
if (Math.abs(fragment[fragment.length - 1]) <= weight) {
downSum++;
} else {
// System.out.println("重置奇数");
downSum = 0;
}//计数超过20说明此段时间没有声音传入(值也可更改)
if (downSum > 20) {
System.out.println("停止录入");
break;
}
}
}
//取得录音输入流
audioFormat = getAudioFormat();
byte audioData[] = baos.toByteArray();
bais = new ByteArrayInputStream(audioData);
ais = new AudioInputStream(bais, audioFormat, audioData.length / audioFormat.getFrameSize());
//定义最终保存的文件名
System.out.println("开始生成语音文件");
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, audioFile);
downSum = 0;
success=true;//表示录音成功
stopRecognize();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
try {
ais.close();
bais.close();
baos.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
} // end catch
}// end captureAudio method
public static void main(String args[]) {
String filename="";
EngineeCore engineeCore = new EngineeCore(filename);
engineeCore.startRecognize();
}
}
现在基本上已经很少在C站发文了,笔记也是写在自己的博客上面,虽然还比较简陋,但也足够我个人使用了。感兴趣的兄弟,欢迎访问——点我