https://www.xfyun.cn/?ch=bdtg&b_scene_zt=1
package com.atguigu.springboot.controller;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.security.SignatureException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.atguigu.springboot.ApiResultDto;
import com.atguigu.springboot.util.EncryptUtil;
import com.atguigu.springboot.util.HttpUtil;
import com.atguigu.springboot.util.SliceIdGenerator;
/**
/
public class WebLfasrDemo {
//这是调用的域名,建议加上https
public static final String LFASR_HOST = “http://raasr.xfyun.cn/api”;
/*
* 此处是设置你的sppid和sercet_key
* 需要在科大讯飞上申请
*/
public static final String APPID = “5e533011”;
public static final String SECRET_KEY = “f954b3f9121226a6c607dceb610b3c98”;
public static final String PREPARE = "/prepare";
public static final String UPLOAD = "/upload";
public static final String MERGE = "/merge";
public static final String GET_RESULT = "/getResult";
public static final String GET_PROGRESS = "/getProgress";
/**
* 文件分片大小,可根据实际情况调整
*/
public static final int SLICE_SICE = 10485760;// 10M
public static void main(String[] args) {//D:\text.txt
/**
* 不用写成定时跑批,手动执行就可以,几天跑一次
*/
//文件的总的目录
String basePath="D:\\aaa";
//先判断这个路径下的是文件还是文件夹
if(new File(basePath).isDirectory()) {
//获取文件夹下的所有的文件夹
String[] list=new File(basePath).list();
//遍历文件夹下的所有的文件
for (String wj : list) {
//测试用的输出,
System.out.println(wj);
//还得判断一下,是文件还是文件夹
if(new File(basePath+"\\"+wj).isDirectory()) {
String[] files=new File(basePath+"\\"+wj).list();
for (String file : files) {
//先判断一下,这个file是文件还是文件夹
System.out.println(file);
File audio = new File(basePath+"\\"+wj+"\\"+file);
//此处是这么拼接,第一层文件夹+第二层文件夹+文件名称
try (FileInputStream fis = new FileInputStream(audio)) {
// 预处理
String taskId = prepare(audio);
// 分片上传文件
int len = 0;
byte[] slice = new byte[SLICE_SICE];
SliceIdGenerator generator = new SliceIdGenerator();
while ((len =fis.read(slice)) > 0) {
// 上传分片
if (fis.available() == 0) {
slice = Arrays.copyOfRange(slice, 0, len);
}
uploadSlice(taskId, generator.getNextSliceId(), slice);
}
// 合并文件
merge(taskId);
// 轮询获取任务结果
while (true) {
try {
System.out.println("sleep a while Zzz" );
System.out.println("此处可以休眠一些时间");
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ApiResultDto taskProgress = getProgress(taskId);
if (taskProgress.getOk() == 0) {
if (taskProgress.getErr_no() != 0) {
System.out.println("任务失败:" + JSON.toJSONString(taskProgress));
}
String taskStatus = taskProgress.getData();
if (JSON.parseObject(taskStatus).getInteger("status") == 9) {
System.out.println("任务完成!");
break;
}
System.out.println("任务处理中:" + taskStatus);
} else {
System.out.println("获取任务进度失败!");
}
}
//获取解析的结果
String result = getResult(taskId);
// 获取结果,测试解析的结果
System.out.println("\r\n\r\n转写结果: " + getResult(taskId));
//把解析的结果写入到文件中去
writeToText(wj,file, result);
/**
* 转写结果: [{"bg":"600","ed":"7530","onebest":"绿是阳春烟景,大块文章的底色,4月的林峦更是绿得鲜活!","speaker":"0"},{"bg":"7540","ed":"9150","onebest":"诶诗意盎然!","speaker":"0"}]
*
* 此处需要写业务逻辑
*
*
*
*/
} catch (SignatureException e) {
e.printStackTrace();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
}
}
/**
* 获取每个接口都必须的鉴权参数
*
* @return
* @throws SignatureException
*/
public static Map<String, String> getBaseAuthParam(String taskId) throws SignatureException {
Map<String, String> baseParam = new HashMap<String, String>();
String ts = String.valueOf(System.currentTimeMillis() / 1000L);
baseParam.put("app_id", APPID);
baseParam.put("ts", ts);
baseParam.put("signa", EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(APPID + ts), SECRET_KEY));
if (taskId != null) {
baseParam.put("task_id", taskId);
}
return baseParam;
}
/**
* 预处理
*
* @param audio 需要转写的音频
* @return
* @throws SignatureException
*/
public static String prepare(File audio) throws SignatureException {
Map<String, String> prepareParam = getBaseAuthParam(null);
long fileLenth = audio.length();
prepareParam.put("file_len", fileLenth + "");
prepareParam.put("file_name", audio.getName());
prepareParam.put("slice_num", (fileLenth/SLICE_SICE) + (fileLenth % SLICE_SICE == 0 ? 0 : 1) + "");
/********************TODO 可配置参数********************/
// 转写类型
// prepareParam.put(“lfasr_type”, “0”);
// 开启分词
// prepareParam.put(“has_participle”, “true”);
// 说话人分离
// prepareParam.put(“has_seperate”, “true”);
// 设置多候选词个数
// prepareParam.put(“max_alternatives”, “2”);
// 是否进行敏感词检出
// prepareParam.put(“has_sensitive”, “true”);
// 敏感词类型
// prepareParam.put(“sensitive_type”, “1”);
// 关键词
// prepareParam.put(“keywords”, “科大讯飞,中国”);
/****************************************************/
String response = HttpUtil.post(LFASR_HOST + PREPARE, prepareParam);
if (response == null) {
throw new RuntimeException("预处理接口请求失败!");
}
ApiResultDto resultDto = JSON.parseObject(response, ApiResultDto.class);
String taskId = resultDto.getData();
if (resultDto.getOk() != 0 || taskId == null) {
throw new RuntimeException("预处理失败!" + response);
}
System.out.println("预处理成功, taskid:" + taskId);
return taskId;
}
/**
* 分片上传
*
* @param taskId 任务id
* @param slice 分片的byte数组
* @throws SignatureException
*/
public static void uploadSlice(String taskId, String sliceId, byte[] slice) throws SignatureException {
Map<String, String> uploadParam = getBaseAuthParam(taskId);
uploadParam.put("slice_id", sliceId);
String response = HttpUtil.postMulti(LFASR_HOST + UPLOAD, uploadParam, slice);
if (response == null) {
throw new RuntimeException("分片上传接口请求失败!");
}
if (JSON.parseObject(response).getInteger("ok") == 0) {
System.out.println("分片上传成功, sliceId: " + sliceId + ", sliceLen: " + slice.length);
return;
}
System.out.println("params: " + JSON.toJSONString(uploadParam));
throw new RuntimeException("分片上传失败!" + response + "|" + taskId);
}
/**
* 文件合并
*
* @param taskId 任务id
* @throws SignatureException
*/
public static void merge(String taskId) throws SignatureException {
String response = HttpUtil.post(LFASR_HOST + MERGE, getBaseAuthParam(taskId));
if (response == null) {
throw new RuntimeException("文件合并接口请求失败!");
}
if (JSON.parseObject(response).getInteger("ok") == 0) {
System.out.println("文件合并成功, taskId: " + taskId);
return;
}
throw new RuntimeException("文件合并失败!" + response);
}
/**
* 获取任务进度
*
* @param taskId 任务id
* @throws SignatureException
*/
public static ApiResultDto getProgress(String taskId) throws SignatureException {
String response = HttpUtil.post(LFASR_HOST + GET_PROGRESS, getBaseAuthParam(taskId));
if (response == null) {
throw new RuntimeException("获取任务进度接口请求失败!");
}
return JSON.parseObject(response, ApiResultDto.class);
}
/**
* 获取转写结果
*
* @param taskId
* @return
* @throws SignatureException
*/
public static String getResult(String taskId) throws SignatureException {
String responseStr = HttpUtil.post(LFASR_HOST + GET_RESULT, getBaseAuthParam(taskId));
if (responseStr == null) {
throw new RuntimeException("获取结果接口请求失败!");
}
ApiResultDto response = JSON.parseObject(responseStr, ApiResultDto.class);
if (response.getOk() != 0) {
throw new RuntimeException("获取结果失败!" + responseStr);
}
return response.getData();
}
/**
* @param OneDirectory 最外一层目录
* @param twoDirectory 第二层目录
* @param fileName 文件名称
* @param fileText 文件内容
*/
public static void writeToText(String twoDirectory,String fileName,String fileText) {
//自己定义一个存放文件的目录,第二层目录就用解析的目录就可以了,话有文件的名称也用之前的就可以
String OneDirectory = "d:/writeToText";
if(fileName != null && !"".equals(fileName)) {
//处理一下文件名,只要前缀
String preFile = fileName.substring(0, fileName.lastIndexOf("."));
//先判断最外层的目录,如果没有就创建
File oneDir = new File(OneDirectory);
if(!oneDir.exists()) {
oneDir.mkdir();
}
//判断第二层目录是否存在,不存在则创建
File twoDir = new File(OneDirectory+"/"+twoDirectory);
if(!twoDir.exists()) {
twoDir.mkdirs();
}
//判断两层目录后,判断文件是否存在
File file = new File(OneDirectory+"/"+twoDirectory,preFile);
if(!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//向指定文件中写入文字
FileWriter fileWriter;
try {
fileWriter = new FileWriter(OneDirectory+"\\"+twoDirectory+"\\"+preFile);
//使用缓冲区比不使用缓冲区效果更好,因为每趟磁盘操作都比内存操作要花费更多时间。
//通过BufferedWriter和FileWriter的连接,BufferedWriter可以暂存一堆数据,然后到满时再实际写入磁盘
//这样就可以减少对磁盘操作的次数。如果想要强制把缓冲区立即写入,只要调用writer.flush();这个方法就可以要求缓冲区马上把内容写下去
BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);
//向文件中写入数据
bufferedWriter.write(fileText);
bufferedWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}