使用自定义语音协议的Microsoft语音识别(Xamarin Android,Websocket)

时间:2018-04-13 05:44:26

标签: c# websocket xamarin.android speech-recognition microsoft-cognitive

我正在尝试使用针对Xamarin Android的Microsoft认知语音从麦克风构建连续语音识别。我不认为Xamarin有图书馆。文档是:https://docs.microsoft.com/en-us/azure/cognitive-services/speech/api-reference-rest/websocketprotocol

我已经完成了websocket连接的事情,现在我非常坚持将消息发送到websocket服务器。我在文档中注意到了

  

每次发送消息时,我们都必须在特定路径上发送标题

例如,这些标题是设置语音协议的第一个配置,

Path : speech.config
X-Timestamp :   Client UTC clock time stamp in ISO 8601 format
Content-Type :  application/json; charset=utf-8

我正在使用 WebSocketClient ,但我找不到任何设置标头或更改路径的方法。有没有办法设置标题和/或更改路径,以便我可以正确地向服务器发送消息?或者我有错误的看法?

我的第二个问题是 WebSocketClient 没有任何事件处理程序来接收消息,我的工作是:

private static async Task DataReceiving(ClientWebSocket ws)
{
while (true)
{
   ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[1024]);
   WebSocketReceiveResult result = await ws.ReceiveAsync(
   bytesReceived, CancellationToken.None);
   Log.Info("SOCKETRECEIVED",Encoding.UTF8.GetString(bytesReceived.Array, 0, result.Count));
   if (ws.State != WebSocketState.Open)
   {
       Log.Info("SOCKETCLOSED", "CLOSED");
       break;
   }
}
}

但我没有收到任何消息或任何消息。

编辑:

以下是标题的代码,

//List<Tuple<string, string>> Headers <<Contains [Title] and [Content]
foreach (var item in Headers)
{
    message += item.Item1 + " : " + item.Item2 + Environment.NewLine;
}
message += Environment.Newline; // ensure double carriage return

编辑: 这是我发送WAV标题的代码:

using (MemoryStream stream = new MemoryStream())
{
    short channelCount = 1;
    int sampleRate = 1024;
    int bitsPerSample = 16;
    using (var writer = new BinaryWriter(stream, Encoding.UTF8))
    {


        writer.Write("Path: audio"+Environment.NewLine);
        writer.Write("X-Timestamp: " + DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"+Environment.NewLine));
        writer.Write("Content-Type : audio/x-wav"+Environment.NewLine);
        writer.Write("X-RequestId: " + Guid.NewGuid().ToString().Replace("-",string.Empty)+Environment.NewLine);
        writer.Write(Environment.NewLine);

        //chunk ID
        writer.Write('R');
        writer.Write('I');
        writer.Write('F');
        writer.Write('F');

        writer.Write(-1); // -1 - Unknown size

        //format
        writer.Write('W');
        writer.Write('A');
        writer.Write('V');
        writer.Write('E');

        //subchunk 1 ID
        writer.Write('f');
        writer.Write('m');
        writer.Write('t');
        writer.Write(' ');

        writer.Write(16); //subchunk 1 (fmt) size
        writer.Write((short)1); //PCM audio format

        writer.Write((short)channelCount);
        writer.Write(sampleRate);
        writer.Write(sampleRate * 2);
        writer.Write((short)2); //block align
        writer.Write((short)bitsPerSample);

        //subchunk 2 ID
        writer.Write('d');
        writer.Write('a');
        writer.Write('t');
        writer.Write('a');

        //subchunk 2 (data) size
        writer.Write(-1); // -1 - Unknown size
    }
    byte[] result;
    //using (MemoryStream ms = new MemoryStream())
    //{
    //    stream.CopyTo(ms);
    //    result = ms.ToArray();
    //}
    result = stream.ToArray();
    ArraySegment<byte> byteresult = new ArraySegment<byte>(result);
    await _socketclient.SendAsync(byteresult, WebSocketMessageType.Binary, false, CancellationToken.None);
    Log.Info("SENDINGWAV", System.Text.Encoding.UTF8.GetString(result));
}

这是我发送数据字节的代码,

public async Task SendByteHeader(byte[] data)
{
        string s = "";
        s+=("Path: audio" + Environment.NewLine);
        s +=("X-Timestamp: " + DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ" + Environment.NewLine));
        s +=("Content-Type : audio/x-wav" + Environment.NewLine);
        s +=("X-RequestId: " + Guid.NewGuid().ToString().Replace("-", string.Empty) + Environment.NewLine);
        s +=(Environment.NewLine);
        byte[] array = Encoding.UTF8.GetBytes(s);
        List<byte> endres = new List<byte>(array);
        endres.AddRange(data);

        ArraySegment<byte> byteresult = new ArraySegment<byte>(endres.ToArray());
        await _socketclient.SendAsync(byteresult, WebSocketMessageType.Binary, false, CancellationToken.None);
        Log.Info("SENDINGBYTE", Encoding.UTF8.GetString(data));
  }

我在连接开始时运行它:

Task.Run(()=>DataReceiving(_socketclient));

所以,我首先发送了Wav头,然后开始从录制中发送音频字节(我正在使用Plugin.AudioRecording)。 我还没有收到任何消息/回复。

编辑

我每200毫秒向服务器发送一些数据以使其“实时”,但我注意到在发送5-6之后,我的所有SendAsync都对此代码崩溃

await _socketclient.SendAsync(byteresult, WebSocketMessageType.Binary, false, CancellationToken.None);

错误是“无法访问一次性对象(websocket)”。似乎websocket被处理了?或者连接被终止了?

1 个答案:

答案 0 :(得分:2)

  

我正在使用WebSocketClient,但我找不到任何设置标头或更改路径的方法。有没有办法设置标题和/或更改路径,以便我可以正确地向服务器发送消息?或者我有错误的看法?

如果您参考所发布文档的TextWebSocket Message部分。您可以找到以下声明:

  

文本WebSocket消息携带文本信息的有效负载,该文本信息由一段标题和一个由用于HTTP消息的熟悉的双回车换行换行符分隔的主体组成。

这意味着,您使用client.SendAsync()发送给服务的邮件可以包含两部分:标题部分和正文部分,两部分由double-carriage-return newline pair分隔。

  

我的第二个问题是WebSocketClient没有任何事件处理程序来接收消息

关于此问题,您正确执行此操作,您可以在正确发送邮件后再次尝试。该服务将发回它识别的消息。

相关问题