您当前的位置:首页 > 计算机 > 编程开发 > Java

科大讯飞语音转文字开发(Java代码)

时间:03-10来源:作者:点击数:
业务背景:公司要做一个语音转写的功能,自己开发的成本实在是有点大,直接调用科大讯飞的语音转写的接口,这是调用的具体步骤

科大讯飞的网址:

https://www.xfyun.cn/?ch=bdtg&b_scene_zt=1

当你注册成功以后,系统会把APPID和SecretKey给你,这两条数据你要记录一下,后面要用到

在这里插入图片描述

进入网址后,因为我用的是语音转写服务,所以,我先领取体验包

在这里插入图片描述

下面介绍一下用WebAPI的方式来进行的接口调用,首先可以先把接口的demo例子下载下来,集成到我们的项目中

在这里插入图片描述

下载完成后,是这几个类

在这里插入图片描述

主要介绍一下WebLfasrDemo这个类吧,咱们自己的业务逻辑代码是写在这里的

代码我已经粘贴出来了,上面注释都写的很详细,有一个地方没写,就是异常的处理,根据自己公司的规范自己处理一下就可以了

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;

/**

  • 非实时转写webapi调用demo
  • 此demo只是一个简单的调用示例, 不适合用到实际生产环境中
  •  
  • @author white
  •  

/

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();
    	}
    }
}

}

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门