Google Home に喋らせる

自発的に Google Home に喋らせたい。

喋らせている人たちはローカルの Google Home に対してローカルネットワーク内のラズパイなどで API 叩いて喋らせるみたいな感じになっている。

ググるgoogle-home-notifier が主流に見えるが、ラズパイで動かすにはセットアップに一手間いる。Go 製の homecast があるのでバイナリを置くだけにしたい。

どういう仕組みか

  • Google Home を探して音声再生 API を叩く
  • 再生する音源は Google Translate で利用されている text-to-speech を利用している

Google Home を探す

HashiCorp の mdns という mDNS のクライアントを利用して探している。Google Home のホスト名には _googlecast._tcp というサービス名が含まれ、付加情報部には md=Google Home が含まれるのでこれでフィルタリングする。

Google Home が複数台ある場合などはホスト名を控えておいて個別に操作することになりそう。

喋らせる

Google Text to Speech に再生させたい文字列を渡して音声ファイルの URL を取得する。 go-cast を使い、Google Home で音声ファイルを再生する。

Google Cast SDK を見るに Chromecast と API の互換性があるようだ

https://translate.google.com/translate_tts を叩く Text to Speech の使い方は非公式なのでいつか使えなくなるかもしれない。その場合は音声ファイルを生成してどっかに置いておく必要がある。

YAPC::Okinawa 2018 ONNASON に行った

昨日飲みすぎて午前中は倒れてたけど午後から行った。

自分がベストトーク賞に投票した発表はこれ。

  • 小さく一つの仕事に集中させる意思を持ち、妥当そうな設計で Production Ready なミドルウェアを書き上げるのがすごい
  • WS をアプリからクライアントへの通知だけに使って、クライアントからの書き込みは REST API というパターンは参考になる

沖縄に友達を作りに行ったつもりだったけど県外からの人が案外多くて、路線バスで帰る人たちは沖縄に家がある人なのでその人たちと少し喋ったくらいだった。地域コミュニティへ遊びに行かなくては。

1日で終わる YAPC って初めてだった。サクッと楽しめていい。2日あったりすると1日目の夜がピークになって2日目疲れてる。ともかく運営やトークした皆さんはお疲れ様でした。

Docker for Mac で動いているコンテナでホスト側のサウンドカードを使う

自分でスマートスピーカーを作りたくなり、音声認識のところで Julius をいじってるなう。Julius を含む音声認識部分をコンテナで切り出しているところでホスト側 (macOS) のサウンドカードを使わせるようにしたかったのでやり方をメモっておく。

macOS ではなく ALSA の使える Linux 環境であれば Docker の --device オプションで --device=/dev/snd:/dev/snd としたりすれば動くらしい。VirtualBox だとオーディオ設定からホスト側のサウンドカードを利用できるので、コンテナを VirtualBox 上で動かすことで Docker の device オプションによりホスト側サウンドカードを利用できる。VirtualBox を経由するのではなく別のやり方が無いか調べていたら PulseAudio 経由で音声を再生するやり方も見つかったので、これをベースに音声入力もできないか試してみた。

audio - Record Sound on Ubuntu Docker Image - Stack Overflow

大まかな説明

  • コンテナ側
    • PulseAudio の設定で音声データの入力元を /dev/audio とかにしておく
    • socat の tcp-listen で port に流れてきた音声データを /dev/audio に流し込む準備をしておく
  • ホスト側 (macOS)
    • SoX (Sound exhange) でマイクからの音声データを socat で待ち受けているポートに流し込む
  • コンテナ側で録音できる

検証作業

  • Dockerfile
FROM ubuntu

RUN apt-get update && apt-get install -y pulseaudio socat alsa-utils
  • コンテナ側
bash-3.2$ docker build -t mictest . && docker run -p 127.0.0.1:3000:3000 -v `pwd`:/mictest -it mictest
...
root@bf3b26a44c0e:/# pulseaudio -D --exit-idle-time=-1
W: [pulseaudio] main.c: This program is not intended to be run as root (unless --system is specified).
root@bf3b26a44c0e:/# pacmd load-module module-pipe-source file=/dev/audio format=s16 rate=44100 channels=2
root@bf3b26a44c0e:/# socat tcp-listen:3000 file:/dev/audio &
  • ホスト側
bash-3.2$rec --encoding signed-integer -traw --bits 16 --channels 2 --rate 44100 - | nc 127.0.0.1 3000 > /dev/null

rec は SoX の録音用ラッパー。

  • コンテナに戻って
