렌파이에는 대사를 TTS로 읽어주는 황당하지만 쓸만한 기능이 들어있습니다. (황당하지만 쓸만하다니. 무슨 소리일까요?) https://www.renpy.org/doc/html/self_voicing.html#speech-synthesis


링크를 보시면 일단 PC에 한해 해당 기능이 동작하지만 윈도우는 SAPI의 기능을 써서 사용하고 Mac은 Siri와 같은 엔진을 사용합니다. 리눅스는 기본으로 espeak을 사용하는데 특징으로는 한국 사람이 아니라 무슨 외국인이 한국어를 하는 듯한 느낌이 듭니다. 그냥 안 쓰는게 나을 듯 합니다.


Android 부분을 보시면 TTS 기능이 지원이 안 된다고 합니다. 하지만 안드로이드에는 자체적으로 TTS가 내장되어 있습니다. 솔직히 마음먹기에 따라 이걸 끌어다가 사용하면 될 것도 같은데요. 조금 더 찾아봤습니다. 


기본적으로 안드로이드 TTS를 사용하기 위해서는 자바를 써야하는데요. 렌파이의 안드로이드는 NDK로 SDL과 파이썬을 굴리며 JNI를 통해 안드로이드 앱을 만드는 방식입니다. 그러니까 지원이 되기 위해서는 JNI 부분을 건드려야 한다는 말입니다. 


찾다보니 이런 놈이 있더군요. python for android. https://github.com/kivy/python-for-android 파이썬으로 안드로이드 앱을 만들 수 있는 물건입니다. QT하고 조합도 가능한 듯 합니다. 하지만 이걸 쓰면 렌파이를 뜯어 고쳐야 합니다. 여기에 연관된 물건 중 하나가 있더군요.

pyjnius란 라이브러리 입니다. http://pyjnius.readthedocs.io/en/latest/android.html

파이썬을 JNI로 감싸서 자바에서 사용하는 물건인 듯 합니다. Jython하고 관계가 약간은 있을 겁니다. 파이썬 스크립트를 자바에서 사용하고 자바의 라이브러리를 파이썬으로 가져와서 사용하는 등 그냥 Jython의 느낌이 다분한 라이브러리 입니다.


여기를 잘 보시면 안드로이드의 TTS를 가져오는 부분이 있습니다. 제일 아래에 있습니다.

http://pyjnius.readthedocs.io/en/latest/android.html#using-texttospeech


렌파이에는 Python 코드를 그냥 실행하는 기능이 있으니 이 라이브러리를 가져와서 쓰게 하기만 하면 안드로이드 TTS를 그냥 쓸 수 있겠다는 생각이 들었습니다.


"이거 괜찮겠는데? 일단 라이브러리를 적용하는 것부터 해야겠다."


그런데...무언가 이상하더군요. pyjnius의 설명의 예시에

org.renpy.android.PythonActivity

이게 끼어있습니다. 조금 더 찾아봤습니다.


https://lemmasoft.renai.us/forums/viewtopic.php?f=8&t=27165#p328793

"Ren'Py includes pyjinus"

네...그렇습니다. 렌파이는 이미 이 라이브러리를 쓰고 있던 것이었습니다. 이쯤되니 "어째서 TTS가 지원이 안 된거지?" 라는 생각이 들더군요.


일단 제가 알아낸 것으로는 렌파이에서 PythonActivity란 클래스는 사라지고 PythonSDLActivity로 바뀌었습니다. 그런데 이것도 엄밀히 말하면 Android Activity이니 문제는 없을 겁니다. 그렇다면....renpy엔진을 뜯어 고쳐서 Say 함수가 호출 될 때 TTS가 작동되게 하면 되겠다는 생각이 들었습니다.


아 참고로 Say함수는 renpy/exports.py에 들어있습니다. renpy.say(who,what)이게 API라더군요. 그럼 이 API를 수정하면 그만이겠지요. 후후


즉, 또 삽질입니다. 마침 Sunrider Academy의 번역도 찰지고 하니 이를 이용하면 재미있을 듯 합니다. 안드로이드TTS는 삼성TTS나 구글TTS같이 찰진(?) 목소리들이 많으니 이를 이용하면 재미있을 듯 합니다. 물론 어떻게 될지는 저도 모릅니다. 일단 해봐야지요. 후후


일단 export.py의 SAY함수안에 다음 코드를 끼워넣었는데...

    if renpy.android:
        import sys
        reload(sys)
        sys.setdefaultencoding('utf-8')
        #print str(what)
        from jnius import autoclass
        Locale = autoclass('java.util.Locale')
        PythonActivity = autoclass('org.renpy.android.PythonSDLActivity')
        TextToSpeech = autoclass('android.speech.tts.TextToSpeech')
        #tts = TextToSpeech(PythonActivity.mActivity, None)

        tts = PythonActivity.mActivity.tts

        tts.setLanguage(Locale.getDefault())
        tts.speak(str(what), TextToSpeech.QUEUE_FLUSH, None) 


일단 컴파일은 됩니다만 TTS엔진 세팅이 덜 되었다고 나옵니다. 대체 뭘까요...?


아무래도 Activity쪽 문제라 생각되어서 renpy/rapt/src/org/renpy/android/PythonSDLActivity.java


여기를 수정해서 TTS엔진을 미리 끌어 오는 것으로 수정 했습니다.


일단 첫줄에

public class PythonSDLActivity extends SDLActivity {

...

}


이 부분에 TTS엔진의 인터페이스를 추가합니다.


public class PythonSDLActivity extends SDLActivity implements
        TextToSpeech.OnInitListener{

private TextToSpeech tts;

...

}


요렇게 수정합니다.


그리고 onCreate()에


tts = new TextToSpeech(this, this);


이 한 줄을 추가해서 tts객체를 하나 만듭니다. 물론 onDestroy()에도


tts.Shutdown();

을 추가해서 종료될 때 tts엔진을 같이 종료하게 만듭니다.


그리고 제일 중요한 oninit()함수


    @Override
    public void onInit(int status) {
 
        if (status == TextToSpeech.SUCCESS) {
 
            int result = tts.setLanguage(Locale.getDefault());
 
            if (result == TextToSpeech.LANG_MISSING_DATA
                    || result == TextToSpeech.LANG_NOT_SUPPORTED) {
                Log.e("TTS", "This Language is not supported");
            } else {
                //아무짓도 하지 않는다...
            }
 
        } else {
            Log.e("TTS", "Initilization Failed!");
        }
 
    } 


그냥 어디서 Copy 해 온 것인데 TTS가 제대로 작동 하는지에 대해 로그를 남깁니다. 일단 컴파일은 됩니다. 문제는 이게 실행이 되느냐인데...으음...?


... 좀 많이 삽질해서 성공 했습니다...뭔가 이상하기는 하지만(...)


그런고로 수정된 파일을 올리겠습니다.


PythonSDLActivity.java는 renpy 설치된 곳/rapt/src/org/renpy/android/PythonSDLActivity.java


여기에 덮으시고


export.py는 renpy 설치된 곳/renpy에 덮으시면 됩니다.


6.99.10기준입니다. 여차하면 diff파일도 하나 추가하지요.


PythonSDLActivity.java

exports.py

TTS가 돌아가는 동영상도 하나 올리겠습니다.

,