Webサーバ不要!PythonでGoogle Home(Nest)に任意のテキストをしゃべらせてみる

スピーカー

更新日: 2020-12-23

Google Home(2019年にGoogle Nestというブランドに改称)にしゃべりかけると応答してくれるのはとても便利です!我が家でも、天気を聞いたり、エアコンをつけたり、電気を消したり、色々とGoogle Homeを活用しています。

が、そんなに賢いなら自分で能動的にしゃべって色々教えて下さいよ!!

と思ってしまうのは私だけではないでしょう!

今回は、Pythonを使ってGoogle Homeに任意のテキストを音声としてしゃべってもらえるようにしたいと思います。

注意
  • この記事で紹介している方式は、2020年11月頃のgoogle TTS APIの仕様変更により利用できなくなりました。もともとは、google TTS APIはGETリクエストで利用できていたものが、POSTリクエストに変更され、pychromecastのメソッドにURLを渡すだけではaudioファイルをダウンロードできなくなったためです。詳しくは、Switch to the newer Google TTS APIを参照ください。

なぜPythonを使うのか??

今回はPythonを使って、Google homeに喋らせてみます。

なぜPythonを使うのかというと、Windows WSLでも、ChromeOS Linuxでも、CentOSでも、UbuntuでもPythonはデフォルトでインストールされていることが多く、追加でパッケージをインストールする必要がないことが一つ。

もう一つは、機械学習などが得意なPythonで実装できれば、将来的に人工知能っぽくGoogle Homeに喋らせやすいのでは?と思ったことです。

個人的に仕事でPythonばかり使っているので、なんとかPythonで実装したかった!というのも大きな理由です。

もちろん、次で紹介するようにnodeで実装する方法もあります!が、追加でnodeをインストールする必要もあるので、すでにPythonが使える環境があるのであれば、ここの記事で紹介する方法のほうがお手軽にできます!

既存の実装例を解説

すでにGoogle Homeに自発的に喋らせることを実現している人はいっぱいいますので、既存の実装例ということで二つ紹介したいと思います!

Node.jsのgoogle-home-notifierを使う

有名なのは、node.jsのgoogle-home-notifierを使った実装例です。google-home-notifierは、Google TTS (Text To Speech)  APIにアクセスするURLの生成からGoogle Home へのキャストまで全部やってしまう結構便利なライブラリです!

分かりやすくするために、google-home-notifierの内部動作を絵にしてみました。

google home notifierの構成

google-home-notifierは、Google TTS APIから、mp3音声ファイルをダウンロードするためのURLを生成し、Castv2というプロトコルを使ってGoogle Homeに通知します。

音声ファイルのダウンロードURLを受け取ったGoogle Homeは、Google TTS APIに対して、リクエストを発行し、実際に音声ファイルをダウンロードして再生する、という動きになります。

参考記事はこちら。

PythonでgTTS+PyChromecast+WEBサーバを用いて実装!

一方で、Pythonを使ったものは結構面倒な実装しかありませんでした。

これも絵にしてみるとこんな感じです。

google home download from local web server

この実装では、まずGoogle TTS APIを用いて、mp3音声ファイルをダウンロードし、ローカルに保存しておきます。そして、一時的にローカルにWebサーバを立ち上げ、ダウンロードしたmp3ファイルをhttpでダウンロードできるようにしてあげます。

その上で、ダウンロードURLをGoogle Homeに通知して、Google Homeにmp3ファイルを再生させます。

音声ファイルのダウンロードが二回もある上に、ローカルでWEBサーバを立ち上げないといけないので、かなり面倒ですね。

参考にしたのは以下のページです。

Pythonを使ったWebサーバ不要の実装

今回の記事で目標とする実装は、Pythonでgoogle-home-notifierのようなシンプルな構成で実装することです!

Pythonを使ってnode.jsのgoogle-home-notifierのような実装するためには、PythonのgTTSライブラリの実装に問題がありました。

何が問題だったかというと、google TTS APIのURLが取得できない(できなかった)ということ!!音声ファイルをダウンロードしてローカルに保存することしかできませんでした。

Python gTTSライブラリにPR出して修正

ということで、今回この記事を書くために、gTTSのオーナーさんに直接修正のPRを出して、URLを取得できるようにしてもらいました。実際に出したPRはこれ。

オーナーさんの本業が忙しかったようで、マージされるまで時間がかかりましたが、gTTSのv2.1.0以降では、get_urls()というメソッドでURLを取得できるようになっています。

pychromecastとgTTSの使い方

まず実装のサンプルは、以下のページで公開しています。

以下でこの公開しているコードを少し詳しく解説します。

まずは、pychromecastとgTTSをimportします。

import pychromecast
from gtts import gTTS

pychromecastは、Google Home に音声ファイルをキャストするためのライブラリで、gTTSは、Google TTS APIを用いて、テキストを音声ファイルに変換するためのものです。

まずは、pychromecastを使って、chromecast用のクライアントを作成します。今回は以下のように書いてみました。なお、ここのコードは以下の記事を参考にしています。

def get_speaker(ip_addr=None, name=None):
    if ip_addr:
        return pychromecast.Chromecast(str(ip_addr))

    speakers = pychromecast.get_chromecasts()
    if len(speakers) == 0:
        print('No devices are found')
        raise Exception
    if name:
        return next(s for s in speakers if s.device.friendly_name == name)
    return next(speakers)

