エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

RaspberryPi + Cloud Text-to-Speech APIで毎朝ニュースを喋ってもらおう

個人的にですが、最近ニュース番組のバラエティ化が進んでいるような気がしている今日この頃です。 ただ最新情報を知りたいだけなのに、CMのCMやら、よく分からない企画を朝から流され、いい加減ウンザリ…

ということで、ラズパイで最新ニュースを拾って喋ってもらおう!と思って作ったのが今回のアプリです。

f:id:tansantktk:20201122122241p:plain

やりたいこと

  • RaspberryPiでニュースを取得するAPI経由でデータを取得し、Cloud Text-to-Speech API(※)を使って生成した音声ファイルを再生させる。
  • 毎朝ニュースを自動で喋らせる。

※Cloud Text-to-Speech APIは他のフリーの読み上げライブラリと比較すると高品質ですが、無料枠付きの従量課金制です。一定以上のAPIリクエストを実施すると有料になりますが、個人で使う分には無料枠内でほぼ収まるかと思います。

cloud.google.com

Cloud Text-to-Speech APIとは何?

  • GCP(Google Cloud Platform)のサービスの1つです。
  • APIに喋らせたい文字列をHTTPリクエストすることで、機械音声を生成し、音声ファイルをレスポンスしてくれます

完成物


RaspberryPi + Cloud Text-to-Speech APIで毎朝ニュースを喋ってもらおう

動画で喋っているのは我が家の2代目のラズパイとなります。 ちなみに名前はtelecasterくんといいます。よろしくおねがいします。 (他にはstratocasterくんとmustangちゃんが稼働中。)

github.com

システム構成図

f:id:tansantktk:20201121210720p:plain

メインの処理はpythonで書きます。 処理フローは以下の通りです。

  1. crontabで特定日時になったらシェルスクリプトを実行。
  2. シェルスクリプトからpythonコードを実行。
  3. pythonコード内でNewsAPIからニュースデータを取得。
  4. Google Cloud Text-to-Speech APIへ喋らせたいニュースデータをリクエスト。
  5. Google Cloud Text-to-Speech APIのレスポンスからを音声を発声。

物理的に必要なもの

  • RasberryPi 3B+
  • スピーカー(入力端子はφ3.5mmステレオミニジャック。ラズパイと接続可能で音が出るなら種類は何でもいいです)

スピーカーは安く済ませたかったのでAmazonで1000円台のものを買いました。 エレコム pcスピーカー USB給電 4W コンパクト ブラック Amazon限定PKG MS-P08UECBK

物理的なものは大体Amazon秋月電子さん辺りで買い揃えられます。 いつもお世話になってます。

秋月電子通商 トップページ - 電子部品・半導体 【通販・販売】

RaspberryPiの実装

動作環境

ラズパイにRaspbianをインストールし、インターネットに接続できる状態にしておいてください。 (説明は省略)

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:    10
Codename:   buster
$ python3 --version
Python 3.7.3

$ pip3 --version
pip 18.1 from /usr/lib/python3/dist-packages/pip (python 3.7)

以降はGitHubソースコードありきで説明していますので、下記リポジトリをラズパイの適当な場所にDLしておきます。

https://github.com/TansanMilMil/news-pi

NewsAPIからニュースを取得する

NewsAPIという外部サービスを利用して、ニュースデータを取得します。 まずはNewsAPIのアカウントを作成し、APIキーを生成します。

newsapi.org

生成したAPIをクエリパラメータに付与して、GETリクエストをすることで、JSONでニュースデータを取得することができるようになります。 クエリとして指定できる値については公式Documentationを参照下さい。 Postmanやターミナル上でcurlしたりしてデバッグしてみても良いと思います。

Everything - Documentation - News API

ここで取得したAPIキーは後で使います。

GCPでCloud Text-to-Speech APIを有効にする

次に任意の文字列を音声として出力してもらう為に、Cloud Text-to-Speech APIを使います。

ここからGCPコンソールで操作をしていきます。 GCPアカウントとプロジェクトがまだ無い場合は、先に作成しておいて下さい。 cloud.google.com

Cloud Text-to-Speech APIを有効にする

GCPコンソールの画面上部の検索ボックスからCloud Text-to-Speech APIを探して専用の画面へ移動し、Cloud Text-to-Speech APIを有効にします。

サービスアカウントキーの作成

公式リファレンスの「認証の設定」に沿ってAPIを利用するためのサービス アカウント キーを作成します。 cloud.google.com

作成後、認証情報が記載された下記のようなjsonファイルがDLされます。 後でpythonコードから参照させますので、読み上げアプリ用ディレクトリに認証情報用のcredentialsディレクトリを作り、その中に入れておきます。(.../alerm-pi/credentials/gcp-service-account.json)

jsonファイルは分かりやすいよう名前をgcp-service-account.jsonに変更しています。 (セキュリティ上、認証情報に関わるファイルはGitHubにはアップしていませんのでご注意下さい。)

