繁体   English   中英

在 Javascript 中检查麦克风音量

[英]Checking microphone volume in Javascript

我正在尝试制作一个需要访问用户麦克风的小游戏。 我需要能够检查麦克风是否已连接,如果已连接,请检查游戏期间通过麦克风的声音音量。 我该怎么做?

在不得不自己解决之后,稍微详细一点的答案可能会帮助其他人看这里。

以下代码将根据麦克风音量注销大约 0 到 100 的数字。

navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(stream) {
  audioContext = new AudioContext();
  analyser = audioContext.createAnalyser();
  microphone = audioContext.createMediaStreamSource(stream);
  javascriptNode = audioContext.createScriptProcessor(2048, 1, 1);

  analyser.smoothingTimeConstant = 0.8;
  analyser.fftSize = 1024;

  microphone.connect(analyser);
  analyser.connect(javascriptNode);
  javascriptNode.connect(audioContext.destination);
  javascriptNode.onaudioprocess = function() {
      var array = new Uint8Array(analyser.frequencyBinCount);
      analyser.getByteFrequencyData(array);
      var values = 0;

      var length = array.length;
      for (var i = 0; i < length; i++) {
        values += (array[i]);
      }

      var average = values / length;

    console.log(Math.round(average));
    // colorPids(average);
  }
  })
  .catch(function(err) {
    /* handle the error */
});

如果你有这个数字 jquery 来设计颜色块。 我在下面提供了一个示例函数,但这是最简单的部分。 只需取消注释颜色 pids 函数即可。

function colorPids(vol) {
  let all_pids = $('.pid');
  let amout_of_pids = Math.round(vol/10);
  let elem_range = all_pids.slice(0, amout_of_pids)
  for (var i = 0; i < all_pids.length; i++) {
    all_pids[i].style.backgroundColor="#e6e7e8";
  }
  for (var i = 0; i < elem_range.length; i++) {

    // console.log(elem_range[i]);
    elem_range[i].style.backgroundColor="#69ce2b";
  }
}

为了确保这个答案尽可能详细,我还在下面附上了我的 html 和 css,因此如果您希望启动并运行一个工作示例,您只需复制 js html 和 css。

html:

<div class="pids-wrapper">
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
  <div class="pid"></div>
</div>

css:

.pids-wrapper{
  width: 100%;
}
.pid{
  width: calc(10% - 10px);
  height: 10px;
  display: inline-block;
  margin: 5px;
}

毕竟,你最终会得到这样的东西。 在此处输入图片说明

