feat(archive-service): add ASR voice recognition feature

新增ASR语音识别客户端,当语音类型的归档消息上传到COS后,异步调用ASR服务进行识别,并将识别结果更新到数据库中
This commit is contained in:
jqb 2026-06-26 17:17:11 +08:00
parent a5b4f93227
commit c4d993a9f5
2 changed files with 107 additions and 0 deletions

View File

@ -0,0 +1,99 @@
package com.artedu.archive.service;
import com.artedu.archive.entity.ArchiveMessage;
import com.artedu.archive.mapper.ArchiveMessageMapper;
import com.artedu.common.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
* ASR 语音识别服务客户端
* 语音上传到 COS 后,调用该服务进行识别
*/
@Slf4j
@Service
public class AsrClient {
private static final String ASR_URL = "http://8.159.132.53:8000/api/asr/recognize";
@Autowired
private RestTemplate restTemplate;
@Autowired
private ArchiveMessageMapper archiveMessageMapper;
/**
* 异步调用 ASR 识别(避免阻塞媒体上传主流程)
*/
@Async
public void recognizeAsync(Long archiveMessageId) {
if (archiveMessageId == null) {
return;
}
try {
recognize(archiveMessageId);
} catch (Exception e) {
log.error("ASR 识别异步调用失败: archiveMessageId={}", archiveMessageId, e);
}
}
/**
* 同步调用 ASR 识别
*/
public String recognize(Long archiveMessageId) {
if (archiveMessageId == null) {
return null;
}
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, Object> body = new HashMap<>();
body.put("archive_message_id", archiveMessageId);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
ResponseEntity<String> response = restTemplate.postForEntity(ASR_URL, request, String.class);
String responseBody = response.getBody();
log.info("ASR 识别调用成功: archiveMessageId={}, status={}, response={}",
archiveMessageId, response.getStatusCode(), responseBody);
// 解析响应,如果返回了 content,同步更新到 archive_messages 表
if (responseBody != null && !responseBody.isEmpty()) {
try {
Map<String, Object> result = JsonUtils.fromJsonMap(responseBody);
if (result != null && Boolean.TRUE.equals(result.get("success"))) {
Object contentObj = result.get("content");
if (contentObj != null) {
String content = contentObj.toString().trim();
log.info("ASR 识别内容: archiveMessageId={}, content={}", archiveMessageId, content);
if (!content.isEmpty() && archiveMessageMapper != null) {
ArchiveMessage update = new ArchiveMessage();
update.setId(archiveMessageId);
update.setContent(content);
archiveMessageMapper.updateById(update);
log.info("ASR 识别内容已更新到 archive_messages: archiveMessageId={}", archiveMessageId);
}
}
}
} catch (Exception parseEx) {
log.warn("ASR 响应解析或更新失败: archiveMessageId={}", archiveMessageId, parseEx);
}
}
return responseBody;
} catch (Exception e) {
log.error("ASR 识别调用失败: archiveMessageId={}", archiveMessageId, e);
return null;
}
}
}

View File

@ -50,6 +50,9 @@ public class CosStorageService {
@Autowired
private ArchivePullService archivePullService;
@Autowired
private AsrClient asrClient;
private static final String MEDIA_CACHE_DIR = "/app/media";
/**
@ -257,6 +260,11 @@ public class CosStorageService {
mediaFile.setStatus(1);
archiveMediaFileMapper.insert(mediaFile);
// 语音文件上传到 COS 后,异步调用 ASR 识别
if ("voice".equals(message.getMsgtype())) {
asrClient.recognizeAsync(message.getId());
}
return cosUrl;
}