HTML5でWebカメラとマイクを同時にテストする

**ひろってきたサンプル2つを混ぜただけです**

美貌と美声がなぜかちゃんと反映されない不具合が残っていますが、動きのリアルタイム描写と音声(録音・再生)をほぼ同時に確認できます。**おかしいなあ。**

# 実行環境

* Windows7
* Firefox 62

# コード

```html
<html><head>
<title>Voice Replay</title>
<script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();

var processor = null;
var num = 0;
var duration = 0.0;
var length = 0;
var sampleRate = 0;
var floatData = null;
function handleSuccess( stream ){
  var video = document.getElementById('myVideo');
  video.srcObject = stream;


  var source = context.createBufferSource();
  var input = context.createMediaStreamSource( stream );
  processor = context.createScriptProcessor( 1024, 1, 1 );
  
  input.connect( processor );
  processor.onaudioprocess = function( e ){
    //. 音声データ
    var inputdata = e.inputBuffer.getChannelData(0);
    //console.log( inputdata );

    if( !num ){
      num = e.inputBuffer.numberOfChannels;
      floatData = new Array(num);
      for( var i = 0; i < num; i ++ ){
        floatData[i] = [];
      }
      sampleRate = e.inputBuffer.sampleRate;
    }
    
    var float32Array = e.inputBuffer.getChannelData( 0 );
    if( availableData( float32Array ) ){
      duration += e.inputBuffer.duration;
      length += e.inputBuffer.length;
      for( var i = 0; i < num ; i ++ ){
        float32Array = e.inputBuffer.getChannelData( i );
        Array.prototype.push.apply( floatData[i], float32Array );
      }
    }
  };
  processor.connect( context.destination );
}

function startRec(){
  $('#recBtn').css( 'display', 'none' );
  $('#stopBtn').css( 'display', 'block' );

  navigator.mediaDevices.getUserMedia( {video: true,  audio: true } ).then( handleSuccess );
}

function stopRec(){
  $('#recBtn').css( 'display', 'block' );
  $('#stopBtn').css( 'display', 'none' );

  if( processor ){
    processor.disconnect();
    processor.onaudioprocess = null;
    processor = null;
    
    var audioBuffer = context.createBuffer( num, length, sampleRate );
    for( var i = 0; i < num; i ++ ){
      audioBuffer.getChannelData( i ).set( floatData[i] );
    }
    
    console.log( audioBuffer ); //. これを再生する
    
    var source = context.createBufferSource();

    source.buffer = audioBuffer;           //. オーディオデータの実体（AudioBuffer インスタンス）
    source.loop = false;                   //. ループ再生するか？
    source.loopStart = 0;                  //. オーディオ開始位置（秒単位）
    source.loopEnd = audioBuffer.duration; //. オーディオ終了位置（秒単位）
    source.playbackRate.value = 1.0;       //. 再生速度＆ピッチ

    source.connect( context.destination );

    //. for lagacy browsers
    source.start( 0 );
    source.onended = function( event ){
      //. イベントハンドラ削除
      source.onended = null;
      document.onkeydown = null;
      num = 0;
      duration = 0.0;
      length = 0;

      //. オーディオ終了
      source.stop( 0 );

      console.log( 'audio stopped.' );
    };
  }
}

function availableData( arr ){
  var b = false;
  for( var i = 0; i < arr.length && !b; i ++ ){
    b = ( arr[i] != 0 );
  }
  
  return b;
}
</script>
</head>
<body>
  <div id="page">
    <div>
      <h2>音声再生</h2>
      <input id="recBtn" value="Rec" onclick="startRec();" style="display:block;" type="button">
      <input id="stopBtn" value="Stop" onclick="stopRec();" style="display:none;" type="button">
    </div>
    <video id="myVideo" autoplay="1" width="800" height="600"></video>
  </div>

</body></html>
```

動きは下記の参照元記事を見てもらえればわかります。
Recボタンでカメラとマイクを許可すれば、カメラはリアルタイム、
マイクはStopボタンを押すまで録音→押したら再生になります。


# 参照元

* [HTML5 の Web Audio API を使ってマイクから入力した音声データを再生する : まだプログラマーですが何か？](http://dotnsf.blog.jp/archives/1072473945.html)
* [HTML5 での映像と音声の取得 - HTML5 Rocks](https://www.html5rocks.com/ja/tutorials/getusermedia/intro/)

# 経緯

Webカメラを買ったのですが、いざUSBケーブルをつないだもののそこからどうすればいいのか首を傾げまして。

ネットで調べてみると、アプリをインストールして動作確認するだとか、
Skypeでテストしようだとかが出てきます。
もっと簡単にWindows単体やブラウザで見れないのかと調べると今は懐かしいFlashでのテストページが出てきたり…ブラウザがブロックどころかPCからもアンインストールしましたよ…

他にもいくつかありましたが、カメラというちょっと個人情報的にも気になるものなのでもうすこしセキュアにできないか悩んでいました。

そのときにふと
[エディタの左上にリアルタイムに顔を表示する - hitode909の日記](https://blog.sushi.money/entry/2018/03/14/111400)
を思い出し、HTML5でできるじゃん！コードも見れるしローカル実行で安全！とHTML5で検索することにしました。

結果、それぞれのサンプルつき解説ページが見つかって動作を確認できたのですが、同時に動かすような記事が軽くさらっただけでは見つからず。
マイク付きカメラを動かしあっちのページでカメラ位置確認、こっちのページでマイクを確認、というのは手間だったので、2つのサンプルスクリプトをまぜることにしました。