如何将实时音频流端点连接到直线语音端点?

Posted

技术标签:

【中文标题】如何将实时音频流端点连接到直线语音端点?【英文标题】:How to hook real-time audio stream endpoint to Direct Line Speech Endpoint? 【发布时间】:2019-10-09 01:10:00 【问题描述】:

我正在尝试将生成连续音频流的实时音频端点与最终与我的 Azure bot api 交互的 Direct Line Speech (DLS) 端点连接起来。

我有一个 websocket API,可以连续接收二进制格式的音频流,这就是我打算将它转发到 DLS 端点,以便与我的机器人连续使用 Speech2Text。

根据反馈和answer here,我已经能够将我的 Direct Line 语音端点与实时流连接起来。

我尝试了一个示例 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 转换。 我知道 DLS API 支持ListenOnceAsync(),但不确定它是否支持 ASR(它知道对方的发言者何时停止讲话) 我能否只获取 Direct Line Speech 端点的 websocket url 并假设 DLS 正确使用了直接 websocket 流?

【问题讨论】:

我有点困惑,因为您说您正在使用“PullAudioInputStreamCallback”方法来“推送”音频流,然后在代码中我看到您创建了一个推送流。你能说明你在哪里使用这个拉流吗? 我的错,我正在使用 PushAudioInputStream。前段时间我在尝试 Pull,但效果不佳。 我注意到这里有一些潜在的问题。您在没有等待的情况下调用ConnectAsync,因此在您调用ListenOnceAsync 时该任务可能无法完成(也无需等待)。然后,在给这些异步方法中的任何一个完成时间之前,您将同时处理输入流和音频配置。那会是你的问题吗?你只是说代码不起作用,所以我不知道你是看到错误消息还是什么。 【参考方案1】:

我认为我没有正确地将数据分块到 Direct Line Speech 以确保它接收完整的音频以进行正确的 S2T 转换。

DialogServiceConnector.ListenOnceAsync 将一直监听到流关闭(或检测到足够的静音)。您不会关闭您的流,除非您在 using 块的末尾处理它。您可以等待ListenOnceAsync,但您必须确保先关闭流。如果您不等待ListenOnceAsync,那么您可以随时关闭流,但您可能应该在完成写入流后立即执行此操作,并且您必须确保不丢弃流(或ListenOnceAsync 之前的配置)有机会完成。

您还想确保ListenOnceAsync 获得完整的话语。如果您一次只接收 4 个字节,那么这肯定不是完整的话语。如果您想将块保持在 4 个字节,那么在该循环的多次迭代期间保持 ListenOnceAsync 运行可能是个好主意,而不是每获得 4 个字节就一遍又一遍地调用它。

我知道 DLS API 支持 ListenOnceAsync() 但不确定这是否支持 ASR(它知道对方的说话者何时停止说话)

我认为您必须确定扬声器何时停止在客户端说话,然后从您的 WebSocket 收到一条消息,指示您应该关闭 ListenOnceAsync 的音频流。

看起来ListenOnceAsync 确实支持 ASR。

我可以只获取 Direct Line Speech 端点的 websocket url 并假设 DLS 正确使用直接 websocket 流吗?

你可以试试,但我自己不会这么认为。 Direct Line Speech 仍处于预览阶段,我不希望兼容性变得容易。

【讨论】:

如何判断说话者是否停止说话? @bedtym - 如果您也负责客户端代码,那么您可以为所欲为。检测一定程度的静默,检测诸如“结束”之类的关键字,让用户按下按钮,让每个聆听会话持续特定的时间等等。这是您的应用程序。 我知道我可以从客户端做到这一点,我在问是否可以在 DLS 端配置任何东西。如果我要进行 ASR,那就和自己重新构建 DLS 一样好。 @bedtym - 这是一个很好的观点。我做了更多的挖掘,我发现当演讲者停止讲话时,DialogServiceConnector 确实会自行触发 SessionStopped 事件。所以我想这取决于您知道何时调用 ListenOnceAsync(或 StartKeywordRecognitionAsync)。这个答案可以接受吗? 这也是我观察到的行为,我尝试使用它,但问题是 DirectLineSpeech 上的 ASR 过于敏感。假设我在说些什么,然后暂停一秒钟以思考并继续,DLS 端的 ASR 已经停止了会话,机器人已经进入下一个工作流程。我不确定如何解决这个事实有意义吗?

以上是关于如何将实时音频流端点连接到直线语音端点?的主要内容,如果未能解决你的问题,请参考以下文章

通过 socket.io 1.0 实时音频

使用实时流进行语音识别

实时音频流到移动设备 - 动态播放速度

如何在 Python 中进行实时语音活动检测?

是否可以将实时数据发送到 Bing 语音识别?

我可以直接与 Windows 上的音频端点交互吗?