Pythonで文字列やテキストを読み上げる機能を作っていますが、gTTSでやってみました。
とくに問題ないですが、気になるのはmp3ファイルを作って音声を再生していることです。
できれば、直接読み上げさせたいです。もっといいライブラリーとかありますか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
実用的かというと疑問ですが、gTTS(google text to speech)を使ってもファイルへセーブせずにできそうな気がしたのでやってみました。
gTTSにはmp3ファイルへ出力するsaveメソッドの他にwrite_to_fpメソッドというのがありますね。これでmp3形式のままストリームへ書き込むことはできます。
再生についてpygameが簡単そうなので調べてみますとpygame.mixer.music.loadのドキュメントにこう書いてありました。
load(filename) -> None
load(object) -> None
Load a music file for playback
2番目の引数のobjectの意味をgithub: rwobject.cで見てみるとどうやらこれもストリームを想定しているようでした。
そこでファイルの代わりにio.BytesIO
へ音声データを保存して再生できるか試しました。短いテキストだと数十KBぐらいのサイズになりますが、とりあえずは再生できました。
Python
1from gtts import gTTS 2from pygame import mixer 3import time 4import io 5 6 7text = """ 8Open the Pod bay doors, HAL. 9I'm sorry Dave, I'm afraid I can't do that. 10""" 11 12 13def run_tts(t): 14 tts = gTTS(text=t, lang='en', slow=True) 15 f = io.BytesIO() 16 tts.write_to_fp(f) 17 print(' sound size=', f.tell()) 18 f.seek(0, 0) 19 mixer.music.load(f) 20 mixer.music.play(1) 21 while True: 22 time.sleep(0.1) 23 if not mixer.music.get_busy(): 24 break 25 f.close() 26 time.sleep(0.2) 27 28 29if __name__ == '__main__': 30 mixer.init() 31 for t in text.split('\n'): 32 if t == "": 33 continue 34 print('speaking:', t) 35 run_tts(t) 36 mixer.music.stop()
最初長めのテキストを「gTTSから音声データを読みつつ、別のスレッドで並行して再生する」というのをイメージしていたのですが、mixer.music.load/playの挙動を調べてみると最初にストリームの末尾へseekしており「一回ごとにgTTSから完全なMP3フォーマットのデータを読み込んでから再生した方がよさそう」と感じたので上記のような単純なコードにしました。
やってみると結構不安定で、たまにHALが同じ単語を永遠に繰り返し始めます...
ファイルへ保存してから再生するともっと安定するのかどうか。そのあたりはやってみてません。
Windows 10, Python 3.6.0(Python 2.Xではやってみてません)
gTTS 1.2.2
pygame 1.9.3
投稿2018/03/22 08:46
編集2018/03/22 09:00総合スコア18392
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/24 02:42
2018/03/24 03:54