WebARを市役所で実証実験してきたので書く

企業人制度を利用して潮来市へ派遣しています。
<img width="150" alt="maker_fuji.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/c4b6074b-805a-e462-3cc9-c3be8cd4ac93.png">
WebARを使った観光事業の活用方法を潮来市役所に提案して実証実験をしてきたので、雑記していきます。

# WebARとは
WebARとは、Webブラウザでカメラ機能を使い拡張現実（AR）利用できる機能です。
これまではアプリをインストールするなどの手間が必要でした。
しかし、WebARではスマホやタブレットからSafari、Chromeなどのブラウザから見ることができます。
また、スマホやタブレットに限らず、ブラウザとWebカメラがあれば、ほとんどのプラットフォームで対応できます。
また、ロケーションでのARも比較的簡単に実装できます。
AR.js + A-FrameだとHTML書くだけで実装が可能です。
```
    <body style="margin: 0; overflow: hidden;" onLoad="init();">
        <header id="header">
            <div id="headerInner">
                <h1 id="logoTitle"><a href="/" title="TOP">TOP</a></h1>
            </div>
        </header>

        <!-- A-FRAME用のシーン -->
        <a-scene
            vr-mode-ui="enabled: false;"
            loading-screen="enabled: false;"
            arjs="trackingMethod: best; sourceType: webcam; debugUIEnabled: false;"
            id="scene"
            embedded
            gesture-detector
            device-orientation-permission-ui="enabled: false"
        >
            <!-- マーカータグ -->
            <a-marker
                type="pattern"
                preset="custom"
                url="assets/ayame_chan_marker.patt"
                raycaster="objects: .clickable"
                emitevents="true"
                cursor="fuse: false; rayOrigin: mouse;"
                id="marker_ayame_chan"
            >
                <!-- 表示する画像 -->
                <a-image
                    src="assets/ayame_chan.png"
                    scale="1 1 1"
                    class="clickable"
                    rotation="-90 0 0"
                    gesture-handler
                ></a-image>
            </a-marker>
            <a-entity camera></a-entity>
        </a-scene>
    </body>
```

ただし、VideoはハンドラなどをJavascriptで書く必要があります。
また、Video再生には罠があり、ブラウザの制約でミュート以外では自動再生されません。
音声をつける場合は再生ボタンをつける、ミュートで自動再生して音声を調整できるようにするなどの対応が必要になります。
```javascript:VideoHandler
AFRAME.registerComponent('vidhandler', {
    init: function () {
        const marker = this.el;

        if (!this.vid){
            this.vid={};
        }

        this.vid[marker.id] = document.querySelector(MAP_TO_VIDEO[marker.id]);
        marker.addEventListener('markerFound', function (event) {
            gtag('event', `Marker Found : ${event.target.id}`, {
            'event_category': 'AR Marker',
            'event_label': event.target.id});

            this.vid[event.target.id].play();
        }.bind(this));

        marker.addEventListener('markerLost', function (event) {
            this.vid[event.target.id].pause();
        }.bind(this));
    },
});
```

ちなみにA-Frameの内部はThree.js使っているラッパーなので、AR.js + Three.jsでもできる。
ただしThree.jsは初期化だけで長い。
```javascript:init()
import * as THREE from "three";

// サイズを指定
const width = 1280;
const height = 720;

// レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#myCanvas"),
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);

// シーンを作成
const scene = new THREE.Scene();

// カメラを作成
const camera = new THREE.PerspectiveCamera(45, width / height);
camera.position.set(0, 0, +1000);
................................ 略 ................................
```

# まあ、まずは実践

https://github.com/shinohe/itako-AR

既に動くアプリがあるので実際に試してみましょう。
1. iPhoneの方はカメラアプリから、Androidの方はGoogleレンズなどでQRを読みこむとWebARのアプリが開きます（Androidのデフォルトブラウザでは動きません、諦めてChrome使ってください）
<img width="200" alt="itako-AR-github.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/abaebf71-a9a3-ad7c-f5ce-596874ef3673.png"> <br>
1. 次にこのマーカーを起動したWebアプリで読み込んでみてください。
<img width="200" alt="maker_fuji.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/d140a229-1942-a8fc-2814-e44b85292a5c.png"><br>
1. こんな感じで藤の動画が流れると思います
<img width="200" alt="maker_fuji.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/765ee630-62b5-7f80-f4b0-9976057be658.png"> <br>
1. あやめちゃんマーカーも置いておきます
<img width="200" alt="maker_fuji.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/4ae85549-e98b-e1fd-e83f-3516019336cf.png">

# お試し期間の構成
- Githubにアスペクト比などのメタデータを直書き （お試しなので限りなく工数削減）
- Github + Netlifyでオートデプロイ
- GoogleAnalyticsでイベント集計

