Edited at

Google Home+IFTTT+Windows (WSL)でYoutubeから曲名検索して音楽を流す


Google HomeでYoutubeを流す!

いつかGoogle Homeで音楽を簡単に流すサービスが出てくるだろうと気長に待っていましたが、いまだに曲名を指定して無料で音楽を流すことが出来ません。とは言っても、PCと連携させればできるという話は見ていたので、そろそろ試してみようかなとやってみました。

この手の話はラズベリーパイを使ったりしているのが多いのですが、やっぱりINTELのCPUが速度的に良いよねと思っているので、Windows上で構築しました。

ただし、Windowsからだと何故かyoutube-dlが一切反応しなかったので、WSLを使ってほぼLinuxと同じ環境で構築しました。

個人的にはWSL大好きですが、systemctlが使えなかったり、mDNS bonjourのためにavahi-daemonを動かそうとしても無理そうだったりしたので今回はちょっとしんどかったです。

構築したシステムの処理の流れは、

Google Home→IFTTT→自宅のWSL→Google Home

です。


まずはGoole HomeにPCから喋らせる

使用するのは、google home notifierです。

WSLでUbuntuを起動して、

git clone https://github.com/noelportugal/google-home-notifier.git

cd google-home-notifier
vi package.json
# "google-tts-api": "0.0.2", -> "0.0.4"に変更します。ここは年一回くらいで上がるバージョンに更新しないとGoogle Homeが応答してくれなくなるっぽい。

#後でdns_sd.hがないと怒られるので、先にインストール
sudo apt install -y libavahi-compat-libdnssd-dev

#nodejsのインストール
sudo apt install -y nodejs npm
npm install #package.jsonをもとに足りないツールをインストール

vi google-home-notifier.js
#4行目を //var browser = mdns.createBrowser(mdns.tcp('googlecast')); としてコメントアウト

mDNSの解決がWSLでは難しそうだったので、IPアドレスを直接設定する機能だけにして逃げました。

下記のような純粋なjsだけのライブラリだったら大丈夫なのかな。

https://qiita.com/tkyko13/items/163e80d3b65543d6a9da

「こんにちは」と言わせるための、下記のファイルを作成します。


test.js

var googlehome = require('./google-home-notifier');

var language = 'ja';
googlehome.ip('192.168.1.xxx', language); //Google HomeのIPアドレスを入れる
googlehome.notify('こんにちは', function(res) {
console.log(res);
});

Google HomeのIPアドレスは、こんな感じで調べる。

そして、

node test.js

とすると、Google Homeが「こんちには」というはずです。


Youtubeで検索する、音楽ファイルのURLを取ってくる

youtube-dlを使います。

sudo apt-get install youtube-dl

#試しに動くかやってみる
youtube-dl -g -x https://www.youtube.com/watch?v=aFhvWOgg-YU
#これで次のようなメッセージが出てくればOK
#https://r2---sn-nvoxu-ioqe7.googlevideo.com/videoplayback?expire=1570772858&ei=GcOfXbmkOYSNs8IP8bSbsAs&ip=240d%3A1a%3A17b%3A9200%3Ac0b4%3Ab11b%3A6ff8%3A23a7&id=o-AHSRWSLwg6mVJTiQHdb6EX2YXZjhOIk6Ydpka3F7-IuI&itag=251&source=youtube&requiressl=yes&mm=31%2C29&mn=sn-nvoxu-ioqe7%2Csn-ogul7n7s&ms=au%2Crdu&mv=m&mvi=1&pl=44&pcm2=no&initcwndbps=2065000&mime=audio%2Fwebm&gir=yes&clen=771865&dur=46.801&lmt=1541317992068792&mt=1570751139&fvip=5&keepalive=yes&fexp=23842630&c=WEB&txp=5411222&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cpcm2%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=ALgxI2wwRQIhAKBLLV3aSYJgmMjqJx55GUB6xB8rCk3sxDRT8-RJ28u0AiB35Av9mO5a7Hfo38KfaXoVlEgnMos1FG0ZeNtoySOZvQ%3D%3D&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRgIhAIfA3nbxI7p6xum4jTiecJVQZXkzu_nQgwTLugMw1NzGAiEAtFybKA6eiPZuEPvByGeQ4gbORQ8pm0_OA_R2Gqw1lnc%3D&ratebypass=yes


