みかづきブログ・カスタム

基本的にはちょちょいのほいです。

音声認識 + WebAR で頭の上に吹き出しを表示する 💬

先日、帽子にARマーカーをつけてみたのですが、なかなか可能性を感じまして、思い切ってARマーカー付きの帽子を作ってみることにしました。

折角なので、プリントではなく刺繍でマーカーを入れたいなと思い、色々探してみたところ、なんとなく見つけたのがこのサイト

www.jetchop.co.jp

発注してからから20日。

ついにARマーカーが刺繍された帽子が届きました。

f:id:kimizuka:20201211225916j:plain

果たして刺繍はマーカーとして認識されるのか、ドキドキしながら試してみると、

全く問題ありませんでした。

早速、自分の直近のツイートを取得するプログラムと組み合わせようと思ったのですが、同じことをしても芸がないので、音声認識 + AR で頭の上に吹き出しを表示してみました。

画面に映っているのが1人ならば、ARマーカーがなくとも顔認識で吹き出しの位置を決めれそうなものですが、将来的に複数人に対応しようとしたり、マスクをしている人対策をしたりすることを考えると、マーカー付きの帽子は悪いアプローチではない気がしています。

HTML

<script>
  const recognition = new webkitSpeechRecognition();
  const fontSize = 24;
  let txt;

  recognition.lang = 'ja';

  document.body.onload = function() {
    recognition.addEventListener('result', function(evt) {
      const transcript = evt.results[0][0].transcript;

      if (transcript) {
        txt = transcript;
      }
    });

    recognition.addEventListener('end', () => {
      recognition.start();
    });

    recognition.start();
  };

  AFRAME.registerComponent('plane', {
    init: function() {
      this.canvas = document.getElementById('canvas');
      this.ctx = canvas.getContext('2d');
    },

    tick: function() {
      const material = this.el.getObject3D('mesh').material;

      this.canvas.width = 300;
      this.canvas.height = 100;

      this.ctx.save();
        this.ctx.fillStyle = 'white';
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.restore();
      this.ctx.save();
        this.ctx.textAlign = 'center';
        this.ctx.font = `${ fontSize }px sans-serif`;
        this.ctx.fillText(
          txt,
          this.canvas.width / 2,
          (this.canvas.height - height) / 2 + fontSize
        );
      this.ctx.restore();

      if (!material.map) {
        return;
      }

      material.map.needsUpdate = true;
    }
  });
</script>
<a-scene embedded arjs="debugUIEnabled: false" vr-mode-ui="enabled: false">
  <a-assets>
    <canvas id="canvas"></canvas>
  </a-assets>
  <a-marker marker type='pattern' url='./pattern.patt'>
    <a-plane
      plane
      width="6"
      height="2"
      rotation="-80 0 0"
      position="0 0 -4"
      material="shader: flat; src: #canvas"
    ></a-plane>
  </a-marker>
  <a-entity camera></a-entity>
</a-scene>

現状長いセリフを言うと、吹き出しをはみ出してしまうのですが、そこは追々修正していこうと思います。