概要
WebARの認識ライブラリ8th wallを使って、画像マーカーを読み込みタイミングでSEや音楽を再生したいという要望があったので、やり方を記載します。
前提
- A-Frameを使った実装の方法です。
- iOSやAndroidスマホのウェブブラウザはユーザーの許可なしにいきなり音を出せない制約があるため、ARの体験を始める前にボタンクリックしてから音を再生してすぐ止めるなどの処理を入れる必要があります。今回はこの制約は考えずに、画像マーカーを読み込んだタイミングで音を鳴らす処理のみの説明です。
- 8th wallについての説明や登録の方法などはここではしません。
- 8th wallのサーバーでホスティングする方法で説明します。
プロジェクト作成
A-Frameベースで、画像マーカーを読み込んだら3Dオブジェクトが表示されるサンプルプロジェクトが8th wallの公式から公開されていて、それをクローンして使うのがてっとり早いので、今回はそれを使います。
こちらのリンクからサンプルプロジェクトのページを開けます。
A-Frame: Image Target Flyer
ページを開いたら、画面右上のほうにある「Clone Project」をクリックしてプロジェクトを作成してください。
Workspace、Project URL、License Typeは、ご自身が使う用途に応じてお好きなものを選んでください。
実装
プロジェクトが作成できたら、画面左のメニューの中から、「Editor」を選んでソースコードを編集する画面に移動します。
1. サウンドファイルをプロジェクトにアップロードする
まず、再生するサウンドファイルを用意する必要があります。
画面左のファイル一覧からAssets
という箇所にサウンドファイルをアップロードします。
Assetsの文字の右にある「+」のアイコンをクリックして、自分で用意したmp3ファイルをアップロードしてください。
ここでは、sound_test.mp3
というファイルをアップロードしました。
2. サウンドファイルを読み込む
サウンドファイルをA-Frameで使用するアセットとして登録します。
body.html
を開いて、 のタグの中にタグで先ほどアップロードしたファイルを読み込むための記述をします。後述の処理で必要になるidには、systemAudio
と名前をつけました。
<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
ファイルを開いて、下記のコードを一番下の行から追加してください。
<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
を用意してくれているので、そのイベントが飛んできたタイミングでfoundImage
という関数を呼び、その関数内で音を鳴らすという流れです。
このサンプルプロジェクトには2つの画像マーカーが登録されていますが、このように画像マーカーが複数ある場合に、該当のマーカー以外が検出されたときは音を鳴らさないようにしたいと思います。
xrimagefound
のイベントが発火されたときに呼ばれる関数では、detail
という名前で検出した結果の値を受け取れます。検出した画像マーカーの名前を取りたい場合は、detail.name
とすると取得できます。画像マーカーの名前は8th Wallの管理画面から設定することができます。
ここでは、検出された画像マーカー名がサウンドを鳴らしたい画像マーカー名と同じかをチェックする処理も入れています。
作成したA-Frameのコンポーネントをsound-play-image-target
という名前で登録しています。
※ 8th Wallが提供しているA-Frameのライブラリでは、xrimagefround以外にも色々なイベントを登録できるので、詳しくは8th Wallの公式ドキュメントのイベント一覧ページをご参照ください
3. 作成したA-Frameコンポーネントを画像マーカー検出ののタグに設定する
再び、body.html
に戻り、先ほど作成したA-Frameのコンポーネントのsound-play-image-target
を画像マーカー検出のタグに設定します。
今回は、登録されている2つの画像マーカーのうち、クラゲが一匹だけの画像のほうを認識したタイミングでのみ再生するようにします。
画像マーカー検出のタグ<xrextras-named-image-target>
のうち、name
に該当の画像マーカー名であるmodel-target
が設定されているほうに、sound-play-image-target
を設定します。model-target
は8th Wallの画像マーカー登録画面で指定されている名前です。
次に、名前で再生するかどうかを判別したいため、sound-play-image-target
コンポーネントに名前の判定用の文字列として使うname
に、model-target
を設定します。
<!-- 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のエディタで開発している場合は画面右の方にスマホのエミュレーターがあるので、そこで動作確認もできます。ビデオが流れてクラゲの画像マーカーが認識されたタイミングでサウンドが再生されます。