gcp-service-account.jsonの中身は下記のようになっているはずです。

gcp-service-account.json

{
      "type": "service_account",
      "project_id": "**************************************",
      "private_key_id": "**************************************",  
      "private_key": "**************************************",
      "client_email": "**************************************",
      "client_id": "**************************************",
      "auth_uri": "https://accounts.google.com/o/oauth2/auth",
      "token_uri": "https://oauth2.googleapis.com/token",
      "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
      "client_x509_cert_url": "**************************************"
}

これらの情報が流出すると誰でもAPIが使えるようになってしまいますので、取り扱いには注意しましょう。

NewsAPI用の認証情報ファイルを作成

NewsAPIを呼び出す為にAPIキーが必要ですが、別ファイルとして切り出しておきたいのでcredentialsディレクトリに追加しておきます。

$ touch alerm-pi/credentials/newsapi.ini
$ vim alerm-pi/credentials/newsapi.ini

newsapi.ini

[DEFAULT]
ApiKey = ***********************************

******の部分は、前の手順で作成したNewsAPIアカウントで利用可能なAPIキーをコピペしてください。

ラズパイにGCPの認証情報をロードさせる

.bashrcを編集し、ラズパイ起動時に認証情報jsonを参照できるようにしておきます。

$ sudo vim ~/.bashrc

.bashrc

export GOOGLE_APPLICATION_CREDENTIALS="/home/pi/alerm-pi/credentials/gcp-service-account.json"

ラズパイで各種ライブラリをインストール

# mp3(効果音)再生用のライブラリをインストール
$ sudo apt install mpg321=0.3.2

# mp3(BGM)再生の為のライブラリをインストール
$ sudo apt install python-pygame=1.9.3
$ pip3 install mutagen==1.44.0

# NewsAPIを使う為のライブラリをインストール
$ pip3 install newsapi-python==0.2.6

# Google Cloud Text-to-Speech APIを使う為のライブラリをインストール
$ pip3 install google-cloud-texttospeech==1.0.1

取得したニュースを喋らせる

あとはシェルスクリプトを実行すれば喋ってくれます。

$ ./alerm-pi/news-pi.sh

5件のニュースをランダムに順番入れ替えした後、Cloud Text-to-Speech APIが喋ってくれます。 BGMとSEは雰囲気作りの為に流してみました。

ちなみにnews-pi.shには第1引数として1~3の数値を渡せるようにしています。
例えば、$ ./alerm-pi/news-pi.sh 3を実行すれば、デフォルトとは違うBGMが流れます。 朝と夕方のニュースを流すときに、別々のBGMを流して雰囲気を変えてみる…なんて時の為の機能です。

私はゴミ出しをよく忘れるので、ニュースを読み上げた後、曜日判定をさせてゴミの日だったら「〇〇曜日は燃えるゴミの日です。...」と喋らせるようにもしています。

news-pi.pygcpspeech.start(...)の引数に喋らせたい文字列を渡せば、いろいろ喋ってくれますのでここら辺はお好みで改変してみて下さい。 ニュースAPI以外にも、喋らせたいデータが取得さえできればいろいろ応用は効くと思います。
今日の天気とか気温を喋らせるのもいいかもしれませんね!

alerm-pi/my_module/gcpspeech.pyはCloud Text-to-Speech API用の処理だけを切り離した自作パッケージです。 ここで記述している値を変えれば、ピッチや声を変えることも出来ます。 詳細は公式リファレンスを確認下さい。
Types for Google Cloud Texttospeech v1 API — google-cloud-texttospeech documentation

crontabで毎朝に自動的に喋らせる

cronで実行させる場合は、.bashrcとは別にGCPの認証情報jsonの場所を記述しておかないと動作しません。

$ crontab -e

crontab

GOOGLE_APPLICATION_CREDENTIALS="/home/pi/alerm-pi/credentials/gcp-service-account.json"

0 8 * * * /home/pi/alerm-pi/news-pi.sh 2

これで毎朝8:00にラズパイがニュースを読み上げてくれます。

余談

  • 今回はとりあえずNewsAPIを使ってみてはいるのですが、NewsAPIで取得できるニュースは、途中で内容がブツ切りになっていたりするので中途半端に喋ることがあります。他のAPIでの実装もアリかと思います。
    • pythonでニュースサイトをスクレイピングして、取得したニュース文字列をラズパイに読み取ってもらうという手もアリですね。
  • ラズパイで再生する効果音によっては音割れする時がありました。音声によって音割れするもの、しないものがあるのですが、音域のせいなのか容量のせいなのか不明。
  • どうしようもないことですが、「ジャパニーズ・カナタナ・イングリッシュ」な単語は正しく読み上げてくれないときが多々あります。これに関しては西洋かぶれ日本人が悪い。

使用素材(BGM, SE)

下記サイトよりフリー素材をお借りしました。ありがとうございます。

www.tam-music.com

dova-s.jp