root@8c421891ff69:/# arecord /mictest/test.wav
Recording WAVE 'test.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
// この後めちゃくちゃ音を鳴らして Ctrl-C
  • test.wav を聞くと録音できているよかった

おわり

  • ネットワーク経由で PulseAudio 使ったことなかったけど具体的な使い方が見えてきたのでよかった
  • SoX は音量の閾値を超えたら録音開始したり、色々できるようで便利
    • 音声処理ツールのスイスアーミーナイフとトップページに書かれているだけある
  • 実際は Raspbian にのっけたいので実機で確認したいところだが開発中は手元の MacBook Pro で音声入力でやっていきたい 

社内どうぶつタワーバトル大会をしました

これは VOYAGE GROUP Advent Calendar 2017 - Qiita 14 日目の記事です。

VOYAGE GROUP には社内サークルがいくつかあり、各サークル元気に楽しく交流しています。 自分が所属しているのはゲームサークルで、日夜格ゲーの練習をしています。ここ1年はストリートファイター5をやっているので、プラチナ辺りまでいったらブログでも書こうと思っていたのですがなかなか難しいですね(現在ゴールド)。

社内で流行っているゲームは時の流れにもよりますが格ゲーやイカのゲームだったり、スマホゲームだと Vainglory が強かったりします。そのなかで少しずつ盛り上がりを見せているのが どうぶつタワーバトル (DTB)です!DTBiTunes App Store でも上位に食い込んでくるほど人気になってきているゲームです。今回はその DTB の魅力を伝えていきたいと思います!

といってもシンプルな話で、伝えたいことを一言で説明すると 忘年会はどうぶつタワーバトルで盛り上がろう! です。

概要

動画を見ていただければわかるはずです。動物を積み上げて崩さないやつが優勝、それ以外は敗北と共に屈辱を味わう。それだけのシンプルなゲームです。 社内の人が言ってましたが、動物版ジェンガという感じですね。

シンプルに見えますが、いくつかのセオリーやパターンがあったり、序盤・中盤・終盤とフェーズごとにどう置くべきなのかすごく考えさせられるゲームになります。 勝つためにどうすれば良いのかということは日夜研究されており(たぶん)、 2キリン 5.5象 握力 など専門用語が飛び交うほどの奥の深さを持つゲームです。 今夜勝ちたい ゲーム攻略記事で有名なゴジラインさんでも記事にされています。

【どうぶつタワーバトル】今夜勝ちたい『どうぶつタワーバトル』 | ゴジライン

個人的な攻略法は、 無茶をしない この一言につきますね。

何が魅力なのか

シンプルの中に奥深さががあるのはもう述べたとおりですが、一番の魅力はみんなで遊んだときの 盛り上がり にあると思っています。主要なゲームモードはオンライン対戦なのですが、対戦部屋を作成してから知り合い同士で遊ぶこともできます。

一緒に遊ぶ人に強すぎる人がいたら負けっぱなしで面白くないかもしれないのでは?と思う方もいるかもしれませんが、DTB の難しく楽しいところは一瞬も気が抜けないところです。下手な積み方をするとすぐに負けますし、適当に置いても謎の力により勝ったりします。

謎の力の例です。

どう転んでも面白いし盛り上がる、DTB の面白さですね。飲み屋で数時間 DTB をやって笑いこけている自分に気づいたときは忘れてしまっていた童心を取り戻したかのようでした。

社内大会をしました

社内の色々な人が DTB にハマっているのを見かけて、お昼ごはん休憩がてら社内大会を実施しました!DTB をやっていない人も観戦に来てくれたりと盛り上がりました。

f:id:jewel12:20171215000215j:plain

レート 2000 超えの猛者もいる中、本番のバトルなら強いと意気込んで企画したのですが優勝には至りませんでした……また出直したい。

おわり

企業対抗戦のお誘いや個人的な挑戦などはいつでも受け付けております!きっと盛り上がると思うので、興味ある方は @jewel_x12 までご連絡ください!VG勢はよく#だいだい という部屋で戦っています。

もう年の瀬、忘年会は積もる話もあるかもしれませんが、すべて無視してどうぶつタワーバトルで動物を積んで盛り上がりましょう!笑いで締められればそれでよし!

明日の VOYAGE GROUP Advent Calendar 2017 の記事もご期待下さい!!

QMK Firmware の話 (VOYAGE GROUP Advent Calendar 2017)

これは VOYAGE GROUP Advent Calendar 2017 - Qiita の 7 日目の記事です。

インターンをやった話をしようと思ったのですが後回しにして、今伝えたい気持ちが強い QMK Firmware の話をしますね。

