0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

S氏がスマホをトランシーバー化したいというので頑張った話

Posted at

S 氏へ
面白い相談を、ありがとう。

もらった要求をまとめる

  • ツーリング時の通話に使いたい
  • お金はかけたくない
  • デバイスは追加したくない
  • いったん切れても自動で再接続してほしい
  • LINE の通話よりもラグを減らしたい
  • 通信量は抑えたい

いくつか構成を伝えたが、今回はこんなイメージで作る

image.png

気になる点はいくつかある

テザリングで端末間の通信はできるのか

簡単にノートパソコン 2 台をスマホのテザリングで接続し
片方でローカルウェブサーバを起動し
片方でアクセスした

成功した
特にテザリングした中では端末間の送信は禁止されていなかった
場合によっては設定で変更かもしれない。。。

ローカルだけで WebRTC 接続できるのか

普通にできるっぽい
インターネット越しに通話するとなるとサーバを使って使えそうな経路を調べることになるが、特にその設定をしなければローカルの経路情報だけが用意されて互いに通信するらしい

SDP は QR コードにできるのか

試しに生成したローカルの経路情報付き SDP を QR コードにしてみた
ものすごい細かさなので読み取りが難しいが読むことはできた
あまりに使い勝手が悪ければ複数の QR コードに分ける手もあるので受け渡し方法は QR で問題なさそう

ざっくりと設計

テザリングをするといっても
親機は SIM のない、モバイルルーターや使わなくなった端末かもしれない
そのため、インターネット接続がなくても動作するようにしたい
ネイティブアプリか PWA が考えられる

かなりどちらでもよかったが Flutter 触りたいのでネイティブアプリとして作る
と思ったがライブラリがビルドできないエラーを抱えているようだったので React(Next)を使った PWA に路線変更した

画面設計

ナビゲーションバーを使ってどの画面へも好きなタイミングで遷移できる

画面名 見えるもの できること
TOP マイクデバイス 使用デバイスの変更
接続状態
接続中のセッション数
招待 リクエスト QR
QR 読み取り カメラプレビュー QR の読み取り
レスポンス QR

※リクエストの QR の読み取り完了後は自動でレスポンスの QR を表示する
※レスポンスの QR の読み取り完了後は自動で TOP 画面へ遷移する

ユーザの利用フロー

  1. 全員、アプリをインストール
  2. 全員、同じ Wi-Fi に接続
  3. 全員、アプリを起動
  4. 親が QR コードを表示する(招待画面)
  5. 子が QR コードを読み取る(QR 読み取り画面)
  6. 子が QR コードを表示する(QR 読み取り画面にて QR が自動で表示される)
  7. 親が QR コードを読み取る(QR 読み取り画面)

これで通話できる
本来ならサーバ経由で送り合う SDP を QR コードで渡すことで通信を確立する
親 → 子だけでなく、レスポンスとなる子 → 親の情報伝達も必要になる
Flutter であれば親機をサーバにして子 → 親のステップを省けるはずだった
PWA ではサーバ機能を提供できないので断念

使えそうなライブラリ調査

PWA

CSS フレームワーク

まぁ、、、とりあえず Bootstrap でいいか。。。
みんな使ってるし。。。

一応ここで使用率はチェック

image.png

WebRTC

そもそも Javascript で WebRTC が扱える
概念的には親子間で通信する際に互いに自分と相手の SDP を設定することで使えるらしい
設定するものとしては以下の表の通り
番号は今回の処理フローにおける設定順
QRで送っているのは1と3の情報

LocalDescription RemoteDescription
1 親の OfferSDP 4 子の AnswerSDP
3 子の AnswerSDP 2 親の OfferSDP

QR コード生成

React 向けのもあるが
より人気のあるこっちにした
QR コード画像の URL を発行してくれる

QR コードリーダー

すごくいろいろあったが React 使うならこれでよさそう

こちらの記事が大変参考になりました

状態管理

React 標準の context で作ってみる
Redux は Vuex を使ったことがあるのでなんとなく思想がわかったのと
実際に使うとなると学習コストがかかりそうだったので今回はパス

作ってみる

Next.js プロジェクトの初期化

npx create-next-appコマンドは Nuxt ほどじゃないが気軽に使えてよかった
今回は Typescript と ESLint を有効にした
できれば CSS フレームワークやほかの Linter の導入も支援してほしい。。。

ライブラリの導入

一旦使いそうなライブラリをすべて導入してビルドしてみる
Flutter で最初開発してて、中盤に差し掛かって導入したライブラリがビルドできないとかいう悲劇があったので、今回は最初にその可能性をつぶしておく

Bootstrap は特に問題なし、ついでに空のページとナビバーを追加してページ切り替えの動作確認

QR コードの読み取りは少しトラブル発生
React18 系に標準だと対応していなかった
Issue を参考にnpm i react-qr-reader --legacy-peer-depsでインストールした
あまりいい対応ではないが動いたのでヨシ

QR コード生成は難なく成功

PWA は各ページのキャッシュ方法が分からなかったが
cacheOnFrontEndNav という設定があったので助かった

ひとまずどのライブラリも問題なく入って動かせた

音声通話を実現する

1 対 1 の通信確立にチャレンジする
この記事がものすごくわかりやすかった
https://lealog.hateblo.jp/entry/2019/04/22/095422

OfferSDPはQRにできたがAnswerSDPが若干容量オーバーでQRにできなかった
そもそもQRが細かすぎてスマホ同士で読める気がしないので
SDPを分割して複数のQRを一定間隔で表示することで情報を渡すことにした
QRの冒頭にインデックス情報をつけることで結合できるように工夫

意外な挙動をもう一つ確認した
AndroidはChromeでマイクを使用しているとChromeを通話アプリとして扱うらしい
このせいで音量が0にできなかった
さらにどのタブかは関係ないらしく、マイクを使っていないタブの音も通話扱いになっていた
今回は通話するためのアプリなのでいったん気にせず進めるが、音量を0にできないのでデバッグ中にハウリングが止まらない

複数人との通話を実現する

接続を複数持って管理できるようにする
これは単純でRTCPeerConnectionのインスタンスを複数持てるようにObjectに格納して保管するだけ

デプロイ

誰でも使えるように公開する
Vercelを使ったことがなく、Nextに触れたこのタイミングで使ってみることにした
驚くほど簡単だった
もうHerokuは時代遅れなのかもしれない。。。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?