70 lines
2.4 KiB
C#
70 lines
2.4 KiB
C#
using System.Net.WebSockets;
|
|
using System.Text.Json;
|
|
using Health.Application.Speech;
|
|
|
|
namespace Health.WebApi.Endpoints;
|
|
|
|
public static class SpeechEndpoints
|
|
{
|
|
public static void MapSpeechEndpoints(this WebApplication app)
|
|
{
|
|
app.Map("/api/speech/realtime", async (
|
|
HttpContext http,
|
|
IRealtimeSpeechRecognitionProxy proxy,
|
|
ILoggerFactory loggerFactory) =>
|
|
{
|
|
if (!http.WebSockets.IsWebSocketRequest)
|
|
{
|
|
http.Response.StatusCode = StatusCodes.Status400BadRequest;
|
|
await http.Response.WriteAsJsonAsync(new
|
|
{
|
|
code = 40001,
|
|
data = (object?)null,
|
|
message = "该接口仅支持 WebSocket 连接",
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!proxy.IsConfigured)
|
|
{
|
|
http.Response.StatusCode = StatusCodes.Status503ServiceUnavailable;
|
|
await http.Response.WriteAsJsonAsync(new
|
|
{
|
|
code = 50301,
|
|
data = (object?)null,
|
|
message = "实时语音识别服务尚未配置",
|
|
});
|
|
return;
|
|
}
|
|
|
|
using var socket = await http.WebSockets.AcceptWebSocketAsync();
|
|
try
|
|
{
|
|
await proxy.ProxyAsync(socket, http.RequestAborted);
|
|
}
|
|
catch (OperationCanceledException) when (http.RequestAborted.IsCancellationRequested)
|
|
{
|
|
// 客户端离开页面或断开网络。
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
loggerFactory.CreateLogger("SpeechEndpoints")
|
|
.LogError(ex, "Realtime speech proxy failed");
|
|
if (socket.State == WebSocketState.Open)
|
|
{
|
|
var payload = JsonSerializer.SerializeToUtf8Bytes(new
|
|
{
|
|
type = "error",
|
|
message = "语音服务暂时不可用,请稍后重试",
|
|
});
|
|
await socket.SendAsync(
|
|
payload,
|
|
WebSocketMessageType.Text,
|
|
true,
|
|
CancellationToken.None);
|
|
}
|
|
}
|
|
}).RequireAuthorization(policy => policy.RequireRole("User"));
|
|
}
|
|
}
|