我按照教程编写了一个可以通过 Twilio SDK 调用的应用程序,该应用程序打开 WebSocket 连接。我正在使用 Spring Boot,现在我希望能够在电话中通话并使用 Azure 认知服务将其转录为文本,并对文本执行一些操作。将文本转换回语音并将其发送到手机。我的问题是,当我说某件事时,我会将其发送到 Azure 并取回,但在手机中它会重复很多次。而不是一次。下面是通过套接字接收和发送消息的方法:
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException, InterruptedException {
JsonNode request = jsonMapper.readTree(message.getPayload());
if (request.path("media").path("track").asText().equals("inbound")) {
String base64EncodedAudio = request.path("media").path("payload").asText();
if (payloads.size() > 200) {
String response = contructResponse(session, request);
session.sendMessage(new TextMessage(response));
payloads.clear();
} else {
payloads.add(base64EncodedAudio);
}
}
}
private String contructResponse(WebSocketSession session, JsonNode request) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String streamSid = request.path("streamSid").asText();
for (int i = 0; i < payloads.size(); i++) {
byte[] decoded = base64Decoder.decode(payloads.get(i));
sessions.get(session).pushData(decoded);
decoded = sessions.get(session).getBytes();
if (decoded != null)
outputStream.write(decoded);
}
byte[] encodedBytes = Base64.getEncoder().encode(outputStream.toByteArray());
return objectMapper.writeValueAsString(new OutBoundMessage("media", new Media(new String(encodedBytes)), streamSid));
}
我的希望是,一旦收到 200 条消息,我将连接这些消息中的音频,进行天蓝色处理,然后发回一条消息,因为列表有效负载在此之后被清除且不超过 200 条。但似乎并非如此。它是否在不同的线程上工作,而所有天蓝色的东西都在另一个线程上进行,并在清除有效负载之前不断添加消息?有人有意见吗?
我不知道到底发生了什么,但我的猜测是,对
constructResponse
和 session.sendMessage
的调用可能比另一条 websocket 消息到达所需的时间更长,因此在您能够之前,会重复该过程清除payloads
。
能否克隆
payloads
,清除原始 payloads
列表,然后将克隆传递给 constructResponse
方法?
类似:
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException, InterruptedException {
JsonNode request = jsonMapper.readTree(message.getPayload());
if (request.path("media").path("track").asText().equals("inbound")) {
String base64EncodedAudio = request.path("media").path("payload").asText();
payloads.add(base64EncodedAudio);
if (payloads.size() > 200) {
// Clone the current members of payloads, I think this will work, excuse the type if it's wrong
ArrayList<String> clonedPayloads = payloads.clone();
payloads.clear();
String response = contructResponse(clonedPayloads, session, request);
session.sendMessage(new TextMessage(response));
}
}
}
然后更改
constructResponse
以接收克隆的有效负载列表作为参数:
private String contructResponse(ArrayList<String> payloads, WebSocketSession session, JsonNode request) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String streamSid = request.path("streamSid").asText();
for (int i = 0; i < payloads.size(); i++) {
byte[] decoded = base64Decoder.decode(payloads.get(i));
sessions.get(session).pushData(decoded);
decoded = sessions.get(session).getBytes();
if (decoded != null)
outputStream.write(decoded);
}
byte[] encodedBytes = Base64.getEncoder().encode(outputStream.toByteArray());
return objectMapper.writeValueAsString(new OutBoundMessage("media", new Media(new String(encodedBytes)), streamSid));
}