ip_addrが渡された場合には、固定IPでGoogle Homeを指定します。IP指定の場合は、pychromecast.Chromecast(ip) のように記述します。

ip_addrではなくnameが渡された場合は、pychromecast.get_chromecasts()で返ってきたリストのうち、device.friendly_nameが一致するものを選択して返します。

Google Homeに割り振られているIPの調べ方ですが、Google Homeアプリのデバイスの設定画面の一番下で確認することができます。

Google Home IPアドレス 確認方法

あとは、ここで作成したchromecastクライアントのplay_mediaというメソッドを使うと音声ファイルを再生させることができます。

speaker.media_controller.play_media(url, 'audit/mp3')

urlには、mp3音声ファイルのダウンロードURLを渡します。

ここで渡すurlを生成するために、gTTSライブラリを使用します。使い方は、以下のような感じです。

tts = gTTS(text=text, lang=lang)
urls = tts.get_urls()

上にも書きましたが、gTTS v2.0以前では、このget_urls()というメソッドがなく、URLを生成することができませんでしたが、v2.1.0以降では、URLを生成することができるようになっています。

get_urls()のメソッドが返すのは、URLのリストになっています。

これはなぜかというと、無償でGoogle TTS APIを使う場合の制限として、一度のAPIリクエストでは100文字までしか音声ファイル化できないため、長いテキストの場合には、複数のAPIリクエストに分割する仕様になっているからです。

短いテキストであれば、リストの要素は一つだけですので、その要素を取り出せばOKです!

これらの処理を一つにまとめて以下のように記述してみました。

def speak(text, speaker, lang='en'):
    try:
        tts = gTTS(text=text, lang=lang)
        urls = tts.get_urls()
        if not speaker.is_idle:
            print("Killing current running app")
            speaker.quit_app()
            time.sleep(5)
        speaker.wait()
        speaker.media_controller.play_media(urls[0], 'audit/mp3')
        speaker.media_controller.block_until_active()
    except Exception as error:
        print(str(error))
        raise Exception

最後に、これを使ってGoogle Homeにしゃべらせている動画を載せます。

PythonでGoogle Homeをしゃべらせてみよう!

gTTS v2.1.0以降では、今までNode.jsでしかできなかった構成で、PythonでもGoogle Homeにしゃべらせられるようになりました!

これでわざわざnodeをインストールすることなく、Pythonで好きなテキストをGoogle Homeにしゃべらせることができます。

Pythonは、あらかじめインストールされている環境が多いので、わざわざnodeをインストールしたくない!という人や、Pythonが得意な機械学習と組み合わせてAIっぽくしゃべらせてみたい!という人は、この記事で紹介する方法でGoogle Homeにおしゃべりさせてみてください!

おすすめ記事

  • 超簡単!A-Frameアニメーションの書き方まとめ超簡単!A-Frameアニメーションの書き方まとめ 今回は、VRコンテンツをHTML風に簡単に書けるA-Frameを使って、WordPress記事内に作成した3Dコンテンツにアニメーションをつけてみようと思います!どれも簡単に書けるので試してみると面白いとおもいます! ちなみに、A-Frameでアニメーションを記述する際 […]
  • Pythonでネットワークグラフを描くならNetworkx + Plotlyが便利!Pythonでネットワークグラフを描くならNetworkx + Plotlyが便利! 今回は、Pythonでネットワークグラフを描いてみましたので、その方法を詳しく記事にしたいと思います。 仕事では、ほとんどPythonを使っているのですが、物と物との関係性を自動でサクッと可視化できたら便利だろうと思い、色々調べてみた結果、今回のnetworkx と […]
  • 革新的なアイデアを生み出すための重要ポイントをまとめてみた!革新的なアイデアを生み出すための重要ポイントをまとめてみた! 私がこの記事を書こうと思ったきっかけは、以下の本を読んで、日本人はイノベーションを起こすことが苦手ではなく、日本社会にありがちな組織がイノベーションを生み出すことを邪魔している!ということが書かれていたからです。なんてもったいないことでしょうか!! アメリカや中国では、イ […]
  • 20代独身で中古マンションを購入したら5年後こうなった!マンション購入体験記20代独身で中古マンションを購入したら5年後こうなった!マンション購入体験記 おそらく人生で最も大きな買い物になるであろう住宅購入。誰もが即断できるような買い物ではありません。そんな大きな買い物であるマンション購入を25歳しかも独身でやってしまった私の体験を記事としてまとめてみようと思います! 今や多くの人が生涯独身を貫く時代、独身でマンション購 […]
  • 子供の才能を引き出す教育方式まとめ(保存版)子供の才能を引き出す教育方式まとめ(保存版) この記事では世の中の有名な教育方式についてまとめ、全ての方式に共通する部分を考察してみました! 大変幸運なことに、我が家にもかわいい長女が無事に産まれました。初めに産まれたばかりのこの子を見ていて思ったのは、一体この子はどのような大人に育つのだろうか?どのような才能・能力を持 […]
  • Nature Remo + Python + Heroku でお家データを定期計測してみよう!Nature Remo + Python + Heroku でお家データを定期計測してみよう! Nature Remoというスマートリモンコンを購入しました! Nature […]

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA