2016-10-09 18 views
-1

먼저 내 목표를 설명하겠습니다. 내가 노력하고있는 목표는 입력 .wav 파일을 제공하고,이를 일종의 음성 인식 API로 보내고 텍스트 파일을 반환하는 것입니다. 내가 염두에두고있는 응용 프로그램은 매우 간단합니다. 문법이나 구두점을 위해 구문 분석 할 필요는 없습니다. 크고 긴 문장을 반환 할 수 있습니다. 괜찮습니다. 내가 말한 각 단어를 텍스트 파일 (.tsv 또는 .csv 형식)로 관찰하여 처리합니다.SAPI 또는 동등하게 사용 가능한 오디오 파일을 텍스트로 오디오

그러나 데이터의 까다로운 부분은 입니다. (검토 한 모든 타사 오디오 필사본 서비스의 95 %가 까다로운 까닭입니다. 사용자에게 이런 종류의 데이터를 제공하지 마십시오.) 내가 필요로하는은 SR이 추측하는 각 단어의 [0.00 - 1.00] 신뢰 점수입니다. 해당 데이터를 .tsv 또는 .csv 형식의 텍스트가 포함 된 텍스트 파일의 새 열에 저장하고 싶습니다.

그게 전부입니다. 그게 내 목표 야. 여기에 관련 게시물에 전문가에서 인용 한 것입니다 :

Convert Audio(Wav file) to Text using SAPI?

SAPI 확실히 당신이 원하는 무엇을 할 수 그것은 내 목표는 가능한 것 같다. in-proc 인식기로 시작하여 은 오디오를 파일 스트림으로 연결하고 받아쓰기 모드를 설정하고 을 사용하면됩니다.

여기가 .WAV 전사 신뢰 점수에 대한 관련 문서입니다 :

https://msdn.microsoft.com/en-us/library/jj127911.aspx 모두가 나에게 문제를 설명하자 지금은 너무 간단 소리 만하게

https://msdn.microsoft.com/en-us/library/microsoft.speech.recognition.recognizedwordunit.confidence(v=office.14).aspx

; 왜 내가 질문을 게시하는지. 문제는 나에게 C++이나 COM에 관해서는 알지 못하기 때문에 나의 목표는 도달 할 수 없다는 것이다. 저는 SAPI가 창일 경험의 일부 였고 헌신적이고 친숙한 사용자 인터페이스를 가지고 있다고 생각했습니다. 그래서 나는이 과정을 더 연구할수록 점차 놀랐다. 그러나 나는 여전히 원칙적으로 이것은 매우 간단한 것이라고 믿습니다. 그래서 나는 낙관적입니다.

저는 파이썬과 약간의 JS에 대한 지식이 있습니다. 나는 파이썬이 다른 언어에 대한 코드 매직을 가지고 있다는 것을 알고있다. 그래서 파이썬이 SAPI와이 인터페이스를 할 수 있다고 확신하지만, C++을 알지 못해서 더 좋을 것 같지 않다.

기술 불일치에도 불구하고 Dragon, Nuance, Chrome 플러그인과 같은 사용자 친화적 인 대안이 필요한 데이터 세분성을 제공하지 않기 때문에 필자는 여전히 SAPI의 일부입니다.

이제 내 질문의 핵심에 도착하자 : 전술 한 바와 같이

  1. 누군가가 내 "목표"의 난이도 나에게 자신의 평가를 줄 수 있습니까? 단일 .bat 파일에서 수행 할 수 있습니까? 예제 코드는 크게 감사하겠습니다.
+0

상당히 개방적인 질문입니다. 아무리 크거나 작게 입력해도 조금이라도 기쁘게 생각합니다. 단지 내가 세계에서 가장 숙달 된 프로그래머가 아니라는 것을 명심하십시오. 따라서이 도메인 별 용어를 모두 파악하지는 못 하겠지만 최선을 다하고 있습니다. –

답변

2

아마도 C# 언어를 강력하게 다루지 않으면 SAPI의 C 인터페이스로 작업하기가 어려울 것입니다. 나는 개념을 테스트하기 위해 당신이 얼마 전에 이야기하고있는 것을 거의 정확하게 수행하는 프로그램을 작성했습니다. 처음 코드 덤프 :

#include "dirent.h" 
#include <iostream> 
#include <string> 
#include <sapi.h> 
#include <sphelper.h> 

int main(int argc, char* argv[]){ 

    DIR *dir; 
    struct dirent* entry; 
    struct stat* statbuf; 
    ::CoInitialize(NULL); 
    if((dir = opendir(".")) != NULL){ 
     while((entry = readdir(dir)) != NULL){ 
      char extCheck[260]; 
      strcpy(extCheck, entry->d_name); 
      if(strlen(extCheck) > 4 && !strcmp(strlwr(extCheck) + strlen(extCheck)-4, ".wav")){ 
       //printf("%s\n",entry->d_name); 
       //1. Find the wav files 
       //2. Check the wavs to make sure they're the correct format 
       //3. Output any errors to the error log 
       //4. Produce the text files for the wavs 
       //5. Cleanup and exit 
       FILE* fp; 
       std::string fileName = std::string(entry->d_name,entry->d_name + strlen(entry->d_name)-4); 
       fileName += ".txt"; 
       fp = fopen(fileName.c_str(), "w+"); 
       HRESULT hr = S_OK; 
       CComPtr<ISpStream> cpInputStream; 
       CComPtr<ISpRecognizer> cpRecognizer; 
       CComPtr<ISpRecoContext> cpRecoContext; 
       CComPtr<ISpRecoGrammar> cpRecoGrammar; 
       CSpStreamFormat sInputFormat; 
       hr = cpRecognizer.CoCreateInstance(CLSID_SpInprocRecognizer); 
       hr = cpInputStream.CoCreateInstance(CLSID_SpStream); 
       hr = sInputFormat.AssignFormat(SPSF_16kHz16BitStereo); 
       std::string sInputFileName = entry->d_name; 
       std::wstring wInputFileName = std::wstring(sInputFileName.begin(), sInputFileName.end()); 
       hr = cpInputStream->BindToFile(wInputFileName.c_str(), SPFM_OPEN_READONLY, &sInputFormat.FormatId(), sInputFormat.WaveFormatExPtr(), SPFEI_ALL_EVENTS); 
       hr = cpRecognizer->SetInput(cpInputStream, TRUE); 
       hr = cpRecognizer->CreateRecoContext(&cpRecoContext); 
       hr = cpRecoContext->CreateGrammar(NULL, &cpRecoGrammar); 
       hr = cpRecoGrammar->LoadDictation(NULL,SPLO_STATIC); 

       hr = cpRecoContext->SetNotifyWin32Event(); 
       auto hEvent = cpRecoContext->GetNotifyEventHandle(); 
       hr = cpRecoContext->SetInterest(SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_END_SR_STREAM), SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_END_SR_STREAM)); 
       hr = cpRecoGrammar->SetDictationState(SPRS_ACTIVE); 
       BOOL fEndStreamReached = FALSE; 
       unsigned int timeOut = 0; 
       //WaitForSingleObject(hEvent, INFINITE); 
       while (!fEndStreamReached && S_OK == cpRecoContext->WaitForNotifyEvent(INFINITE)){ 
        CSpEvent spEvent; 

        while (!fEndStreamReached && S_OK == spEvent.GetFrom(cpRecoContext)){ 

         switch (spEvent.eEventId){ 

          case SPEI_RECOGNITION: 
           { 
            auto pPhrase = spEvent.RecoResult(); 
            SPPHRASE *phrase = nullptr;// new SPPHRASE(); 
            LPWSTR* text = new LPWSTR(L""); 
            pPhrase->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, text, NULL); 
            pPhrase->GetPhrase(&phrase); 

            if(phrase != NULL && phrase->pElements != NULL) { 
             std::wstring wRuleName = L""; 

             if(nullptr != phrase && phrase->Rule.pszName != NULL) { 
              wRuleName = phrase->Rule.pszName; 
             } 

             std::wstring recognizedText = L""; 
             bool firstWord = true; 
             for(ULONG i = 0; i < (ULONG)phrase->Rule.ulCountOfElements; ++i) { 

              if(phrase->pElements[i].pszDisplayText != NULL) { 

               std::wstring outString = phrase->pElements[i].pszDisplayText; 
               std::string soutString = std::string(outString.begin(), outString.end()); 
               if(!firstWord){ 
                soutString = " " + soutString; 
                firstWord = false; 
               } 
               soutString = soutString + " "; 
               fputs(soutString.c_str(),fp); 
               /*if(recognizedText != L"") { 
                recognizedText += L" " + outString; 
               } else { 
                recognizedText += outString; 
               }*/ 
              } 
             } 

            } 
            delete[] text; 

            break; 
           } 

          case SPEI_END_SR_STREAM: 
           { 
            fEndStreamReached = TRUE; 
            break; 
           } 

         } 

         // clear any event data/object references 
         spEvent.Clear(); 
        } 
       } 

       hr = cpRecoGrammar->SetDictationState(SPRS_INACTIVE); 
       hr = cpRecoGrammar->UnloadDictation(); 
       hr = cpInputStream->Close(); 

       fclose(fp); 
      } 
     } 
     closedir(dir); 
    } else { 
     perror("Error opening directory"); 
    } 

    ::CoUninitialize(); 

    std::printf("Press any key to continue..."); 
    std::getchar(); 
    return 0; 
} 

