音声認識して、MindARで画像をcanvas-textureで貼り付け、頭上に「吹き出し」を表示させてみた

# 「吹き出し」を表示したい
　話した言葉を頭上に吹き出しとして表示する。完成したのが「ARふきだし」です。
 https://kaihatuiinkai.jp/ardeasobou/fukidasi.html
![AR_fukidasi_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509199/9f3e45d2-1ad6-5f75-2f49-2e57d0d2c45a.png)
　「Speech Recognitionで音声認識　→　canvasに文字を描く　→　MindARで表示」 の処理をしています。

# canvasの画像をMindARでAR表示
「AR.js examples」の「Canvas Textures」のソースを参考にしました。
https://stemkoski.github.io/AR.js-examples/index.html
解説については「AR.jsでWebARしてみる(8) Canvas Textures」を参照ながら作成しました。
https://zenn.dev/zgw426/articles/fdeb88825e8851d092d3
　scriptを2か所に分けて記載しています。上段が「canvas → AR表示」、下段が「canvasへの描画」です。

```haml:mindar-canvas.html
<html>
<head>
<meta charset='UTF-8'>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title> MindARでcanvas画像を表示 </title>
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mind-ar@1.2.5/dist/mindar-face-aframe.prod.js"></script>
</head>
<body>
<script>
    AFRAME.registerComponent('canvas-texture', {
        init: function() {
        this.canvas = document.querySelector("#arCanvas");
        this.canvas.width = 440;
        this.canvas.height = 440;
        this.context = this.canvas.getContext('2d');
        },
        tick: function(t, dt) {
        // canvasから画像を取得する
        var image = document.querySelector('#drawCanvas').getContext('2d').getImageData(0, 0, 440, 440);
        // 取得した画像を貼り付ける
        this.context.putImageData(image, 0, 0);
        let material = this.el.getObject3D("mesh").material;
        if (!material.map)
            return;
        else
            material.map.needsUpdate = true;
        }
    });
</script>
<div style="position:absolute; left:90px; top:50px; width: 500px;height: 500px;">
    <a-scene mindar-face embedded color-space='sRGB'
      renderer='colorManagement: true, physicallyCorrectLights'
      vr-mode-ui='enabled: false'
      device-orientation-permission-ui='enabled: false'>
      <a-assets>
        <canvas id="arCanvas"></canvas>
      </a-assets>
      <a-camera active='false' position='0 0 0'></a-camera>
      <a-entity mindar-face-target='anchorIndex: 1'>
        <a-plane
          position="0.08  0.38  0.1"  scale="1.9  1.9  1.9 "
          material="src: #arCanvas; transparent: true; opacity: 0.95;"
          canvas-texture>
        </a-plane>
      </a-entity>
    </a-scene>  
</div>
<div style="position:absolute; left:690px; top:50px; width: 440px;height: 440px;">
    <canvas id="drawCanvas"
        width="440px" height="440px"
        style="z-index: 2;
        border: 1px solid rgba(0,0,0,1);
        background-color: rgba(255,255,255,0);">
    </canvas>
</div>
<script>
    var context = document.querySelector("#drawCanvas").getContext("2d");
    context.fillStyle = 'red';
    context.font = '40px Roboto medium';
    context.fillText("文字を表示します。" , 10, 100);
</script>
</body>
</html>
```
　上のコードの作動サンプルはこちら https://kaihatuiinkai.jp/ardeasobou/mindar_face_test02.html
 
 canvasに描いた図をARで顔に表示する機能を使って「ARおめんをつくろう」を作ってみました。
https://kaihatuiinkai.jp/ardeasobou/draw.html
![setumei_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509199/ed17cb4f-eece-96c1-9471-959289dba82d.png)

# 音声認識を追加する
「Webページでブラウザの音声認識機能を使おう - Web Speech API Speech Recognition」を参考にして音声認識を追加します。
https://qiita.com/hmmrjn/items/4b77a86030ed0071f548
　「音声認識スタート」ボタンを追加します。
 
```haml:Speech-Recognition.html
<div style="position:absolute; left:690px; top:500px;">
  <button id="btnListenStart">
    音声認識スタート
  </button>
</div>
```
scriptタグ内に音声認識の機能を記述します。
```javascript:Speech-Recognition.html
  //音声認識の準備
  const listen = new webkitSpeechRecognition();
  listen.lang = 'ja-JP';  // 日本語   'en-US'; // 英語（米国）
  //listen.continuous = true;
  //音声認識「スタート」ボタンを押したとき
  const listenStart = document.getElementById('btnListenStart');
  listenStart.addEventListener('click' , function() {
    document.getElementById('btnListenStart').style.display ="none";
    try{
      listen.start();
    }catch(e){
      console.log(e);
    }
  });
  //音声認識した文字をcanvasに描く
  listen.onresult = function(e) {
    listen.stop();
    if(e.results[0].isFinal){
      var listenText =  e.results[0][0].transcript
      context.clearRect(0, 0, 440, 440);      
      context.fillStyle = 'red';
      context.font = '40px Roboto medium';
      context.fillText(listenText , 10, 100);
    }
  }
  // 音声認識の連続動作をさせる
  listen.onend = () => {
    listen.start() 
  };
```
　これで、「音声認識　→　canvasに文字を描画　→　MindARで顔の上に表示」ができます。
サンプルサイトはこちら https://kaihatuiinkai.jp/ardeasobou/mindar_face_test03.html

　'en-US'にすると、英語の音声認識になります。
 https://kaihatuiinkai.jp/ardeasobou/speech_bubble.html
![speech_bubble_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509199/494ace90-27ea-cd52-e405-53df8af2dd48.png)
　英語の発音練習に利用してください。