Tornadoを使ってみる

音声合成機能


こちら
こちらな どにWeb Speech API(Speech Synthesis API)による音声合成機能が紹介されています。
音声合成機能はブラウザーの機能なので、テンプレート内でJavaScriptを呼び出す必要が有ります。
tornadoのテンプレート内で、どうやってJavaScript側に変数を渡すのか、色々調べましたが
こ ちらに解決策が有りました。

そこで、簡単なサンプルを紹介します。
こちらがpythonコードです。
テンプレート(speak.html)にtextの変数名で音声合成させたいテキストを渡しています。
import tornado.httpserver
import tornado.ioloop
import tornado.web
from tornado.options import define, options
import os.path
import logging

define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("speak.html", text="Web Speech API を使ってみよう!")

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r'/', IndexHandler)],
        template_path=os.path.join(os.path.dirname(__file__), "templates"),
        static_path=os.path.join(os.path.dirname(__file__), "static"),
        debug=True
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

こちらがテンプレート(speak.html)です。
JavaScriptを実行するだけなので、headもbodyも有りません。
これでpythonから渡ってくるtext変数をJavaScriptに取り込むことができます。
<script>
  text = '{% raw text %}'
  //alert(text);
  speechSynthesis.speak(new SpeechSynthesisUtterance(text));
</script>

今回使用したブラウザーはGoogle Chromeです。
これだけで、ブラウザーが喋ってくれると思いましたが、Google Chromeではボタンクリックなどのユーザー操作が伴わない音声合成は禁止となっています。
ページを開いただけで勝手にベラベラ喋られたら、確かに迷惑です。

Google Chromeの場合、以下のページで音声合成を許可するページを追加することができます。
設定を変更後にブラウザーを起動すると、「Web Speech API を使ってみよう!」と喋ってくれるようになりました。




こちら
のページによると、Web Speech APIは以下のブラウザーで対応しているようですが、おそらくどのブラウザーでもChromeと同様に
許可を与える必要が有ると思います。

- Safari 9.1.2 (11601.7.7) + OS X El Capitan10.11.6
- Chrome 54.0.2840.71 + OS X El Capitan10.11.6
- Opera 41.0.2353.69 + OS X El Capitan10.11.6
- Firefox 49.0.2 + OS X El Capitan10.11.6
- iOS Safari 10.0 + iOS10.11
- Edge 38.14393.0.0 + Windows10



テンプレート(speak.html)を以下の様に変更すると、10秒ごとにページをリロードします。
また、python側から渡されるテキストが無いときは何も喋らなくなります。
<script>
  setTimeout(function () {
    location.reload();
  }, 10000);
  text = '{% raw text %}'
  //alert(text);
  if (text.length > 0) {
    speechSynthesis.speak(new SpeechSynthesisUtterance(text));
  }
</script>

pythonコードを以下の様に変更するとdata/speaktext.txtに書き込まれた最後の行を1回だけ喋ります。
import tornado.httpserver
import tornado.ioloop
import tornado.web
from tornado.options import define, options
import os.path
import logging

define("port", default=8000, help="run on the given port", type=int)
define("speakPath", default="data/speaktext.txt", help="run on the given file path", type=str, metavar="PATH")

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        logging.info("Index:get")
        logging.info("os.getcwd()={}".format(os.getcwd()))
        logging.info("speakPath={}".format(options.speakPath))
        speakFilePath=os.path.join(os.getcwd(), options.speakPath)
        logging.info("speakFilePath={}".format(speakFilePath))

        data = ""
        if (os.path.exists(speakFilePath)):
            with open(speakFilePath, 'r') as f:
                lines = f.readlines()
                print("lines={}".format(lines))
            data = lines[-1:][0]
            data = data.replace('\n','')
            print("data={}".format(data))
            os.remove(speakFilePath)

        self.render("speak.html", text=data)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers=[(r'/', IndexHandler)],
        template_path=os.path.join(os.path.dirname(__file__), "templates"),
        static_path=os.path.join(os.path.dirname(__file__), "static"),
        debug=True
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

別のターミナルから以下のコマンドで、喋るテキストを与えることができます。
連続して書き込んでも最後の行しか取り出さないので、「5行目の内容です」を喋ります。
これで好きな時に好きな言葉を喋るアプリが完成します。
echo "1行目の内容です" >> data/speaktext.txt
echo "2行目の内容です" >> data/speaktext.txt
echo "3行目の内容です" >> data/speaktext.txt
echo "4行目の内容です" >> data/speaktext.txt
echo "5行目の内容です" >> data/speaktext.txt

続く...