这是一个简单地使用setTimeout而不是已弃用的createScriptProcessor函数的答案:

 (async () => { let volumeCallback = null; let volumeInterval = null; const volumeVisualizer = document.getElementById('volume-visualizer'); const startButton = document.getElementById('start'); const stopButton = document.getElementById('stop'); // Initialize try { const audioStream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true } }); const audioContext = new AudioContext(); const audioSource = audioContext.createMediaStreamSource(audioStream); const analyser = audioContext.createAnalyser(); analyser.fftSize = 512; analyser.minDecibels = -127; analyser.maxDecibels = 0; analyser.smoothingTimeConstant = 0.4; audioSource.connect(analyser); const volumes = new Uint8Array(analyser.frequencyBinCount); volumeCallback = () => { analyser.getByteFrequencyData(volumes); let volumeSum = 0; for(const volume of volumes) volumeSum += volume; const averageVolume = volumeSum / volumes.length; // Value range: 127 = analyser.maxDecibels - analyser.minDecibels; volumeVisualizer.style.setProperty('--volume', (averageVolume * 100 / 127) + '%'); }; } catch(e) { console.error('Failed to initialize volume visualizer, simulating instead...', e); // Simulation //TODO remove in production! let lastVolume = 50; volumeCallback = () => { const volume = Math.min(Math.max(Math.random() * 100, 0.8 * lastVolume), 1.2 * lastVolume); lastVolume = volume; volumeVisualizer.style.setProperty('--volume', volume + '%'); }; } // Use startButton.addEventListener('click', () => { // Updating every 100ms (should be same as CSS transition speed) if(volumeCallback !== null && volumeInterval === null) volumeInterval = setInterval(volumeCallback, 100); }); stopButton.addEventListener('click', () => { if(volumeInterval !== null) { clearInterval(volumeInterval); volumeInterval = null; } }); })();
 div { --volume: 0%; position: relative; width: 200px; height: 20px; margin: 50px; background-color: #DDD; } div::before { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: var(--volume); background-color: green; transition: width 100ms linear; } button { margin-left: 50px; } h3 { margin: 20px; font-family: sans-serif; }
 <h3><b>NOTE:</b> This is not accurate on stackoverflow, since microphone use is not permitted. It's a simulation instead.</h3> <div id="volume-visualizer"></div> <button id="start">Start</button> <button id="stop">Stop</button>

这也意味着它可以根据需要轻松启动和停止。

这是检测可用的音频控件所需的片段(摘自: https : //developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia

navigator.getUserMedia(constraints, successCallback, errorCallback);

下面是一个使用 getUserMedia 函数的示例,该函数将使您能够访问麦克风。

navigator.getUserMedia = navigator.getUserMedia ||
                     navigator.webkitGetUserMedia ||
                     navigator.mozGetUserMedia;

if (navigator.getUserMedia) {
   navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
      function(stream) {
         console.log("Accessed the Microphone");
      },
      function(err) {
         console.log("The following error occured: " + err.name);
      }
    );
} else {
   console.log("getUserMedia not supported");
}

这是一个演示您想要的“输入音量”的存储库。

https://github.com/cwilso/volume-meter/

简单的麦克风 Vu 计见https://codepen.io/www-0av-com/pen/jxzxEX

2018 年检查并工作,包括 Chrome 浏览器安全更新导致的错误修复。

HTML <h3>VU meter from mic input (getUserMedia API)</h3> <button onclick="startr();" title="click start needed as security in browser increased and voice mic can only be started from a gesture on page">Start</button> <canvas id="canvas" width="150" height="300" style='background:blue'></canvas> <br> CLICK START <div align=left>See JS for attribution</div> <h3>VU meter from mic input (getUserMedia API)</h3> <button onclick="startr();" title="click start needed as security in browser increased and voice mic can only be started from a gesture on page">Start</button> <canvas id="canvas" width="150" height="300" style='background:blue'></canvas> <br> CLICK START <div align=left>See JS for attribution</div>

CSS

body {
  color: #888;
  background: #262626;
  margin: 0;
  padding: 40px;
  text-align: center;
  font-family: "helvetica Neue", Helvetica, Arial, sans-serif;
}

#canvas {
  width: 150px;
  height: 100px;
  position: absolute;
  top: 150px;
  left: 45%;
  text-align: center;
}

JS(需要 JQuery)

// Courtesy www/0AV.com, LGPL license or as set by forked host, Travis Holliday, https://codepen.io/travisholliday/pen/gyaJk 
function startr(){
 console.log ("starting...");
 navigator.getUserMedia = navigator.getUserMedia ||
   navigator.webkitGetUserMedia ||
   navigator.mozGetUserMedia;
 if (navigator.getUserMedia) {
  navigator.getUserMedia({
      audio: true
    },
    function(stream) {
      audioContext = new AudioContext();
      analyser = audioContext.createAnalyser();
      microphone = audioContext.createMediaStreamSource(stream);
      javascriptNode = audioContext.createScriptProcessor(2048, 1, 1);

      analyser.smoothingTimeConstant = 0.8;
      analyser.fftSize = 1024;

      microphone.connect(analyser);
      analyser.connect(javascriptNode);
      javascriptNode.connect(audioContext.destination);

      canvasContext = $("#canvas")[0].getContext("2d");

      javascriptNode.onaudioprocess = function() {
          var array = new Uint8Array(analyser.frequencyBinCount);
          analyser.getByteFrequencyData(array);
          var values = 0;

          var length = array.length;
          for (var i = 0; i < length; i++) {
            values += (array[i]);
          }

          var average = values / length;

//          console.log(Math.round(average - 40));

          canvasContext.clearRect(0, 0, 150, 300);
          canvasContext.fillStyle = '#BadA55';
          canvasContext.fillRect(0, 300 - average, 150, 300);
          canvasContext.fillStyle = '#262626';
          canvasContext.font = "48px impact";
          canvasContext.fillText(Math.round(average - 40), -2, 300);
          // console.log (average);
        } // end fn stream
    },
    function(err) {
      console.log("The following error occured: " + err.name)
    });
} else {
  console.log("getUserMedia not supported");
 }
}

我还没有查看这个库的代码,但在线演示似乎有效:

https://github.com/cwilso/volume-meter

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM