動機

チャットツールでは音声メッセージのやりとりができる。ということは、チャットツールを介してインターホンとか、トランシーバーみたいなものを作ることができる?たとえばこんな具合に。

  • 場所1: ボタンを押す。何か話す。
  • 場所2: 場所1からのメッセージがスピーカーから流れる。ボタンを押して答える。
  • 場所1:場所2からのメッセージが聞こえる。

そんなのケータイでやればいいじゃん、と思うかもしれませんが、届いたメッセージがすぐに(容赦なく)スピーカーから流れるところがいいのでス。ボタンを押せばいつでもすぐに話せるところも。電話をかけるよりも簡単に。二階から一階の台所に話しかけるぐらいの気軽さで、ネットワーク越しのどこかの場所に話しかけられたら。

さて、そんなものを作ることができるのでしょうか。(きっとできたからこれをかいているんでしょう)

こうすればできるんじゃないか

図1:初期アイデア

telegram bot A, Bを作り、chat groupに入ってもらう。botだけのchatはつくれないから、私がhuman memberとして入る。raspberry piでガジェットA、Bを作り、bot A、bot Bの住処とする。

ガジェットAで録音したボイスメッセージをbot Aにchatへ投稿してもらう。bot Bは投稿されたボイスメッセージをダウンロードして再生する。私はその様子をchat上で見ることができる。これができればbot B -> bot Aという流れも同様にできるはず。

まずはbot Aだけで試してみる

仕組みはこんな感じ。

図2:プロトタイピング1

ガジェット1号機を作り、以下のステップが実行できるようにする。

できたものには✅。

1.ボイスメッセージの録音(raspiにつけたボタンの動作)✅
2.chat groupへ投稿(録音、投稿まではbot Aの一連のプロセス)✅
3.投稿されたメッセージをhuman userが聞く✅👈私が担当しました
4.human userがボイスメッセージを投稿✅👈私が担当しました
5.human userが投稿したメッセージをbot Aが自動でダウンロード✅
6.ダウンロードしたメッセージを再生(ダウンロード、再生まではbot Aの一連のプロセス)✅

ガジェットづくりも、テストも、codingも、GitHub copilotに手伝ってもらったりしながらそれほど苦労せずに完了。ステップ1から6も、難なくすべて✅。

順調。うれしい。

うまくいったので、もう一つガジェットを作るためのボタンとraspberry pi zero 2 wを注文。

2nd ガジェットづくり

ガジェットのイメージは、大きめのボタンが二つあって、一つは録音スタート用、もう一つは届いたメッセージをもう一度聞くためのもの。マイクとスピーカーもできるだけ簡単につけたい。材料リストは以下の通りです。

  • 1. Raspberry pi zero 2 W
  • 2, 3. arcade button
    色違いを二つ。
  • 4. スピーカー (4W)
    小さいのに元気な音が出ます。
  • 5. reSpeaker 2-Mics Pi HAT
    マイクとRGB LEDが3つ、ボード上にボタンもあって便利です。v2.0というのが売られています。私のは数年前に買った、v1.0です。
  • 6.10 k 抵抗
    pull up回路を組むため。
  • 7. grove cable
  • 8. prototype PCB breadboard
図3:ガジェットの具(材料ともいう)
図4:ガジェットづくりのようす(2号機)

Cytronから部品を買ったときの箱が、しっかりしていてなかなかいい感じだったので、とっておいたものを用いた。ちょっと大きすぎるけど、よしとする。向かって右が録音ボタン、左側(青)が再生ボタン。どちらにも録音と再生には赤と青のボタンを使いたかったのだが、手持ちに赤いボタンがなかったので、1号機では仕方なく黄色と青でがまんした。2号機用には着想どおりの赤と青を購入した。

図5:できあがったガジェットペアとその中身

ためそうぜ!

試す前から待ちきれない!BotFatherにたのんでもう一つボットを作り、bot Bとして2号機に住まわす。まず、bot Bだけならbot Aだけの時のように動くことを確認。いよいよbot Aのいる1号機にも火を入れる。

さてどうなるか?

あれ?

だめじゃん。

bot A(1号機)から送ったメッセージをbot B(2号機)が拾わない。チャットにはちゃんと送られているのに。ちなみに私(human user)がチャットにボイスメッセージを送ると、1号機2号機両方から音声が流れる。すこーしだけタイミングがずれていて、short delayをかけた感じに聞こえて面白い。それはともかく、

なんで?

困った。これじゃあだめだ。だめ。もう一人の自分が、ケータイからボイスメッセージ入れればガジェットに届くんだから、いいんじゃないの?二か所に同時に届くし、それも面白いぜ、というが、だめだ。それではだめ。両方が、ボタン押し、しゃべる、送られる、反対側で再生、をできなければだめだ。だって、

ルンルンしながら材料買って2号機作ったじゃん。金返せ、俺!

考えた。調べた。GitHub Copilotにも相談した。

まずわかったことは、telegram botはtelegram botのメッセージを受けないように設計されていること。そうしないとbot同士がメッセージをバウンスしあったりしたときにどうしようもない量のトラフィックがながれることになるから。なるほど。(おせえんだよ)

Copilotいわく、どうしてもやりたいなら、botではなくてhuman userとしてメッセージを送るコードを書けばできるぜ。でもこれは気が進まない。そもそも自分をuserとして使うのはいいが、もう一つは?一つはhuman, もう一つはbotという手もあるが、それでも気が進まない。

どうするか。

こうした。

