안드로이드는 음성인식(Speech Recognize)기능을 지원하고 있습니다.


그런데 안드로이드에서 지원하는 음성인식이 두가지 방식이라는 사실은 잘 모르시는 분들이 많습니다. 하나는 잘 알려진, 구글 음성인식 검색을 지원하는 음성인식 엔진이며, 다른 하나는 안드로이드 소스에 들어있으며 SpeechRecorder라는 안드로이드 내장 앱 등등에서 쓰이고 있는 Nuance SREC 네이티브 엔진입니다.

안드로이드의 음성인식 엔진은 두가지

구글 음성인식 검색용 엔진은 offline에서는 사용할 수 없었으나 (젤리빈부터 가능), Nuance SREC 엔진은 자체 내장 native 엔진이기때문에 offline에서 사용 가능하다는 장점이 있으며, 아파치 라이선스로 모든 소스가 공개되어 있다는 장점이 있습니다!

최근에 젤리빈에서 지원하기 시작한 오프라인 음성인식 지원은 Nuance SREC을 사용한 오프라인 음성인식이 아닌 것으로 보입니다. (http://forum.xda-developers.com/showthread.php?t=2014946 참조해서 보면 오프라인으로 쓰고자 하는 경우 데이터를 받게끔 되어있습니다. http://www.youtube.com/watch?v=BTARRXP_I24 넥서스 7에서 오프라인 음성인식 사용하기 영상 참조)

반면, 현재 SREC은 영문만 지원하는 단점이 있습니다. (SREC에서 쓰이는 사전도 영문만 있고, grammar도 영문만 지원) 또한 일반적인 grammar 문법은 잘 지원하지만 dictation을 아직 지원하지 않습니다.

Nuance SREC 엔진은 2008/2009년에 공개되었는데도 많이 사용되지 않고 있는 것은 아마도 관련 문서가 아직은 거의 없기 때문이 아닌가 합니다. (혹은 다른 음성인식 라이브러리를 사용한다거나 해서??)
비교적 최근에 데비안 프로젝트에서 Nuance SREC엔진을 포팅하려는 시도가 있는 것 같은데 별다른 진척은 없는 상태입니다. https://github.com/arthurv/srec 참조

추가: Nuance srec을 이용해 kinect를 리눅스상에서 쓸 수 있게 포팅한 (소스를 보면 고친 부분은 거의 없음) 것도 있더군요. http://www.keyboardmods.com/2011/10/kinect-speech-recognition-in-linux.html 이것을 보면 리눅스상에서도 많은 수고 없이도 사용할 수도 있을 것으로 생각됩니다.

그밖에 더 자세한 내용은 다음 사이트를 참조하시기 바랍니다.


Nuance SREC 음성엔진을 사용하는 프로젝트

그런데 Nuance SREC엔진은 안드로이드 SDK API로 지원되지 않으므로, 이 자체 내장 엔진을 이용해서 앱을 만드려면 android.speech.srec.* 소스를 복사해서 사용하는 방식으로 만들어야 합니다. 이와 같은 방식으로 안드로이드 내장 음성인식 엔진 SREC을 사용하는 대표적인 프로젝트/앱이 다음과 같은 것이 있습니다.

소스 예제

android.speech.srec.Recognizer 자바 소스를 살펴보면 다음과 같은 식으로 사용할 수 있다는 주석이 있습니다.
(아래 소스를 조금 보기좋게 해 두었습니다.)
https://github.com/CyanogenMod/android_frameworks_base/tree/jellybean/core/java/android/speech/srec
https://github.com/CyanogenMod/android_frameworks_base/blob/jellybean/core/java/android/speech/srec/Recognizer.java - CyanogenMod 소스

// create and start audio input
InputStream audio = new MicrophoneInputStream(11025, 11025*5);
// create a Recognizer
String cdir = Recognizer.getConfigDir(null);
Recognizer recognizer = new Recognizer(cdir + "/baseline11k.par");
// create and load a Grammar
Recognizer.Grammar grammar =
    recognizer.new Grammar(cdir + "/grammars/VoiceDialer.g2g");
// setup the Grammar to work with the Recognizer
grammar.setupRecognizer();
// fill the Grammar slots with names and save, if required
grammar.resetAllSlots();
for (String name : names) grammar.addWordToSlot("@Names", name, null, 1, "V=1");
// names 배열에 이름을 넣어두면 인식됨 예를 들어 { "hello", "foobar", "kim" }
grammar.compile();
grammar.save("/mnt/sdcard/foo.g2g"); // path를 고쳐둠
// start the Recognizer
recognizer.start();
// loop over Recognizer events
while (true) {
    switch (recognizer.advance()) {
    case Recognizer.EVENT_INCOMPLETE:
    case Recognizer.EVENT_STARTED:
    case Recognizer.EVENT_START_OF_VOICING:
    case Recognizer.EVENT_END_OF_VOICING:
        // let the Recognizer continue to run
        continue;
    case Recognizer.EVENT_RECOGNITION_RESULT:
        // success, so fetch results here!
        for (int i = 0; i < recognizer.getResultCount(); i++) {
            String result = recognizer.getResult(i, Recognizer.KEY_LITERAL);
            Log.d(TAG, "result = " + result); // 인식 결과값 출력
        }
        break;
    case Recognizer.EVENT_NEED_MORE_AUDIO:
        // put more audio in the Recognizer
        recognizer.putAudio(audio);
        continue;
    default:
        // notifyFailure();
        break;
    }
    break;
}
// stop the Recognizer
recognizer.stop();
// destroy the Recognizer
recognizer.destroy();
// stop the audio device
audio.close();

위의 소스를 거의 고치지 않고서 이를 이용해 간단한 샘플 앱을 만들어보니 자체 내장 음성인식 엔진 SREC이 아주 잘 작동하는 것을 확인하였습니다. (아래 링크를 참조하세요)
(이렇게 확인하고 구글링을 더 해보니 2011년에 이미 다른 분이 이 테스트를 해보신 모양입니다 :) http://www.eoeandroid.com/thread-54280-1-1.html 참고)

기타 참고 사이트


요청이 계속 있어서 간단한 앱을 급조했습니다~

(ICS 배포 이후부터 일부 기종은 srec을 제거한 상태인 기종의 경우에 libsrec_jni가 내장되지 않아서 제대로 작동하지 않습니다.)

https://github.com/wkpark/srec-example

컴파일하고 설치한 후에 사용법은 다음과 같습니다.

1. Start 버튼을 누른다.

2. Dial 123 123 같은 식의 VoiceDialer 명령을 내려본다. (이 명령 세트는 VoiceDialer.g2g 그래머 파일에 있는 내용)

(VoiceDialer.g2g는 external/srec/config/en.us/grammars/VoiceDialer.grxml 파일을 참조하세요)

컴파일된 앱: (libsrec_jni.so가 자체 내장된 기종에서만 제대로 작동합니다)

srec-example.apk



by dumpcookie 2013. 3. 16. 23:05

리눅스상에서 자유롭게 쓸 수 있는 오픈소스/자유 소프트웨어 Text-To-Speech(TTS)엔진은 꽤 많으며, 다음과 같은 공개 TTS엔진이 유명합니다.

  • Festivalhttp://www.cstr.ed.ac.uk/projects/festival/ - MIT 형식의 라이선스 (상용 제한 없음) - 대부분의 리눅스 배포판에서 기본으로 설치됨
  • MBROLAhttp://tcts.fpms.ac.be/synthesis/ - 한국어도 지원 (부산대 김경석 교수가 만든 "한말(hanmal)" 음성 지원) - 개인은 자유롭게 쓸 수 있으나, 제한적인 라이선스(상용 안됨)
  • eSpeakhttp://espeak.sourceforge.net/ - GPL 라이선스 - 윈도우 및 안드로이드 지원
  • HTS http://hts.sp.nitech.ac.jp/ - BSD 라이선스 (상용제한 없음) - Google TTS엔진에서 사용한다고 함.
    HTS 관련 문서를 읽어보면 상당히 다양한 프로젝트에서 HTS를 사용하고 있다는 것을 알 수 있으며, 음성 소스만 주어지면 그 목소리에 대응하는 synthesize용 목소리를 만들 수 있습니다!! @@ 단, 데모에서 들을 수 있는 음성은 매우 품질이 좋은 반면, flite나 festival 등등의 다른 프로젝트용으로 만들어진 음성자료를 통해 생성된 음질 썩 좋은 편이 아닙니다.
    (데모 페이지는 http://homepages.inf.ed.ac.uk/jyamagis/demos/page35/page35.html를 비롯한 일련의 페이지)

그러나 이러한 공개 TTS엔진에서 만들어내는 소리가 그렇게 훌륭한 편은 아닙니다. MBROLA가 그중에 가장 나은 소리를 들려준다고 하지만 라이선스가 제한이 있고, Festival가 그나마 들어줄만한 소리를 만들어내지만 안드로이드의 svox-pico보다는 음성의 질이 떨어집니다.

구글 안드로이드 도넛(버전 1.6)부터 자체 내장된 svox-pico TTS엔진은 2008년에 SVOX사에서 공개한 TTS엔진입니다. svox-pico는 소스코드까지 공개된 TTS엔진이며, 공개당시 매우 획기적인 일이였고, 소스 및 실행 바이너리 크기가 상당히 적고 가벼운 편이며, 발음도 훌륭한 편이였습니다.

현재는 IVONA와 같은 안드로이드에서 무료로 쓸 수 있는 TTS엔진이 있기때문에 svox-pico의 인기가 다소 떨어진 편이지만, svox-pico의 소스가 공개되어 있으므로 svox-pico를 리눅스에서도 쓸 수 있게되는 것은 시간문제였습니다. (그런데 검색해보니 관련된 한국어 문서가 전혀 없더군요. 그래서 이렇게 포스팅을 하게 된 것입니다 ;)

svox-pico 소스코드

svox-pico 최신 소스코드를 직접 받고자 하는 경우에는 구글 레포지터리를 통해서 받을 수 있습니다.
https://android.googlesource.com/platform/external/svox.git

여기에는 svox의 소스코드뿐만 아니라 언어팩을 만들 수 있는 툴(윈도우용) 및 메뉴얼도 같이 포함되어 있기때문에, 전체 소스코드의 압축된 크기가 상당히 큽니다.

svox-pico 설치해보기

svox-pico는 우분투나 데비안용 패키지가 이미 수년전에 나와있는 상태입니다. 페도라에서 설치하기 위해서 검색해보니 쉽게 찾을 수 없었으나, ALT 리눅스용 소스 rpm이 있었습니다. ALT리눅스용 소스 rpm을 다운로드 받아서 페도라에 맞게끔 spec파일을 살짝 고치고 빌드하니 아무런 문제 없이 컴파일 할 수 있었으며 실행도 아주 잘 되었습니다.

  • src.rpm은 다음 사이트를 통해서 얻을 수 있었습니다.
    http://sisyphus.ru/en/srpm/Sisyphus/svox-pico
  • pico2wave --wave test.wav "Hello World" 라고 실행하면 test.wav가 얻어집니다.
  • 생성되는 소리는 진저브레드에서 Pico-TTS 엔진을 기본으로 설정했을때에 나오는 소리와 똑같았습니다.
  • git 소스로부터 직접 빌드하려 할 경우라면 http://wiki.freeswitch.org/wiki/Mod_tts_commandline 사이트를 참조하시기 바랍니다.


by dumpcookie 2013. 3. 14. 21:54

mecab 프로젝트에 대해 조금 더 살펴보니 2006년에 만들어진 꽤 오래된 프로젝트였습니다. http://mecab.googlecode.com/svn/trunk/mecab/doc/index.html

mecab 패키지에는 이미 java/perl/python 등등의 바인딩을 지원하지만 php 바인딩만 자체 지원하지 않습니다. 그래서 php 바인딩은 없나 하고 살펴보니 2008년도부터 php바인딩을 지원하는 프로젝트가 있었더군요. https://github.com/rsky/php-mecab by rsky

rpm 패키지는 없나 해서 살펴보니 금방 찾을 수 없어서, 그냥 빌드해봤습니다. (참고로 본인은 Fedora 15 사용중)

  1. 소스를 받고 : 소스가 github의 레포지터리이므로 git clone으로 소스를 받고
  2. php 바인딩 소스 디렉토리에서 phpize 실행
  3. make 명령으로 빌드
  4. modules 디렉토리에 생성된 mecab.so/usr/lib/php/modules 아래에 설치
  5. php.ini 설정

$ git clone https://github.com/rsky/php-mecab
Cloning into php-mecab...
remote: Counting objects: 616, done.
remote: Compressing objects: 100% (249/249), done.
remote: Total 616 (delta 427), reused 548 (delta 359)
Receiving objects: 100% (616/616), 120.44 KiB | 110 KiB/s, done.
Resolving deltas: 100% (427/427), done.
$ cd php-mecab/
$ ls
mecab  packages  README.md
$ cd mecab
$ phpize
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626

그런다음 빌드

$ ./configure
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for a sed that does not truncate output... /bin/sed
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether cc accepts -g... yes
checking for cc option to accept ISO C89... none needed
checking how to run the C preprocessor... cc -E
(중략)
checking whether to build shared libraries... yes
checking whether to build static libraries... no
configure: creating ./config.status
config.status: creating config.h
config.status: executing libtool commands
$ make
... (생략)

php 바인딩 소스 본체가 mecab.c라는 소스가 전부라서 눈깜짝할 사이에 빌드가 됩니다.

빌드된 mecab.so 파일을 다음과 같은 식으로 설치해줍니다.

$ sudo cp modules/mecab.so /usr/lib/php/modules/

다음과 같은 내용을 /etc/php.ini에 넣거나, /etc/php.d/mecab.ini라는 파일을 만들어 추가해줍니다.

extension=mecab.so

다음과 같은 간단한 예제를 examples/* 디렉토리 아래에 있는 다양한 예제를 참고해서 만들어봤습니다.

$dic = './mecab-ko-dic-1.1.3-20130226';
ini_set('mecab.default_dicdir', $dic);

$arg = array();

$mecab = mecab_new($arg);

$str = "PHP-mecab 한글테스트중입니다. 무궁화꽃이 피었습니다";
echo mecab_sparse_tostr($mecab, $str);

mecab_destroy($mecab);

이 파일은 test.php라고 이름붙여 저장하고, mecab용 한글 사전 디렉토리는 현재 디렉토리 아래에 있는 은전한닢 프로젝트의 사전으로 지정하였으며 (./mecab-ko-dic-1.1.3-20130226), 다음과 같이 실행해 보니 아무런 문제없이 잘 실행됨을 볼 수 있었습니다.

$ php test.php
PHP     SL,*,*,*,*,*,*
-       SY,*,*,*,*,*,*
mecab   SL,*,*,*,*,*,*
한글    NN,T,한글,*,*,*,*
테스트  NN,F,테스트,*,*,*,*
중      NNB,T,중,*,*,*,*
입니다  VCP+EF,F,입니다,Inflect,VCP,EF,이/VCP+ㅂ니다/EF
.       SF,*,*,*,*,*,*
무궁화  NN,F,무궁화,Compound,*,*,무궁+화
꽃      NN,T,꽃,*,*,*,*
이      JKC,F,이,*,*,*,*
피      VV,F,피,*,*,*,*
었      EP,T,었,*,*,*,*
습니다  EC,F,습니다,*,*,*,*
EOS

by dumpcookie 2013. 3. 11. 16:06