GoogleHomeからローカルの音声ファイルをRaspberry pi経由で流す

きっかけ

目的としては、定時にVOICEROIDの音声で通知して欲しいという考えのもと、
ブラウザから音声のキャストも出来るんだし、簡単だろうとやり始めたところ、
意外とつまりポイントが多かったので、備忘録がてら残します。
引用引用アンド引用となっているので、元のサイトを確認することを推奨します。

よくある検索結果と問題点

検索するとまず出てくるのが、
Google Play Musicに手持ちの曲をアップロードすれば流せる」という情報が出てきますが、こちらの情報は今時点では古いです。

Google Play Musicは、現在Youtube Musicへ移行されたのですが、移行先のYoutube Musicにアップロード後、GoogleHomeに曲を流すように話しかけると 「プレミアムへの登録が必要」という返信を貰います。

試してはいないのですが、もしかするとYoutube Music プレミアムに登録するだけでいけるかもしれません。
ですが、今回の目的だけで課金、というのも二の足を踏んでしまうので、今回は使用しません。

そのため、今回は手持ちのRaspberry pi4から流すようにします。

ウェブ上の音声を流すまで

まず、ラズパイから処理を実行するための下準備として環境を最新化します

sudo apt-get update
sudo apt-get upgrade

続いて、node.js、npmをインストールします

sudo apt-get install nodejs npm
sudo npm install n -g

その後、一旦再起動を行います。

再度コンソール画面を立ち上げ、必要なものをインストールします。

sudo apt-get install -y vim git-core libnss-mdns libavahi-compat-libdnssd-dev


続いて、GoogleHomeから音声を再生するためのソフトとして、
google-home-notifierをインストールします。
こちらを使うことによって、好きな音楽を流せたり、自由にしゃべらせることが可能です。
github.com


google-home-notifierの設置フォルダを適当に作成します。

mkdir homebot
cd homebot

プロジェクトの作成とgoogle-home-notifierをインストール

npm init
npm install google-home-notifier

続いて、google-tts-apiのバージョンアップを行います

vim node_modules/google-home-notifier/package.json
  "bundleDependencies": false,
  "dependencies": {
    "body-parser": "^1.15.2",
    "castv2-client": "^1.1.2",
    "express": "^4.14.0",
-    "google-tts-api": "https://github.com/darrencruse/google-tts/tarball/british-voice",
+    "google-tts-api": "0.0.6",
    "mdns": "^2.3.3",
    "ngrok": "^2.2.4"
  },

というように修正をします。

qiita.com


併せて、browser.jsも修正します。

vim node_modules/mdns/lib/browser.js
 Browser.defaultResolverSequence = [
   rst.DNSServiceResolve()
-, 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
+, 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
 , rst.makeAddressesUnique()
 ];


続いてこちらを参考に、mp3をGoogleHomeに再生させるスクリプトの作成をします。
scrapbox.io

vim main.js
 #!/usr/local/bin/node
 const home   = require('google-home-notifier');
 const argv   = process.argv;
 const mp3URL = argv[2];
 const device = argv[3] || '';
 const msg    = 'Say "OK Google, Stop" to stop play music.';
 if (mp3URL === undefined) {
     console.error('usage: play.js <url of mp3> <device id>');
     process.exit(1);
 }
 home.device(device, 'ja');
 home.ip('<GoogleHomeのIPアドレス>');
 home.play(mp3URL, () => console.log(msg));

ただ、google-home-notifierを使ったGoogleHomeでの再生は、
google-home-notifierのREADMEにあるとおり、特にGoogleHomeのIPアドレスを指定しなくても起動出来るようなのです。
ただ、私の環境では

Error: getaddrinfo -3008

というエラーが発生するので、こちらを参考に、IPアドレスを指定することでエラーが解消されました。
qiita.com


GoogleHomeのIPアドレスの確認方法は、GoogleHomeアプリから、デバイス情報を確認することでIPアドレスの確認が出来ます。

support.google.com


ファイルに実行権限を付与して、テストで音声を流してみます。

chmod 755 main.js
./main.js 'http://www.ne.jp/asahi/music/myuu/wave/toccata.mp3' Google-Home

音声ストップをする場合には、通常のGoogleHomeと同様にストップなどと言って止めます。

ローカルの音声を流すまで

この段階ではまだ、ウェブ上の音声を流すにとどまるので、
続いて、ラズパイ内の音声ファイルを流せるように、ファイルサーバーをラズパイ上に立てます。

vim mp3server.js
const fs   = require('fs');
const path = require('path');
const app  = require('express')();
const port = 3000;
app.listen(port, console.log('port: ' + port));
app.get('/audio/:file', (req, res) => {
    const f = req.params.file;
    const p = path.join('audio', f);
    fs.readFile(p, (err, data) => {
        if (err)
            res.status(400).send(err.toString());
        else {
            res.setHeader('Content-Length', data.length);
            res.write(data);
            res.end();
        }
    });
});

ファイルサーバーの稼働確認をします

mkdir audio #音声ファイルの設置フォルダの作成
cp <再生したいMP3のファイル名> audio
node mp3server.js

ブラウザから以下のURLにアクセスし、音声が流れるか音声ファイルがダウンロード出来たら成功です。
http://<ラズパイのIP>:3000/audio/<再生したいMP3のファイル名>`


次に、再起動してもファイルサーバーが稼働するようにします。

Ctrl + c    #簡易MP3サーバを停止
sudo npm install pm2@latest -g #pm2のインストール
pm2 start bin/mp3server.js
pm2 startup systemd
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2
startup systemd -u ??? --hp /home/???
# 表示された指示の通りに、以下のコマンドを実行する
$ sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u <あなたのユーザー名> --hp /home/<あなたのユーザー名>
$ pm2 save #設定の保存
$ sudo reboot #設定確認のため再起動


ラズパイへの音声ファイル転送はSSHから送るようにします

まず、ラズパイ側から設定を行います

sudo raspi-config

から、設定画面を開き、以下を選択
Interfacting Options → SSH

enabled?は<はい>を選択します。


次にWindowsです。
今回はWinSCPを使いました。

転送プロトコルは「SFTP」
ホスト名に先に調べておいたIPアドレス
ポートは22
ユーザー名とパスワードは所定のものを入れてログインします。

ラズパイのデフォルトログインユーザーは、
ユーザー:pi
パスワード:raspberry
となっているはずですが、私の場合は変更していないつもりでしたがログインが出来なかったので、
新規でユーザーを管理者権限を付与して作成し、新規ユーザーからログインしました。

sudo adduser testuser
sudo gpasswd -a testuser sudo 


ファイル転送後、音声ファイルを先ほどのフォルダにセットし、スクリプトを実行することで、GoogleHomeから音声が流れます。

./main.js 'http://<ラズパイのIP>:3000/audio/<音声ファイル名>' Google-Home

おわりに

以上がGoogleHomeから音声を流す手順です。
ここからcronを組むなりで色々な活用が出来るかと思います。

今回の利用方法だけでは、ラズパイにスピーカーをつければいいのでは?という利用方法となっていますが、
google-home-notifierを使えばテキストを読ませることも可能なので、改修すれば時報やウェブページの読み上げなども可能かとは思います。