Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 流式输入到System.Speech.Recognition.SpeechRecognitionEngine_C#_Sockets_Streaming_Speech Recognition_Sapi - Fatal编程技术网

C# 流式输入到System.Speech.Recognition.SpeechRecognitionEngine

C# 流式输入到System.Speech.Recognition.SpeechRecognitionEngine,c#,sockets,streaming,speech-recognition,sapi,C#,Sockets,Streaming,Speech Recognition,Sapi,我正在尝试用C#从TCP套接字进行“流式”语音识别。我遇到的问题是SpeechRecognitionEngine.setInputOAudioStream()似乎需要一个定义长度的流,该流可以搜索。现在,我能想到的唯一方法是,当更多的输入进来时,在MemoryStream上重复运行识别器 下面是一些代码来说明: SpeechRecognitionEngine appRecognizer = new SpeechRecognitionEngine();

我正在尝试用C#从TCP套接字进行“流式”语音识别。我遇到的问题是SpeechRecognitionEngine.setInputOAudioStream()似乎需要一个定义长度的流,该流可以搜索。现在,我能想到的唯一方法是,当更多的输入进来时,在MemoryStream上重复运行识别器

下面是一些代码来说明:

            SpeechRecognitionEngine appRecognizer = new SpeechRecognitionEngine();

            System.Speech.AudioFormat.SpeechAudioFormatInfo formatInfo = new System.Speech.AudioFormat.SpeechAudioFormatInfo(8000, System.Speech.AudioFormat.AudioBitsPerSample.Sixteen, System.Speech.AudioFormat.AudioChannel.Mono);

            NetworkStream stream = new NetworkStream(socket,true);
            appRecognizer.SetInputToAudioStream(stream, formatInfo);
            // At the line above a "NotSupportedException" complaining that "This stream does not support seek operations."
有人知道怎么避开这件事吗?它必须支持某种类型的流式输入,因为它可以使用setInputOdeFaultAudioDevice()与麦克风配合使用


谢谢,Sean

您是否尝试过将网络流包装到System.IO.BufferedStream中

NetworkStream netStream = new NetworkStream(socket,true);
BufferedStream buffStream = new BufferedStream(netStream, 8000*16*1); // buffers 1 second worth of data
appRecognizer.SetInputToAudioStream(buffStream, formatInfo);

我最终缓冲了输入,然后将其以连续较大的块发送到语音识别引擎。例如,我可能先发送0.25秒,然后发送0.5秒,然后发送0.75秒,依此类推,直到得到结果。我不确定这是否是最有效的方法,但它会给我带来令人满意的结果


祝你好运,肖恩(Sean)

显然这是不可能的(“故意的”!)。请参见

我通过覆盖流类实现了实时语音识别:

class SpeechStreamer : Stream
{
    private AutoResetEvent _writeEvent;
    private List<byte> _buffer;
    private int _buffersize;
    private int _readposition;
    private int _writeposition;
    private bool _reset;