それぞれのbotからchatへのポストはできる。human userのポストはうまく再生してくれる。これはこれで便利だからそのまま残し、あとは、

botからbotへメッセージを渡せるように

すればいい。ここはtelegramにこだわらなくてもいいんじゃないか。とにかくraspberry piからもう一つのraspberry piに録音したボイスメッセージを送信できればいい。

どうやって?

MQTTブローカー経由で!

そっか。ずっと前から気になっていて一度も使ったことがない仕組み。でも外部サーバー使うのやだな。

いや、片方のraspberry pi上にMQTTブローカーを構築すればよい。

なるほど。しかしだ、最終的にはこの2台のraspiは、異なるネットワークにぶら下げることになる。今は家のLANにどちらもぶら下げているが。— (*)

なんと!そうなの!

Tailscale。

それでいきましょう。

(*)の後から話相手が見えなくなるが、

  • raspberry piを同一のTailscale meshに乗せる
  • raspberry pi AにMQTT broakerを構築

で、解決するようなのである。うまくいけば2号機は無駄にならない。

仕組みはこんな感じ。

図6:やっほー!

GitHub copilot君が手伝ってくれる今、方針さえ決まればちょちょいのちょい、なのでアール。

実際はそれほどちょちょいのちょいではなかったが、一日でできた。

で、

うまくいく!

1号機で録音するとtelegramのチャットグループに投稿されるとともに2号機から音声が再生される!やっほーい!(逆もできる!<-あたりまえだけどすごくうれしい!家族に静かにして。といわれてもヤッホーい!と何回も言ってしまった)

あとひとつ。片方のraspiを別のネットワークに持って行ったときに動くことを確認したい。

家のwifiルーター君にguest用のネットワークを作ってもらい、片方のガジェットをそちらに接続して試した。うまくいった!うれしすぎる!

codeやraspiのセットアップについて

GitHubにレポジトリを作りましたので、そちらをご覧ください。

概要だけをリストしますと、

  • pythonで書いています
  • package managerはuv
  • credentialはじめ、いくつかの固定変数はwaklie-talkie.envに書いて/etc/walkie-talkieに設置するようにしています(templateを提供しています)。hardcodeしてもいいのに、と思うようなものまで入れてしまっているので、少しごちゃごちゃしていますが、今はこのままで。
  • アプリはsystem serviceとして、raspi起動後に自動で立ち上がるようにする、という方針です。
  • README.md, DEPLOY_NEW_PI.mdの二つのファイルにセットアップのための情報を書きましたが、試行錯誤しながら書いていった部分もあるので、頭からたどっていけばよい、という流れにはなっていない部分があるかもしれません。
  • raspiはheadlessで使っていますので、すべてssh接続のCLIからの操作が前提です。

セットアップで思いがけずつまずいてしまう可能性があるのは、reSpeaker 2-Mics Pi HATのインストールです。(レポジトリにはrespeaker-2-mic-setup-memo.mdという名前で私の個人用セットアップメモを上げてあります)

https://github.com/HinTak/seeed-voicecard

からzipファイルを取得するのですが、raspi OSのカーネルバージョンに合ったブランチからダウンロードすることがポイントです。検索で見つかるインストラクションには、HinTakさんのレポにいって、zipファイルをダウンロードする、という感じのinstructionになっていて、カーネルバージョンにあったものを選んで、という記述が抜けていることがあります。私もそれに気づかずに他をいじくりまわしてずいぶんてこずった覚えがあります。もしreSpeaker 2-Mics Pi HATを使ってみる場合には、カーネルのバージョン合わせをぜひ覚えておいてください。

おわりに

今度実家に帰省した時に、こっそり設置してこようかなと企んでいます。別にこっそりしなくてもいいんですが、

ピンポーン、おじいちゃん?

という遠くにいるはずの孫の声がいきなり聞こえたらさぞかしびっくりするでしょう。(最初の一回だけ)

ボタンを押して話すだけなので、おじいちゃん、おばあちゃんでも楽々です。

*録音の処理に少し時間がかかるので、ボタンを押して一息いれてからしゃべり始め、しゃべり終わったら一呼吸いれてボタンを押す、というコツが必要。もう少し速いraspiならマシになるかもしれません。

どんな会話だったかな、というのはtelegram chatで振り返りができますので、それも便利です。あと、ケータイのtelegramからボイスメッセージをいれると、両方の端末から音声で流れますので、一斉放送的使い方ができます。端末を3か所4か所にすることもできます。どんな生活シーンで使えるか考えるのも楽しいです。

トランシーバーやインターホンと違うのは、インターネットでつながってるので距離が関係なくなることです。インターネットの普及初期に、メールって一通送るのにいくらかかるんだろうとか、世界一有名なコーヒーサーバーを見てすごいと思ったりしていたころの気分がよみがえりました。ネットワーク上の2点をつなぐ、がインターネットの基本です。今回は、それを改めて実感する工作になりました。

今後

おわりに、を書いたのにまだ書くのか。と思いますが、思いついたので書いておきます。

telegram chatに送られるメッセージはボイスメッセージそのものなので、どんな声で話しているか、という様子がわかるのでいいのですが、見直す時には面倒です。何か特定のやり取りを探すときに、一つ一つ聞かないと内容がわかりません。そこで、

文字に起こしたものも同時に送るようにする

ようにしたい。少々精度が悪くてもヒントになればそれでいいので、できればraspi上で完結するような仕組みを探す。これを自分への課題にします。

うまくできたらまた記事にします。

ABOUT ME
misson
ものづくりが趣味。 GitHub: https://github.com/misson3