2 次代码提交 c6196fab63 ... 38c00f31bd

作者 SHA1 备注 提交日期
  王苗苗 38c00f31bd 新增通过通话记录ID将录音转换为文本的接口 1 周之前
  王苗苗 e27b17e341 新增通过通话记录ID将录音转换为文本的接口 1 周之前

+ 11 - 0
slibra-admin/src/main/java/com/slibra/web/controller/business/TCallRecordController.java

@@ -125,4 +125,15 @@ public class TCallRecordController extends BaseController
     {
         return R.ok(tCallRecordService.getAgentList());
     }
+
+
+    /**
+     * 通过通话ID,将存储的音频转换为文本,并将结果返回给前端
+     * @return
+     */
+    @GetMapping(value = "/updateFile2TextById")
+    public R<String> updateFile2TextById(Long id)
+    {
+        return R.ok(tCallRecordService.updateFile2TextById(id));
+    }
 }

+ 17 - 0
slibra-system/src/main/java/com/slibra/business/res/Ele.java

@@ -0,0 +1,17 @@
+package com.slibra.business.res;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Ele {
+
+    private String SpeakerId;
+    private String Text;
+}
+

+ 2 - 1
slibra-system/src/main/java/com/slibra/business/service/ITCallRecordService.java

@@ -2,7 +2,6 @@ package com.slibra.business.service;
 
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import com.slibra.business.domain.TCallRecord;
 
@@ -65,4 +64,6 @@ public interface ITCallRecordService
     TCallRecord getCallBySessionId(String sessionId);
 
     List<HashMap<String, Object>> getAgentList();
+
+    String updateFile2TextById(Long id);
 }

+ 181 - 0
slibra-system/src/main/java/com/slibra/business/service/impl/File2Text.java

@@ -0,0 +1,181 @@
+package com.slibra.business.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.aliyuncs.CommonRequest;
+import com.aliyuncs.CommonResponse;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.http.MethodType;
+import com.aliyuncs.profile.DefaultProfile;
+
+public class File2Text {
+    // 地域ID,常量,固定值。
+    public static final String REGIONID = "cn-shanghai";
+    public static final String ENDPOINTNAME = "cn-shanghai";
+    public static final String PRODUCT = "nls-filetrans";
+    public static final String DOMAIN = "filetrans.cn-shanghai.aliyuncs.com";
+    public static final String API_VERSION = "2018-08-17";  // 中国站版本
+    // public static final String API_VERSION = "2019-08-23";  // 国际站版本
+    public static final String POST_REQUEST_ACTION = "SubmitTask";
+    public static final String GET_REQUEST_ACTION = "GetTaskResult";
+    // 请求参数
+    public static final String KEY_APP_KEY = "appkey";
+    public static final String KEY_FILE_LINK = "file_link";
+    public static final String KEY_VERSION = "version";
+    public static final String KEY_ENABLE_WORDS = "enable_words";
+    // 响应参数
+    public static final String KEY_TASK = "Task";
+    public static final String KEY_TASK_ID = "TaskId";
+    public static final String KEY_STATUS_TEXT = "StatusText";
+    public static final String KEY_RESULT = "Result";
+    // 状态值
+    public static final String STATUS_SUCCESS = "SUCCESS";
+    private static final String STATUS_RUNNING = "RUNNING";
+    private static final String STATUS_QUEUEING = "QUEUEING";
+    // 阿里云鉴权client
+    IAcsClient client;
+    public File2Text(String accessKeyId, String accessKeySecret) {
+        // 设置endpoint
+        try {
+            DefaultProfile.addEndpoint(ENDPOINTNAME, REGIONID, PRODUCT, DOMAIN);
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        // 创建DefaultAcsClient实例并初始化
+        DefaultProfile profile = DefaultProfile.getProfile(REGIONID, accessKeyId, accessKeySecret);
+        this.client = new DefaultAcsClient(profile);
+    }
+    public String submitFileTransRequest(String appKey, String fileLink) {
+        /**
+         * 1. 创建CommonRequest,设置请求参数。
+         */
+        CommonRequest postRequest = new CommonRequest();
+        // 设置域名
+        postRequest.setDomain(DOMAIN);
+        // 设置API的版本号,格式为YYYY-MM-DD。
+        postRequest.setVersion(API_VERSION);
+        // 设置action
+        postRequest.setAction(POST_REQUEST_ACTION);
+        // 设置产品名称
+        postRequest.setProduct(PRODUCT);
+        /**
+         * 2. 设置录音文件识别请求参数,以JSON字符串的格式设置到请求Body中。
+         */
+        JSONObject taskObject = new JSONObject();
+        // 设置appkey
+        taskObject.put(KEY_APP_KEY, appKey);
+        // 设置音频文件访问链接
+        taskObject.put(KEY_FILE_LINK, fileLink);
+        // 新接入请使用4.0版本,已接入(默认2.0)如需维持现状,请注释掉该参数设置。
+        taskObject.put(KEY_VERSION, "4.0");
+        // 设置是否输出词信息,默认为false,开启时需要设置version为4.0及以上。
+        taskObject.put(KEY_ENABLE_WORDS, true);
+        String task = taskObject.toJSONString();
+        System.out.println(task);
+        // 设置以上JSON字符串为Body参数。
+        postRequest.putBodyParameter(KEY_TASK, task);
+        // 设置为POST方式的请求。
+        postRequest.setMethod(MethodType.POST);
+        // postRequest.setHttpContentType(FormatType.JSON);    //当aliyun-java-sdk-core 版本为4.6.0及以上时,请取消该行注释
+        /**
+         * 3. 提交录音文件识别请求,获取录音文件识别请求任务的ID,以供识别结果查询使用。
+         */
+        String taskId = null;
+        try {
+            CommonResponse postResponse = client.getCommonResponse(postRequest);
+            System.err.println("提交录音文件识别请求的响应:" + postResponse.getData());
+            if (postResponse.getHttpStatus() == 200) {
+                JSONObject result = JSONObject.parseObject(postResponse.getData());
+                String statusText = result.getString(KEY_STATUS_TEXT);
+                if (STATUS_SUCCESS.equals(statusText)) {
+                    taskId = result.getString(KEY_TASK_ID);
+                }
+            }
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        return taskId;
+    }
+    public String getFileTransResult(String taskId) {
+        /**
+         * 1. 创建CommonRequest,设置任务ID。
+         */
+        CommonRequest getRequest = new CommonRequest();
+        // 设置域名
+        getRequest.setDomain(DOMAIN);
+        // 设置API版本
+        getRequest.setVersion(API_VERSION);
+        // 设置action
+        getRequest.setAction(GET_REQUEST_ACTION);
+        // 设置产品名称
+        getRequest.setProduct(PRODUCT);
+        // 设置任务ID为查询参数
+        getRequest.putQueryParameter(KEY_TASK_ID, taskId);
+        // 设置为GET方式的请求
+        getRequest.setMethod(MethodType.GET);
+        /**
+         * 2. 提交录音文件识别结果查询请求
+         * 以轮询的方式进行识别结果的查询,直到服务端返回的状态描述为“SUCCESS”或错误描述,则结束轮询。
+         */
+        String result = null;
+        while (true) {
+            try {
+                CommonResponse getResponse = client.getCommonResponse(getRequest);
+                System.err.println("识别查询结果:" + getResponse.getData());
+                if (getResponse.getHttpStatus() != 200) {
+                    break;
+                }
+                JSONObject rootObj = JSONObject.parseObject(getResponse.getData());
+                String statusText = rootObj.getString(KEY_STATUS_TEXT);
+                if (STATUS_RUNNING.equals(statusText) || STATUS_QUEUEING.equals(statusText)) {
+                    // 继续轮询,注意设置轮询时间间隔。
+                    Thread.sleep(10000);
+                }
+                else {
+                    // 状态信息为成功,返回识别结果;状态信息为异常,返回空。
+                    if (STATUS_SUCCESS.equals(statusText)) {
+                        result = rootObj.getString(KEY_RESULT);
+                        // 状态信息为成功,但没有识别结果,则可能是由于文件里全是静音、噪音等导致识别为空。
+                        if(result == null) {
+                            result = "";
+                        }
+                    }
+                    break;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+    public static void main(String args[]) throws Exception {
+        //从环境变量获取配置的值
+        /*final String accessKeyId = System.getenv().get("ALIYUN_AK_ID");
+        final String accessKeySecret = System.getenv().get("ALIYUN_AK_SECRET");
+        final String appKey = System.getenv().get("NLS_APP_KEY");*/
+        final String accessKeyId = "LTAI5tQ2HmiHCygZkt5BYrYR";
+        final String accessKeySecret = "KhmxTd14SUcXafpFk5yofA43FoeM99";
+        final String appKey = "OKt6jogp6fRjHQVp";
+        String fileLink = "https://gw.alipayobjects.com/os/bmw-prod/0574ee2e-f494-45a5-820f-63aee583045a.wav";
+//        String fileLink = "https://www.w3school.com.cn/i/audio/song.mp3";
+        File2Text demo = new File2Text(accessKeyId, accessKeySecret);
+        // 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
+        String taskId = demo.submitFileTransRequest(appKey, fileLink);
+        if (taskId != null) {
+            System.out.println("录音文件识别请求成功,task_id: " + taskId);
+        }
+        else {
+            System.out.println("录音文件识别请求失败!");
+            return;
+        }
+        // 第二步:根据任务ID轮询识别结果。
+        String result = demo.getFileTransResult(taskId);
+        if (result != null) {
+            System.out.println("录音文件识别结果查询成功:" + result);
+        }
+        else {
+            System.out.println("录音文件识别结果查询失败!");
+        }
+    }
+}

+ 61 - 3
slibra-system/src/main/java/com/slibra/business/service/impl/TCallRecordServiceImpl.java

@@ -1,23 +1,28 @@
 package com.slibra.business.service.impl;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Objects;
 
+import com.alibaba.fastjson2.JSON;
+import com.slibra.business.res.Ele;
 import com.slibra.common.exception.ServiceException;
 import com.slibra.common.utils.DateUtils;
 import com.slibra.common.utils.SecurityUtils;
 import com.slibra.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import com.slibra.business.mapper.TCallRecordMapper;
 import com.slibra.business.domain.TCallRecord;
 import com.slibra.business.service.ITCallRecordService;
 import org.springframework.util.CollectionUtils;
 
+import static com.slibra.common.constant.MyConstants.LONG_1;
+
 /**
  * 通话记录Service业务层处理
  * 
@@ -25,12 +30,20 @@ import org.springframework.util.CollectionUtils;
  * @date 2024-11-11
  */
 @Service
+@Slf4j
 public class TCallRecordServiceImpl implements ITCallRecordService 
 {
-    private static final Logger log = LoggerFactory.getLogger(TCallRecordServiceImpl.class);
     @Autowired
     private TCallRecordMapper tCallRecordMapper;
 
+    @Value("${ALIYUN_AK_ID}")
+    private String accessKeyId;
+
+    @Value("${ALIYUN_AK_SECRET}")
+    private String accessKeySecret;
+
+    @Value("${NLS_APP_KEY}")
+    private String appKey;
     /**
      * 查询通话记录
      * 
@@ -134,4 +147,49 @@ public class TCallRecordServiceImpl implements ITCallRecordService
     public List<HashMap<String, Object>> getAgentList() {
         return this.tCallRecordMapper.getAgentList();
     }
+
+    @Override
+    public String updateFile2TextById(Long id) {
+        //查询数据
+        TCallRecord tCallRecord = this.tCallRecordMapper.selectTCallRecordById(id);
+        if(Objects.isNull(tCallRecord))
+            throw new ServiceException("请输入正确的ID");
+        String url = tCallRecord.getUrl();
+        if(StringUtils.isBlank(url))
+            throw new ServiceException("此次通话记录,未记录录音文件,无法转换");
+        Long hasParsed = tCallRecord.getHasParsed();
+        if(!Objects.isNull(hasParsed) && 1== hasParsed)
+            throw new ServiceException("此次通话记录已经做过转换了,无需重复转换");
+        /*final String accessKeyId = "LTAI5tQ2HmiHCygZkt5BYrYR";
+        final String accessKeySecret = "KhmxTd14SUcXafpFk5yofA43FoeM99";
+        final String appKey = "OKt6jogp6fRjHQVp";*/
+        File2Text file2Text = new File2Text(accessKeyId, accessKeySecret);
+        // 第一步:提交录音文件识别请求,获取任务ID用于后续的识别结果轮询。
+        String taskId = file2Text.submitFileTransRequest(appKey, url);
+        if (taskId != null) {
+            log.info("录音文件识别请求成功,task_id: " + taskId);
+        }
+        else {
+//            log.error("录音文件识别请求失败!");
+//            return "";
+            throw new ServiceException("录音文件识别请求失败!");
+        }
+        // 第二步:根据任务ID轮询识别结果。
+        String result = file2Text.getFileTransResult(taskId);
+        if (result != null) {
+            log.info("录音文件识别结果查询成功:" + result);
+            Ele ele = JSON.parseObject(JSON.parseArray(JSON.parseObject(result).get("Sentences").toString()).get(0).toString(), Ele.class);
+//            log.info(JSON.toJSONString(ele));
+            String text = ele.getText();
+            //同时更新到数据库中去
+            tCallRecord.setHasParsed(LONG_1);
+            tCallRecord.setParsedVoiceContent(text);
+            this.tCallRecordMapper.updateTCallRecord(tCallRecord);
+            return text;
+        }
+        else {
+//            log.error("录音文件识别结果查询失败!");
+            throw new ServiceException("录音文件识别结果查询失败!");
+        }
+    }
 }