IFTTTの設定

ログインしたら、右上のユーザーのアイコンから「Create」をクリックし、「If」の横の「+」ボタンをクリックしてトリガーを作成する。

トリガーには、「Google Assistant」を選択し、「Say a phrase with a text ingredient」を選択し、「What do you want to say?」には、例えば「youtube $ を流して」とする。

「What do you want the Assistant to say in response?」には、確認のため、「$ ですね」としている。

「Language」は「Japanese」を選択。

終わったら、「Create」を押す。

次に「Then」の横の「+」を押して、「Webhooks」を選択し、自宅のサーバに検索キーワードを送信する。

「URL」には自宅サーバの適当なアドレスを入力。(ルータのポート開放が難しければngrokを使うとよさそう。

ここで、日本語のキーワードを自宅サーバに伝えるためには、下記のように「<<< >>>」で囲う必要あり。(なぜか登録時に表示される「<< >>」だとダメ!) 情報元はこちら

http://XXXXXXXXXX/youtube.php?p=<<<{{TextField}}>>>

それ以外はそのままで「Create action」で良い。


自宅サーバの設定

WSLでapacheの設定が済んでいるとして進めると、まずは検索ワードを引数に渡して音楽をGoogle Homeで流すスクリプトを作成する。

先人のスクリプトを参考に、待ち時間等の改良を加えた下記のスクリプトを作成。

その前に、ここなどを参照して、YoutubeのAPIキーを取得しておいてください。


ytplay.js

#!/usr/bin/node

var ipadd='192.168.1.XXX';
const home = require('./google-home-notifier');
const exec = require('child_process').exec;

const argv = process.argv;
const keyword = argv[2] || '';
const lang = argv[3] || 'ja';
const device = argv[4] || '';

const Youtube = require('youtube-node');
const youtube = new Youtube();

var limit = 1;
var items;
var item;
var title;
var id;

//home.device(device, lang);
home.ip(ipadd, lang);

// 取得したAPIキーを入力する。
youtube.setKey('XXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
youtube.addParam('order', 'viewCount');
youtube.addParam('type', 'video');
youtube.addParam('regionCode', 'JP');

// キーワードから検索し、動画IDやタイトルを取得する。
youtube.search(keyword, limit, {'type':'video', 'videoCategoryId':10}, function(err, result) {
if (err) { console.log(err); return; }
items = result["items"];
for (var i in items) {
item = items[i];
title = item["snippet"]["title"];
id = item["id"]["videoId"];
console.log("id : " + id);

read_youtube_title(title);

var waittime=title.length/4*1000;
setTimeout(function(){
get_url_play(id);
}, waittime);

}
});

function read_youtube_title(title){
home.notify(title, (res) => console.log('said '+ title));
}

// 音楽ファイルのURLを取得し、再生する。
function get_url_play(id){
exec('youtube-dl -g -x https://www.youtube.com/watch?v='+id, function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: '+error);
}
var soundUrl = stdout;
// home.play(soundUrl, (res) => console.log('played '+ soundUrl));
home.play(soundUrl, (res) => console.log('played '+ title));

});
}


そして、足りないモジュールをインストール。

npm install youtube-node

ここまでくると、次のコマンドで引数に渡したキーワードでGoogle Homeに音楽を流すことが確認できます。

node ytplay.js "初音ミク"

最後に、apacheの公開対象となっている/var/www/html以下に次のようなphpファイルを置けば完成です。


/var/www/html/youtube.php

<html>

<body>
<?php
$str = $_GET["p"];
$fp = fopen("youtube.log", "a");
fwrite($fp, date("Y/m/d H:i:s")."\n");
fwrite($fp, "p: ".$str."\n");
fclose($fp);
echo exec('/path/to/google-home-notifier/ytplay.js "'.$str.'"');
?>
</div>
</body>
</html>

以上。

あとは、arpを使ってMACアドレスからIPを自動で取ってくるようにすれば、mDNSなくても良いやと思うけど、そんなにIPアドレス変わらないし、たまに手作業で修正しても良いかなと思ってる。