Webカメラ、USBマイクのテストと導入、初期設定 [WebRTC/Web Audio API]
パソコンに接続されている「Webカメラ」または「USBマイク」の映像/音声のテストを行います。その他にデバイス/ブラウザの初期設定方法など。
テスト方法 | HTML5のWebRTC/Web Audio APIのJavaScriptコードで確認しますので映像、音声はサーバーに送信されません。全ての処理はクライアントサイドで行います。 |
---|
※ココで使用しているJavaScriptコードはページ下部を参照してください。
1. 映像、音声のテスト
音声 | |
---|---|
映像 |
パソコンにマイクが接続されていなくても、デバイスで「ステレオミキサー」が有効になっている場合はマイクと認識されます。
※ステレオミキサーはパソコン内の音を拾います。
2. Webカメラ/USBマイクの導入
例としてロジクールの「HD ウェブカメラ C615」(内臓マイク付き)の導入を行います。※USBマイクも同様です。
パソコンにUSBケーブルを差すとプラグアンドプレイで自動的にデバイスドライバーの設定が行われます。Windows10の「デバイスマネージャ」を確認するとイメージングデバイスに「Logicool HD Webcam C615」。オーディオの入力および出力に「HD Webcam C615」が表示されます。
3. ブラウザでの初期設定
Webカメラを使用できるようにするには対象のWebサイトにアクセス後、ブラウザに表示される「カメラ、マイクの使用確認」を「許可」にします。
この時にブロックしてしまうと、カメラ、マイクを使用できません。
その場合は、Chromeだと[設定][詳細設定][コンテンツの設定]のカメラ、マイクのブロックを解除後に、ブラウザ上でF5キーを押してWebサイトを「最新の情報に更新する」と再度、確認ダイアログが表示されるようになります。
4. JavaScriptコード
WebRTC(Web Real-Time Communication)でカメラ、マイク接続。
Web Audio APIでマイクのハウリング対策を行っています。ハウリング対策はロジクールの「HD ウェブカメラ C615」用に調整しています。
また、USBマイク単体(サンワサプライ USBマイクロホン MM-MCU01BK)でテストすると出力音量が小さく感じます。
マイクの機種によってハウリングが異なりますので、ハウリング設定はユーザーが手動で選択できるようにした方が良いかもです。
<!doctype html> <html> <head> <meta charset="UTF-8"> </head> <body> <table> <tr><th>音声</th><td><canvas id="myCanvas" width="300" height="200"></canvas></td></tr> <tr><th>映像</th><td><video id="myVideo" width="300" height="240"></video></td></tr> </table> <script type="text/javascript"> var video = document.getElementById('myVideo'); var tracks; var audioCtx; var audioSourceNode; var analyserNode; var filter1,filter2,filter3; var firstflg = true; function play(){ if(tracks) return; // メタデータがロードされたとき video.onloadedmetadata = function(){ // 加工前音声の再生を無効化する(ハウリング対策) video.muted = true; video.play(); }; // 音声確認の棒グラフの表示及びハウリング対策 function voice_processing(stream){ var canvas = document.getElementById('myCanvas'); // AudioContextの生成 if(firstflg){ // AudioContextの生成 audioCtx = new AudioContext(); firstflg = false; } // MediaElementAudioSourceNodeの生成 if(audioSourceNode){ audioSourceNode.disconnect(); } audioSourceNode = audioCtx.createMediaStreamSource(stream); // AnalyserNodeの生成 // ※音声の時間と周波数を解析する if(analyserNode){ analyserNode.disconnect(); } analyserNode = audioCtx.createAnalyser(); // FFT(高速フーリエ変換)の周波数領域 analyserNode.fftSize = 256; // fftSizeの1/2 var bufferLength = analyserNode.frequencyBinCount; var dataArray = new Float32Array(bufferLength); // *** ハウリング対策 *** if(filter1){ filter1.disconnect(); } if(filter2){ filter2.disconnect(); } if(filter3){ filter3.disconnect(); } // ハイシェルフフィルタ // 8192Hz以下を通して、それ以外は減衰 filter1 = audioCtx.createBiquadFilter(); filter1.type='highshelf'; filter1.frequency.value = 8192; // 周波数 filter1.gain.value = -40; // ゲイン(強さ) // ピーキングフィルタ // 0-500Hzを減衰 filter2 = audioCtx.createBiquadFilter(); filter2.type='peaking'; filter2.frequency.value = 250; // 周波数 filter2.gain.value = -40; // ゲイン(強さ) // バンドパスフィルタ // 0-500Hzを通す。それ以外は減衰 filter3 = audioCtx.createBiquadFilter(); filter3.type='bandpass'; filter3.frequency.value = 250; // 周波数(中央値) // フィルタの設定 audioSourceNode.connect(filter1); filter1.connect(filter2); filter2.connect(filter3); filter3.connect(analyserNode); analyserNode.connect(audioCtx.destination); var canvasCtx = canvas.getContext('2d'); canvasCtx.clearRect(0, canvas.height/2, canvas.width, canvas.height); var draw = function() { // 次の再描画の前にアニメーションを更新 requestAnimationFrame(draw); // 周波数データをFloat32Array配列にコピーする analyserNode.getFloatFrequencyData(dataArray); // 背景の描画 canvasCtx.fillStyle = 'rgb(255, 255, 255)'; canvasCtx.fillRect(0, 0, canvas.width, canvas.height); canvasCtx.strokeRect(0, 0, canvas.width, canvas.height); // スペクトルの描画 var barWidth = (canvas.width / bufferLength) * 2.5; var posX = 0; for (var i = 0; i < bufferLength; i++) { var barHeight =(dataArray[i]+140) * 2; canvasCtx.fillStyle = 'rgb(' + Math.floor(barHeight + 100) + ', 50, 50)'; canvasCtx.fillRect(posX, canvas.height - barHeight / 2, barWidth, barHeight/ 2); posX += barWidth + 1; } } draw(); } var ua = window.navigator.userAgent.toLowerCase(); var chrome = (ua.indexOf('chrome') !== -1) && (ua.indexOf('edge') === -1) && (ua.indexOf('opr') === -1); // Chrome var constraints; if(chrome){ constraints = { "mandatory": { "googEchoCancellation" : false, "googAutoGainControl" : false, "googNoiseSuppression" : false, "googHighpassFilter" : false }, "optional": [] }; // FireFox/Edge }else{ constraints = { "echoCancellation" : false, "autoGainControl" : false, "noiseSuppression" : false }; } // 将来的にウェブ標準予定 if("mediaDevices" in navigator && "getUserMedia" in navigator.mediaDevices ){ // マイク、カメラ navigator.mediaDevices.getUserMedia({ video: true, audio: constraints }).then(function (stream) { tracks = stream.getTracks(); video.srcObject = stream; voice_processing(stream); }).catch(function (err) { // マイク navigator.mediaDevices.getUserMedia({ audio: constraints }).then(function (stream) { tracks = stream.getTracks(); video.srcObject = stream; voice_processing(stream); }).catch(function (err) { // カメラ navigator.mediaDevices.getUserMedia({ video: true }).then(function (stream) { tracks = stream.getTracks(); video.srcObject = stream; }).catch(function (err) { console.log(err); }); }); }); // こちらが将来的にウェブ標準予定 }else{ console.log("USE: navigator.getUserMedia()"); // カメラ、マイク navigator.getUserMedia( {video: true, audio: constraints}, function(stream) { tracks = stream.getTracks(); video.srcObject = stream; voice_processing(stream); }, // マイク function(err) { navigator.getUserMedia( {audio: constraints}, function(stream) { tracks = stream.getTracks(); video.srcObject = stream; voice_processing(stream); }, // カメラ function(err) { navigator.getUserMedia( {video: true}, function(stream){ tracks = stream.getTracks(); video.srcObject = stream; }, function(err) { console.log(err); }); }); } ); } } function stop(){ if(tracks){ tracks.forEach(function(track) { track.stop(); }); tracks = null; } } play(); </script> <button onclick="play();"> 開 始 </button> <button onclick="stop();"> 停 止 </button> </body> </html>
getUserMedia()のaudioでconstraintsの隠しコマンドを使用しています。この隠しコマンドではエコーキャンセラー、オートゲインコントロールなどをオフにしています。audioの通常の使い方は「audio:true」となります。
動作確認はChrome/Firefox/MS Edgeです。IE11は動作しません。
※スマートフォン(Android)でも動作するようです。(iPhoneは未確認)