8th Wallで画像マーカー読み込み時にサウンド（mp3）を再生する

## 概要
WebARの認識ライブラリ8th wallを使って、画像マーカーを読み込みタイミングでSEや音楽を再生したいという要望があったので、やり方を記載します。

## 前提
- A-Frameを使った実装の方法です。
- iOSやAndroidスマホのウェブブラウザはユーザーの許可なしにいきなり音を出せない制約があるため、ARの体験を始める前にボタンクリックしてから音を再生してすぐ止めるなどの処理を入れる必要があります。今回はこの制約は考えずに、画像マーカーを読み込んだタイミングで音を鳴らす処理のみの説明です。
- 8th wallについての説明や登録の方法などはここではしません。
- 8th wallのサーバーでホスティングする方法で説明します。

## プロジェクト作成
A-Frameベースで、画像マーカーを読み込んだら3Dオブジェクトが表示されるサンプルプロジェクトが8th wallの公式から公開されていて、それをクローンして使うのがてっとり早いので、今回はそれを使います。
こちらのリンクからサンプルプロジェクトのページを開けます。
[A-Frame: Image Target Flyer](https://www.8thwall.com/8thwall/flyer-aframe)


ページを開いたら、画面右上のほうにある「Clone Project」をクリックしてプロジェクトを作成してください。
Workspace、Project URL、License Typeは、ご自身が使う用途に応じてお好きなものを選んでください。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34853/c94a7469-5fb1-4b2d-9b1f-8a0818183ec6.png)

## 実装
プロジェクトが作成できたら、画面左のメニューの中から、「Editor」を選んでソースコードを編集する画面に移動します。

### 1. サウンドファイルをプロジェクトにアップロードする
まず、再生するサウンドファイルを用意する必要があります。
画面左のファイル一覧から`Assets` という箇所にサウンドファイルをアップロードします。
Assetsの文字の右にある「＋」のアイコンをクリックして、自分で用意したmp3ファイルをアップロードしてください。
ここでは、`sound_test.mp3` というファイルをアップロードしました。

### 2. サウンドファイルを読み込む
サウンドファイルをA-Frameで使用するアセットとして登録します。
`body.html` を開いて、 <a-assets>のタグの中に<audio>タグで先ほどアップロードしたファイルを読み込むための記述をします。後述の処理で必要になるidには、`systemAudio` と名前をつけました。
```html:body.html
  <a-assets>
    <a-asset-item id="jelly-glb" src="assets/jellyfish-model.glb"></a-asset-item>
    <img id="jelly-thumb" src="assets/video-thumbnail.jpg">
    <video
      id="jelly-video"
      autoplay
      muted
      crossorigin="anonymous"
      loop="true"
      src="assets/jellyfish-video.mp4">
    </video>
    <!-- Add audio resource -->
    <audio id="systemAudio" src="assets/sound_test.mp3" preload="auto"></audio>
  </a-assets>
```

音を鳴らす処理をA-Frameのコンポーネントとして作成して登録します。
今回は簡易的に`head.html` の中に処理を記述します。8th Wallのエディタで`head.html` ファイルを開いて、下記のコードを一番下の行から追加してください。
```html:head.html
<script>
  AFRAME.registerComponent('sound-play-image-target', {
  schema: {
    name: {type: 'string'},
  },
  init: function () {
    const name = this.data.name

    // Get audio assets
    let audio = document.querySelector("#systemAudio");

    // Image target handler
    const foundImage = ({detail}) => {
      if (name !== detail.name) {
        return
      }
      audio.play()
    }

    // Add event listener when the image target is found at the first time
    this.el.sceneEl.addEventListener('xrimagefound', foundImage)
  },
})
</script>
```

再生するサウンドファイルは、先ほど`body.html` で指定した`systemAudio` というid名で取得しています。

画像マーカーをスマホのカメラなどで検出できたタイミングで発火されるイベント[`xrimagefound`](https://www.8thwall.com/docs/api/aframeevents/xrimagefound/) を用意してくれているので、そのイベントが飛んできたタイミングで`foundImage` という関数を呼び、その関数内で音を鳴らすという流れです。
このサンプルプロジェクトには2つの画像マーカーが登録されていますが、このように画像マーカーが複数ある場合に、該当のマーカー以外が検出されたときは音を鳴らさないようにしたいと思います。
`xrimagefound`のイベントが発火されたときに呼ばれる関数では、`detail`という名前で検出した結果の値を受け取れます。検出した画像マーカーの名前を取りたい場合は、`detail.name`とすると取得できます。画像マーカーの名前は8th Wallの管理画面から設定することができます。
ここでは、検出された画像マーカー名がサウンドを鳴らしたい画像マーカー名と同じかをチェックする処理も入れています。

作成したA-Frameのコンポーネントを`sound-play-image-target` という名前で登録しています。
※ 8th Wallが提供しているA-Frameのライブラリでは、xrimagefround以外にも色々なイベントを登録できるので、詳しくは[8th Wallの公式ドキュメントのイベント一覧ページ](https://www.8thwall.com/docs/api/aframeevents/)をご参照ください

### 3. 作成したA-Frameコンポーネントを画像マーカー検出ののタグに設定する
再び、`body.html` に戻り、先ほど作成したA-Frameのコンポーネントの`sound-play-image-target` を画像マーカー検出のタグに設定します。
今回は、登録されている２つの画像マーカーのうち、クラゲが一匹だけの画像のほうを認識したタイミングでのみ再生するようにします。
画像マーカー検出のタグ`<xrextras-named-image-target>` のうち、`name`に該当の画像マーカー名である`model-target` が設定されているほうに、`sound-play-image-target` を設定します。`model-target`は8th Wallの画像マーカー登録画面で指定されている名前です。
次に、名前で再生するかどうかを判別したいため、`sound-play-image-target` コンポーネントに名前の判定用の文字列として使う`name` に、`model-target` を設定します。

```html:body.html
  <!-- Note: "name:" must be set to the name of the image target uploaded to the 8th Wall Console -->
  <xrextras-named-image-target name="model-target" sound-play-image-target="name: model-target">
    <!-- Add a child entity that can be rotated independently of the image target. -->
    <a-entity xrextras-one-finger-rotate gltf-model="#jelly-glb"></a-entity>
  </xrextras-named-image-target>
```

実装は以上です。

変更した内容をエディタの画面上部にある「Save + Build」をクリックして保存します。
8th wallのエディタで開発している場合は画面右の方にスマホのエミュレーターがあるので、そこで動作確認もできます。ビデオが流れてクラゲの画像マーカーが認識されたタイミングでサウンドが再生されます。