    public SpeechStreamer(int bufferSize)
    {
        _writeEvent = new AutoResetEvent(false);
         _buffersize = bufferSize;
         _buffer = new List<byte>(_buffersize);
         for (int i = 0; i < _buffersize;i++ )
             _buffer.Add(new byte());
        _readposition = 0;
        _writeposition = 0;
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return true; }
    }

    public override long Length
    {
        get { return -1L; }
    }

    public override long Position
    {
        get { return 0L; }
        set {  }
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return 0L;
    }

    public override void SetLength(long value)
    {

    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int i = 0;
        while (i<count && _writeEvent!=null)
        {
            if (!_reset && _readposition >= _writeposition)
            {
                _writeEvent.WaitOne(100, true);
                continue;
            }
            buffer[i] = _buffer[_readposition+offset];
            _readposition++;
            if (_readposition == _buffersize)
            {
                _readposition = 0;
                _reset = false;
            }
            i++;
        }

        return count;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        for (int i = offset; i < offset+count; i++)
        {
            _buffer[_writeposition] = buffer[i];
            _writeposition++;
            if (_writeposition == _buffersize)
            {
                _writeposition = 0;
                _reset = true;
            }
        }
        _writeEvent.Set();

    }

    public override void Close()
    {
        _writeEvent.Close();
        _writeEvent = null;
        base.Close();
    }

    public override void Flush()
    {

    }
}
class SpeechStreamer:Stream
{
私人自动存储事件_writeEvent;
私有列表缓冲区;
私有int_缓冲区大小;
私人内部位置;
私人int_写入位置;
私人楼宇重置;
公共演讲拖缆(int bufferSize)
{
_writeEvent=新的自动重置事件(false);
_缓冲大小=缓冲大小;
_缓冲区=新列表(_buffersize);
对于(int i=0;i<\u buffersize;i++)
_Add(新字节());
_readposition=0;
_writeposition=0;
}
公共覆盖布尔可读取
{
获取{return true;}
}
公共覆盖布尔搜索
{
获取{return false;}
}
公共覆盖布尔可写
{
获取{return true;}
}
公共覆盖长长度
{
获取{return-1L;}
}
公众优先多头仓位
{
获取{return 0L;}
集合{}
}
公共覆盖长寻道(长偏移,参见原始坐标系)
{
返回0升;
}
公共覆盖无效设置长度(长值)
{
}
公共重写整型读取(字节[]缓冲区、整型偏移量、整型计数)
{
int i=0;
while(i=_writeposition)
{
_writeEvent.WaitOne(100,true);
继续;
}
缓冲区[i]=_缓冲区[_读取位置+偏移量];
_readposition++;
如果(_readposition==_buffersize)
{
_readposition=0;
_重置=错误;
}
i++;
}
返回计数;
}
公共重写无效写入(字节[]缓冲区、整数偏移量、整数计数)
{
对于(int i=offset;i
。。。并使用该实例作为SetInputOAudioStream方法的流输入。一旦流返回的长度或返回的计数小于请求的长度或计数,识别引擎就会认为输入已完成。这将设置一个永不结束的循环缓冲区。

这是我的解决方案

class FakeStreamer : Stream
{
    public bool bExit = false;
    Stream stream;
    TcpClient client;
    public FakeStreamer(TcpClient client)
    {
        this.client = client;
        this.stream = client.GetStream();
        this.stream.ReadTimeout = 100; //100ms
    }
    public override bool CanRead
    {
        get { return stream.CanRead; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return stream.CanWrite; }
    }

    public override long Length
    {
        get { return -1L; }
    }

    public override long Position
    {
        get { return 0L; }
        set { }
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
        return 0L;
    }

    public override void SetLength(long value)
    {
        stream.SetLength(value);
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        int len = 0, c = count;
        while (c > 0 && !bExit)
        {
            try
            {
                len = stream.Read(buffer, offset, c);
            }
            catch (Exception e)
            {
                if (e.HResult == -2146232800) // Timeout
                {
                    continue;
                }
                else
                {
                    //Exit read loop
                    break;
                }
            }
            if (!client.Connected || len == 0)
            {
                //Exit read loop
                return 0;
            }
            offset += len;
            c -= len;
        }
        return count;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        stream.Write(buffer,offset,count);
    }

    public override void Close()
    {
        stream.Close();
        base.Close();
    }

    public override void Flush()
    {
        stream.Flush();
    }
}
如何使用:

//client connect in
TcpClient clientSocket = ServerSocket.AcceptTcpClient();
FakeStreamer buffStream = new FakeStreamer(clientSocket);
...
//recognizer init
m_recognizer.SetInputToAudioStream(buffStream , audioFormat);
...
//recognizer end
if (buffStream != null)
    buffStream.bExit = true;

可能
setInputOdeFaultAudioDevice()
是Microsoft的“黑魔法”(常见),或者它按照您的建议执行某种批处理。您是否验证缓冲流支持查找?也就是说,在上面的代码中,buffStream.CanSeek()是否返回true?嗨,Sean,我一直在尝试让您的解决方案工作,但到目前为止还没有成功。正如上面提到的其他方法一样,磁盘文件中的所有内容都可以正常工作,但MemoryStream不起作用。您是否偶尔发出识别请求,或者您是否能够使用SpeechAssociated、SpeechReceigned事件?你能发布更多的代码来帮助我吗?谢谢对不起,没有回答你的问题,好了。有了它,我可以进行实时语音识别,也可以通过网络传输音频(我的开源项目ispy的一部分)谢谢Sean…非常好看的项目。你是个天才Sean!您的代码的最新版本工作完美!捕获Skype的输出并针对SAPI运行以进行语音识别。非常感谢您的帮助…您好timemirror您有使用skype的SpeechStreamer的示例代码吗?我在SAPI和MemoryStream方面也有问题。只是无法让它工作,尽管从默认输入或文件中一切都正常。当你说你使用缓冲区工作时,你是说你使用Serguei建议的BufferStream方法,还是说你只是在MemoryStream变大之前停止识别?我两个都试过了,都没有成功。您是否经常使用SpeechResponsized、SpeechRecognited事件或强制识别结果rr=recognizer.recognizer()?您是否可以发布更多代码来提供帮助?非常感谢。