弊社ではキーボードやディスプレイ等を購入する支援制度があり、キーボードにこだわりがある人は多いです。自分の席を見回しても Kinesis のキーボードや ErgoDocs EZ を使用している人、自作キーボード勢がいたりしますね。自分は Let's Split というカワイイキーボードを使っています。

mint.hateblo.jp

Let's Split の良さも紹介したいのですが、キーボードは手に馴染んだり思い入れのあるものを利用してくれればそれでいいです。今日は Let's Split を作成しているときに利用したファームウェアである QMK Firmware を紹介します。


QMK Firmware は Atmel AVR マイコン等向けのファームウェアです。ファームウェアをビルドして書き込むことで、任意のキーマップにすることができます。自作キーボード界隈では AVR マイコンを利用することが多いみたいですね。ErgoDox EZ も AVR マイコン搭載の基板上で動いているので QMK Firmware が利用できます。

QMK Firmwaer はキーマップを変えるだけではなくいろいろな機能があり、それらを利用することでキーボードをもっとパワフルにできます。

いくつか機能があるのですが、自分がみんなに QMK Firmware を知ってもらいたいという気持ちになった機能をいくつか挙げます。

Layer

  • キーボードマップのレイヤーを任意に変更できます
    • あるキーを押している間や押したりすることで切り替えることができます
    • キー数の少ない 40% Keyboard を利用したりするときに重宝します

Auto Shift

  • QMK Firmware で一番好きな機能です
  • 一定時間キーを押していることで Shift が効いたで状態でキーを押したの同じ効果になります
  • デフォルトは結構長く押していないと Auto Shift されないのですが、130ms と短めに調整すると気持ち長く押すだけで Shift が効いて快適に利用できました

Leader Key

  • Leader Key を設定し、タイムアウトしない間に他のキーを押した場合の挙動を定義できます
  • EmacsKey Chord を多用するような人にはオススメそう
  • 自分は使っていない

Mousekeys

  • こちらも自分で使っていないのですが、マウスやクリックをエミュレートできます
  • マウスにまで手を伸ばすのが億劫だったり赤ポチがキーボードにない人向け