오랫동안 이것을 실행하지 않았지만 dirent.h를 사용해야합니다. 나는 그것을 시험해 보는 것 이상의 다른 이유 때문에 그 도서관에서 놀고 있었다.

제공된 코드를 사용하면 인식 단계에서 어떤 신뢰도 값이 생성되는지 알 수 있습니다. 원하는 경우 일괄 처리 파일에서 실행되도록 조정할 수도 있습니다.

  1. 정확도 문제, 그리고 그것을 개선하기 위해 내가했던 것보다 더 많은 시간이 필요할 거라고 인식기를 훈련해야 할 것입니다 : 내가 직면

    문제는 다음이었다 .

  2. 텍스트로 직접 변환한다는 것이 결국 내가 실제로 원했던 것이 아님을 알게되었습니다. 음소 데이터가 꽤 중요한 것으로 밝혀졌습니다. 이를 통해 자신 만의 확신 계획을 수립하고 자신의 애플리케이션과 관련된 고유 한 대안을 개발할 수 있습니다.
  3. Window Recognizer는 좋지만, 잘 모르는 단어는 인식하지 않습니다. 당신은 어휘를 윈도우의 음성 인식 어휘집에 어떻게 추가하는지 알아 내야 할 것입니다.

그렇다고해서 재고 창문 바탕 화면 음성 인식기를 사용하는 것이 중요하지 않습니다. 기존 API를 살펴 보겠습니다. 클라이언트 측 응용 프로그램에만 국한되지 않으면 다른 API를 살펴 보는 것이 좋습니다.

+0

귀하의 모든 포인트가 잘 받아 들여집니다. SAPI의 능력과 그 한계에 대해 설명해 주셔서 감사합니다. 이것이 SR 프로젝트의 미래를 평가하는 데 필요한 것입니다. –

2

정직하게 말하자면, 귀하의 질문에 설명 된 접근 방식을 고려하면 상당히 어렵습니다. 기존의 SAPI 엔진은 받아쓰기 (예 : Microsoft.Speech.Recognition을 통해 사용할 수있는 "서버"엔진)이나 주어진 음성 (예 : System.Speech.Recognition을 통해 사용 가능한 "데스크톱"엔진)의 세부 정보를 배우기 위해 학습해야합니다.

Windows 런타임 인식기 (Windows.Media.SpeechRecognition)는 받아쓰기를 지원하고 신뢰도 값을 제공하지만 스트림에서 인식을 지원하지 않습니다.

설명하는 접근 방식을 사용하면 Bing Speech API을 사용합니다. 이는 REST API를 통해 원하는 신뢰도 값을 제공하기 때문입니다.