[我正在尝试连接实时音频终结点,该终结点将与直接语音(DLS)终结点产生连续的音频流,并最终与Azure机器人api进行交互。
我有一个websocket API,可以连续接收二进制格式的音频流,这就是我打算将其转发到DLS端点,以便与我的机器人进行连续Speech2Text的过程。
基于反馈和answer here,我已经能够将实时语音端点与实时流连接起来。
我尝试了一个示例wav文件,该文件已被DLS正确转录,并且我的机器人可以正确检索文本以对其进行操作。
我已经使用ListenOnce() API,并且正在使用PushAudioInputStream方法将音频流推送到DLS语音端点。
下面的代码是ListenOnce()方法的内部
// Create a push stream
using (var pushStream = AudioInputStream.CreatePushStream())
{
using (var audioInput = AudioConfig.FromStreamInput(pushStream))
{
// Create a new Dialog Service Connector
this.connector = new DialogServiceConnector(dialogServiceConfig, audioInput);
// ... also subscribe to events for this.connector
// Open a connection to Direct Line Speech channel
this.connector.ConnectAsync();
Debug.WriteLine("Connecting to DLS");
pushStream.Write(dataBuffer, dataBuffer.Length);
try
{
this.connector.ListenOnceAsync();
System.Diagnostics.Debug.WriteLine("Started ListenOnceAsync");
}
}
}
以上代码中的dataBuffer是我在Websocket上接收到的二进制数据的“块”。
const int maxMessageSize = 1024 * 4; // 4 bytes
var dataBuffer = new byte[maxMessageSize];
while (webSocket.State == WebSocketState.Open)
{
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(dataBuffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
Trace.WriteLine($"Received websocket close message: {result.CloseStatus.Value}, {result.CloseStatusDescription}");
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
else if (result.MessageType == WebSocketMessageType.Text)
{
var message = Encoding.UTF8.GetString(dataBuffer);
Trace.WriteLine($"Received websocket text message: {message}");
}
else // binary
{
Trace.WriteLine("Received websocket binary message");
ListenOnce(dataBuffer); //calls the above
}
}
但是以上代码不起作用。我相信我对此方法有几个问题/疑问-
我相信我没有正确地将数据分块到Direct Line Speech,以确保其接收到完整的音频以进行正确的S2T转换。
DialogServiceConnector.ListenOnceAsync
会监听,直到关闭流(或检测到足够的静音)。除了在using块的末尾处理流之外,您不会关闭流。您可以等待ListenOnceAsync
,但必须确保先关闭流。如果您不等待ListenOnceAsync
,则可以随时关闭流,但是您可能应该在完成向流的写入后立即进行操作,并且必须确保不丢弃流(或ListenOnceAsync
之前的配置)。
您还想确保ListenOnceAsync
完整发声。如果一次只接收4个字节,那肯定不是一个完整的话语。如果您希望将块保持为4个字节,那么最好在该循环的多次迭代中保持ListenOnceAsync
运行,而不是每获得4个字节就反复调用它。
我知道DLS API支持ListenOnceAsync(),但不确定是否支持ASR(它知道另一侧的扬声器何时停止讲话)
我认为您必须确定发言人何时停止在客户端停止讲话,然后从WebSocket收到消息,指示您应关闭ListenOnceAsync
的音频流。
看起来ListenOnceAsync
确实支持ASR。
我能否仅获取直接语音端点的websocket URL,并假设DLS正确使用了直接websocket流?
您可以尝试,但我不会认为自己。直线语音仍处于预览状态,我不认为兼容性会很容易。