Tap Dance

  • キーを複数回叩くたびに挙動を変化させます
  • たとえば ( キーを 1 回叩くと [, 3 回叩くと { というふうな動作を指定できます
  • 括弧周りならとりあえずこれを叩いておけばオーケーみたいになるので便利

おわり

あとは One Shot Key など色々ありますが上記の機能が特徴的です。 Auto Shift があるだけで QMK Firmware を書き込めない他のキーボードには移れないですね。

VOYAGE GROUP アドベントカレンダー、明日は nakano_tomofumi さんの iOS UU 推定です。 アドテクをやっている仕事柄、UU 推定をすることは結構あるので楽しみです。

VOYAGE GROUP アドベントカレンダーも気になりますが、自作キーボードアドベントカレンダーも面白そうなので、QMK Firmware に興味を持った方はぜひチェケラ。

adventar.org

Let's Split

俺の仕事が捗らないのはどう考えてもキーボードが悪いと勘違いし Kinesis Freestyle2 から何か別なキーボードにしようと探してたら Planck というのが見つかり、可愛いのでこれにしようと思ってたら Planck を左右分割したような Let’s Split の存在を知り、たまたま @matsPod さん主催で PCB 等を共同購入する機会があるよと @rail44 に教えてもらったので共同購入に参加したのでした。

組み立て方はググると出てくるので自分がハマった点だけ述べると、 このキーマップ(Qwerty)でいう c が効かなかったこと。最初はスイッチとの接触不良かなと思ったのだけれど、スイッチを付けなおしたりしても直らず、ダイオードの向きも問題なかった。最初、解決策が思いつかな書くて z の下に c を置いたりとかキーマップで調節してたけど辛かったので頑張って原因を探すことに。PCB のどこかが断線しているのかもしれないと思ったので Let's Split PCB とか雑なクエリで探して以下の画像を眺めていたら断線しているところが分かった。

c の下のキーは動作しているので、スイッチとダイオードがつながっている方が悪いんだろうということで直接繋げてみると c も入力できるようになった。やったね。

f:id:jewel12:20170718200211j:plain

アクリル板は黄緑とマゼンタを片方ずつ購入。キートップは適当に買った黒いやつで、Twitter の写真はオシャレに映っているけど明るいところで見ると大してかっこよくない。色に合わせたキートップを買いたい。

使用感としては格子状のおかげか手の小さい自分にあう良いキーボードなので、共同購入を企画してくださった matsPod さんには感謝。

シンギュラリティと怠惰

この記事は VOYAGE GROUP techlog / Advent Calendar 2016 の記事として書いています。ダラダラした記事になっているのでお暇な時にどうぞ。

今年の個人的な流行語を挙げると「今夜勝ちたい」と「シンギュラリティ」になるでしょうか。前者は今年1年間、ストリートファイター5を毎夜練習しては負け、練習しては負けを繰り返した気持ちが強く現れている良いワードです。弊社はゲームサークルがあり、日夜練習に励んでいるので興味がある方は連絡ください。後者はなんか今年のワードな気がしたのですが、以下を見ると 2014 年から盛り上がり続けているようですね。

このもし来るかもしれないシンギュラリティ後の世界、人工知能が人間を上回った世界とされていますが、これによりロボットに支配されちゃうー、とか仕事がなくなっちゃうー、とか色々想像されていますね。

f:id:jewel12:20161220181142j:plain

ところでこれは生筋子(450gほど)を塩水につけて、菜箸でほぐしているところです。

人間のやることがなくなっても時間と自由がある限り、生筋子を菜箸でほぐすとか色々おもしろいことに挑戦できるようになったりするのではないかと僕は楽観的です。あ、でもやっぱりごろごろしてるだけの怠惰な生活を送るかも……。

さて、僕は人工知能はプログラムを書けるのかというものに興味があります。プログラムを書いてくれるならだらだらゲームをして過ごせるので

プログラムを自動生成する方法で自分が考えつくのは、大量のコードを集めてそれらを何らかのブロックで分割し、期待した結果がでるようにブロックを並べ替えできるよう機械学習していくことです。なのでそのようなものを作ります。下の記事でも Python コード片を集めて、それっぽく動きそうなコードを生成しています。

postd.cc

f:id:jewel12:20161221152122j:plain

次は筋子の筋を取り除くために塩水で洗っていきます。手でかき混ぜて浮いてきたゴミをすくって捨てる、を数回繰り返します。

f:id:jewel12:20161221153143j:plain

洗った後です。きれいになりましたね。ちょいちょい筋が残っているのは取り除くのがだるくなったからです。

それっぽいコード生成する太郎は残念ながら自分で仕事を見つけてくれないので、いったんお仕事を与えましょう。今回は数列のソートをしてもらうことにしました。ちなみに機械にソートさせることすら放棄した記事はこちらです。

ソートをするための簡単な DSL を組んで、コード辺の組み合わせを選んでいく強化学習を目指します。強化学習というとあれです。人工知能Atari 2600 の Pong を攻略する動画を見たことある人もいるのではないでしょうか。ざっくり言うと、ある状態で、ある操作をした結果の報酬をもらい、たくさん報酬がもらえるようにどういう操作をすればよいのか学習していくというものです。僕もたくさん報酬がもらえるように日々頑張っています。(゚∀゚)人(゚∀゚)ナカーマ

f:id:jewel12:20161221155926j:plain

醤油・酒・みりん・昆布を入れて沸騰させた様子です。つけ汁になります。

DSL を組むと言いましたがやっぱり面倒なのでやめましょう。操作できることをもう少し単純化して、数値の入れ替えを繰り返すことでソートを目指すようにしました。コード片の入れ替えではなく、213 の 1 番目と 2 番目を入れ替えるというような操作の学習になります。もはやコードを書かせるという目的はなくなりましたが仕事ができれば良いのです。

実際にコードをアウトプットすることの利点は、人間が理解できる(かもしれない)アウトプットにすることにより、人間による調整の余地があるところかなと思います。まあ人の手を介さずになんかいい感じにちゃんと動けばええのや。

実際はレジスターなどを作ってもう少し複雑な操作をできるようにした結果、人間には理解できないような操作が有効に働くのではみたいな、ほのかな期待があったのですが面倒なのでやめましょう。

f:id:jewel12:20161221162458j:plain

おっ、もしかしてこれはいくらですかね?そうですね。美味しいです。

今回は Q-leaning という手法を使います。詳細は以下が分かりやすいです。

qiita.com

Q-learning で必要なものは以下の 3 つです。

  • 状態
  • 操作
  • 報酬

状態は今回の場合、0123456789 のような数列になります。その状態下でどう操作(入れ替え)をしたらどういう状態になったか、その結果の報酬はどうだったかということを知り、操作に対する期待値を学んでいきます。

報酬はどうやって設定すればよいでしょうか。ちゃんとソートできたら 1, それ以外は 0 にしましょう。良い報酬を与えるとよく働いてくれるかもしれませんが良い報酬を考えるのも面倒ですね。

学習の時、次にどういう操作をしようかというのを決める方法に ε-greedy というものがあるのでこれを使います。これは通常時は期待値の高い操作を選んでいき、ある確率でランダムに操作を選ぶ方法になります。たまに横道にそれるともっといい方法があったみたいなのを生み出します。

f:id:jewel12:20161221164028j:plain

おっとここでカニが登場だー!昨日はカニ鍋をしました。欲望に忠実ですね。

今回は要素数が 7 の数列を並べ替えます。

学習をせずにランダムに入れ替えていくと、10271 回で並び替えられました。頑張ったね。5 回学習すると、15 回の並び替えでうまくいきました。本当は入力値を何回も変えてその結果の平均を見たりするべきですが面倒さがあります。

入れ替えの様子です。実行したコードはこちらになります。

input: 6,4,5,2,1,3,0

...
-----------
step 10, SwapPosAAndPosB(6,4)
[4, 3, 1, 0, 6, 2, 5] -> [4, 3, 1, 0, 5, 2, 6]
max_q: 0.000000
-----------
step 11, SwapPosAAndPosB(3,2)
[4, 3, 1, 0, 5, 2, 6] -> [4, 3, 0, 1, 5, 2, 6]
max_q: 0.512000
-----------
step 12, SwapPosAAndPosB(5,0)
[4, 3, 0, 1, 5, 2, 6] -> [2, 3, 0, 1, 5, 4, 6]
max_q: 0.640000
-----------
step 13, SwapPosAAndPosB(2,0)
[2, 3, 0, 1, 5, 4, 6] -> [0, 3, 2, 1, 5, 4, 6]
max_q: 0.800000
-----------
step 14, SwapPosAAndPosB(5,4)
[0, 3, 2, 1, 5, 4, 6] -> [0, 3, 2, 1, 4, 5, 6]
max_q: 1.000000

知ってる状態までランダムに入れ替えまくって、知ってる状態になったらどんどんゴールを目指していくという感じですね。

100 回学習では 4 回の入れ替えです。よくやった。

step 0, SwapPosAAndPosB(6,0)
[6, 4, 5, 2, 1, 3, 0] -> [0, 4, 5, 2, 1, 3, 6]
max_q: 0.512000
-----------
step 1, SwapPosAAndPosB(4,1)
[0, 4, 5, 2, 1, 3, 6] -> [0, 1, 5, 2, 4, 3, 6]
max_q: 0.640000
-----------
step 2, SwapPosAAndPosB(5,2)
[0, 1, 5, 2, 4, 3, 6] -> [0, 1, 3, 2, 4, 5, 6]
max_q: 0.800000
-----------
step 3, SwapPosAAndPosB(3,2)
[0, 1, 3, 2, 4, 5, 6] -> [0, 1, 2, 3, 4, 5, 6]
max_q: 1.000000
-----------

早くなってよかったみたいなこと言ってますが、学習により知識が増えた結果、知ってる状態に早く到達できるようになっただけです。早くソートしてほしいなら、入れ替えステップ数に応じて報酬を減らしたり増やしたりする必要がありそうです。問題が複雑になると報酬についてもやはり色々考えないといけなくて面倒ですね。

強化学習をベースにしたやり方で良いなぁと思うのは、入力に偏りがある場合それに最適化されたソート方法が学習されるかもしれないというところです。便利やーと思ったのですが、今回やったのと似たような研究があるよと同僚に教えられたのでままならない。

f:id:jewel12:20161221174540j:plain

これは曇っていますが、カニの出汁をよく吸った雑炊といくらですよ。

素数 7 桁で頑張ってましたが、10 桁にしたら学習に異常な時間がかかるようになりました。最初の知識が少ない状態で、ランダム入れ替えによるゴール到達が難しくなったからだと思います。学習のコードは雑に書いたような気がしますが、遅くなった理由はプログラマーの腕がヘボだからだったというだけではありません。たぶん……

Pong を人工知能にクリアさせる場合、どれくらいの状態があるのか考えるだけでお腹いっぱいです。ここでニューラルネットワークが出てきます。Q-learning にニューラルネットワークを組み込んだ DQN (Deep Q Network)というものがあり、先のリンク先に詳しく書かれています。DQN で頑張るところまでやりたかったですが、いくらや鍋を作るのに夢中になって面倒になりました。

来年は怠惰にならないよう頑張ります。年始は人工知能と共に暮す生活を夢見たいです。

次の VOYAGE GROUP Advent Calendar の記事に期待!