### 制作時間など小ネタや反省
- あやめ祭りの期間の半分くらいで実施(2023/05/30~2023/06/18）

https://www.city.itako.lg.jp/page/page005638.html

- 制作時間について。
実装はアプリは1時間程度。
動画データなどの編集&軽量化作業が6時間くらい。
HTML（とJavascript数行）書く、Netlifyの設定だけなので実装は爆速で終わった。
~~動画編集時間の方が圧倒的に長かった。~~
- 市役所設置のWifiが死んだままでインターネット接続できないトラブルがあった。
- 途中テコ入れでパンフレトを作成したタイミングでは伸びた。
- しかし、パンフレット切れと雨で後半はユーザー数が落ち込んだ。（Analyticsの真ん中の大きな山）
- 祭り終了後もパンフレット配ったからか、期間終了後もちらほら利用ユーザーがいる。
- 通信料が上限の1/4だったのでもう少しコンテンツがあってもよかったかもしれない。


### どのくらい使われたか
Google Analytics
<img width="380" alt="スクリーンショット 2023-07-03 11.51.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/1c8970e7-5c86-e025-9ca5-8ba963f64ce9.png">

実施期間は祭りの途中から
200人ちょいくらい、１日あたり15~20人。雨の日は少ない。
インターネット接続できないWifiなどの影響もあり潜在的な利用者数はもっと多いと思われる。

# <font color="MediumPurple">ここまでが実証実験...</font>
実際の事業提案には職員だけで回せる&各種クラウド環境で動くようにアーキテクチャを考えていく。

### 諸条件
- 用途としては観光DXでの活性化およびARコンテンツの創造（謎解きARなど）
- マーカーや画像&動画を管理するのは自治体職員（比較的簡単な操作で利用できること）
- 管理画面の利用ディバイスはPC、スマートフォンを想定
- トラフィックは全然大したことはない
- hls.jsでストリーミング実装を行う
- 日中は常に稼働していること
- 視聴時の利用ディバイスはスマートフォンを想定
- 効果の検証にはGoogle Analyticsを使用する
- 軽量化して配置するとはいえ動画は重たいことには変わりないので、できるだけCDNに置く
- 自治体職員は各種クラウドを触ったことがないので管理画面が必要
- WEB AR表示時のアスペクト比スケールなどの、メタデータの管理も行う必要がある
- ロケーションマッピングでは座標データの管理なども必要
- 動画や画像の変換は自治体職員がやってくれるものとする
- ログ・セキュリティ周りは割愛

## AWSで動くアーキテクチャを考える
上記を含めると下記のような構成が良さそう。
異論あればコメントでお願いします。
<img width="540" alt="ARアーキテクチャ.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/1e892b55-24ca-d4a5-d922-17dd54587c5b.jpeg">

## GCPで動くアーキテクチャを考える
GCPというかFirebase。
AR.jsを利用すれば、HTMLだけで凝った機能が必要ないためFirebaseのWebappで良さそう、費用も安い構成もシンプル。
モバイルアプリを作りたい場合でも素早く展開できる。
問題は Cloud Storage for Firebase はCDNされておらず、カスタムドメインが利用できないので、FastlyなどのCDNサービスは利用が難しいこと。（CNAME登録して無理矢理利用する方法はありそう。そもそもhls.jsが使えるのかわからない）

https://www.ayrshare.com/how-to-put-a-cdn-in-front-of-firebase-cloud-storage/

Firebase HostingならCDNされるはずなので、FHを前段におけばCDNされると思うが、FHにメディアリソースを置きたくない。
Cloud CDNと接続できるのが理想だがやり方が見つからなかった。
後日検証します。

<img width="540" alt="ARアーキテクチャ.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/36e1725d-a9d8-6791-72a0-8458c3049c24.png">

## Azureで動くアーキテクチャを考える
Azure Container Appsの方がAzure Kubernetes Service使うよりも楽。
構成としてはあんまりAWSと変わらないと思う。
<img width="540" alt="Azureアーキテクチャ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257883/35d5c989-f046-243d-60e7-6a7e9ca0af06.png">

# まとめ
- A-Frameだとthree.jsよりも遥かに楽に実装できる。
- 表示するコンテンツ作る方が時間かかる
- 市役所は結構制約がある。
- シンプルでスッキリしてそうで最安なのがFirebase。
しかしCloud Storage for firebaseがCDN化されない。
- 市役所の予算が降りたらやるかもしれない。

# 参考

https://www.city.itako.lg.jp/

https://ar-js-org.github.io/AR.js-Docs/

https://aframe.io/docs/1.4.0/introduction/

各CDN比較は下記

https://cloud-textbook.com/56/