2009-11-05 33 views
5

Tôi đang cố gắng thực hiện nhận dạng giọng nói "streaming" trong C# từ một ổ cắm TCP. Vấn đề tôi gặp phải là SpeechRecognitionEngine.SetInputToAudioStream() dường như yêu cầu một Stream có độ dài xác định có thể tìm kiếm. Ngay bây giờ cách duy nhất tôi có thể nghĩ đến để làm việc này là để liên tục chạy trình nhận dạng trên một MemoryStream làm đầu vào hơn do thỏa thuận hợpĐầu vào trực tiếp vào System.Speech.Recognition.SpeechRecognitionEngine

Dưới đây là một số mã để minh họa:.

  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." 

Có ai biết làm thế nào để có được xung quanh điều này? Nó phải hỗ trợ đầu vào trực tuyến của một số loại, vì nó hoạt động tốt với micro bằng cách sử dụng SetInputToDefaultAudioDevice().

Cảm ơn, Sean

+0

lẽ 'SetInputToDefaultAudioDevice() 'là Microsoft "ma thuật đen"(phổ biến), hoặc nó thực hiện một số loại trạm trộn như bạn đề nghị. –

Trả lời

2

Bạn đã thử gói luồng mạng trong System.IO.BufferedStream chưa?

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

Chỉ cần thử nó, và tôi đã nhận được lỗi tương tự. – spurserh

+0

Bạn có xác minh rằng luồng đệm được hỗ trợ tìm kiếm không? I.e., trong đoạn mã trên, liệu hàm buffStream.CanSeek() có trả về true không? –

1

Tôi đã kết thúc đệm đầu vào và sau đó gửi nó đến công cụ nhận dạng giọng nói trong các khối liên tiếp lớn hơn. Ví dụ, tôi có thể gửi vào lúc đầu tiên 0,25 giây đầu tiên, sau đó 0,5 giây đầu tiên, sau đó 0,75 giây đầu tiên, và như vậy cho đến khi tôi nhận được kết quả. Tôi không chắc chắn nếu đây là cách hiệu quả nhất để đi về điều này, nhưng nó mang lại kết quả thỏa đáng cho tôi.

Chúc may mắn, Sean

+0

Tôi cũng đang gặp sự cố với SAPI và MemoryStreams..chúng tôi không thể làm việc đó mặc dù mọi thứ hoạt động tốt từ đầu vào Mặc định hoặc Tệp. Khi bạn nói rằng bạn đã làm cho nó hoạt động bằng cách sử dụng một bộ đệm, bạn có nghĩa là bạn sử dụng phương pháp BufferStream mà Serguei đề xuất, hoặc bạn chỉ giữ lại sự công nhận cho đến khi MemoryStream lớn hơn? Tôi đã thử cả hai mà không thành công. Bạn có đang sử dụng các sự kiện SpeechHypothesized, SpeechRecognized hoặc buộc RecognitionResult rr = recognizer.Recognize() thường xuyên như vậy không? Bạn có thể đăng thêm bất kỳ mã nào để trợ giúp không? Sẽ được nhiều đánh giá cao. – timemirror

9

tôi đã nhận dạng giọng nói trực tiếp làm việc bằng cách ghi đè các lớp dòng:

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() 
    { 

    } 
} 

... và sử dụng một ví dụ về điều đó như dòng đầu vào cho các phương pháp SetInputToAudioStream. Ngay sau khi luồng trả về độ dài hoặc số được trả lại nhỏ hơn số yêu cầu, công cụ nhận dạng cho rằng đầu vào đã kết thúc. Điều này thiết lập một bộ đệm tròn mà không bao giờ kết thúc.

+0

Hi Sean, tôi đã cố gắng để có được giải pháp của bạn để làm việc nhưng cho đến nay không quản lý nó. Như với những người khác trên tất cả mọi thứ hoạt động tốt từ tập tin đĩa nhưng chỉ không làm việc với MemoryStream. Bạn có thỉnh thoảng đưa ra yêu cầu nhận dạng hay bạn có thể sử dụng các sự kiện SpeechHypothesized, SpeechRecognized? Bạn có thể đăng thêm bất kỳ mã nào để trợ giúp không? Cảm ơn! – timemirror

+0

Xin lỗi, đã bỏ lỡ câu hỏi của bạn, có bạn đi. Với điều đó tôi có thể thực hiện nhận dạng giọng nói thời gian thực và cũng truyền tải nguồn cấp dữ liệu âm thanh qua mạng (một phần của dự án nguồn mở của tôi ispy - http://www.ispyconnect.com) – Sean

+0

Cảm ơn Sean ... . – timemirror

1

Đây là giải pháp của tôi.

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(); 
    } 
} 

Làm thế nào để sử dụng:

//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; 
Các vấn đề liên quan