Как создать измеритель громкости (измерить уровень звука) в браузере с помощью JavaScript

В качестве одного из тех странных проектов, которыми мы хотели бы поделиться здесь, в нашем мире кода, мы представляем вам сегодня одну из тех функций, которые вы, вероятно, не будете использовать на своей сцене Laboral, но в личных проектах или просто для расширения своих знаний о Javascript. Мы говорим о полезном «измерителе громкости», который пригодится для его графического отображения, чтобы предупредить того, кто использует систему со знаменитой зеленой и красной полосой, что он должен говорить тихо.

Давайте начнем !

1. Скачать измеритель громкости

Volume Meter — это не плагин, а набор из 2 полезных функций, которые помогут вам получить уровень входного сигнала микрофона через API WebAudio. Если вы работаете в каком-то научном проекте о том, как восстановить уровень звука микрофона через браузер, это, вероятно, не то, что вы ищете. Но если цель состоит в том, чтобы получить общее представление об измерении уровня звука для вашего пользователя, то это может быть довольно полезно.

Скачать скрипт измерителя громкости в репозитории Github здесь. Этот сценарий был написан Крис Уилсон в Google, посетите официальный репозиторий в Github для дополнительной информации.

2. Использование измерителя громкости

Как упоминалось ранее, «плагин» — это две функции, вы можете самостоятельно решить, хотите ли вы объявить их в окне или просто добавить их в качестве нового скрипта в ваш документ. Дело в том, что доступны 2 функции плагина: createAudioMeter а также volumeAudioProcess,

С помощью этих функций вы можете получить уровень звука микрофона и выполнить любую из следующих задач:

Важный

Стоит сказать, что скрипты (getUserMedia) должно быть выполнено после загрузки окна, иначе оно завершится неудачей по очевидным причинам.

Уровень отображения в Canvas

Чтобы показать известную полосу, которая становится зеленой и красной в зависимости от уровня входного сигнала микрофона, вы можете использовать следующий код. Он попытается получить доступ к User Media API и через поток, полученный в качестве первого аргумента в обратном вызове onMicrophoneGranted, уровень входного сигнала микрофона может быть получен благодаря функциям плагина. createAudioMeter а также volumeAudioProcess:


/*
The MIT License (MIT)
Copyright (c) 2014 Chris Wilson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
var audioContext = null;
var meter = null;
var canvasContext = null;
var WIDTH=500;
var HEIGHT=50;
var rafID = null;
window.onload = function() {
// grab our canvas
canvasContext = document.getElementById( "meter" ).getContext("2d");
// monkeypatch Web Audio
window.AudioContext = window.AudioContext || window.webkitAudioContext;
// grab an audio context
audioContext = new AudioContext();
// Attempt to get audio input
try {
// monkeypatch getUserMedia
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
// ask for an audio input
navigator.getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}, onMicrophoneGranted, onMicrophoneDenied);
} catch (e) {
alert('getUserMedia threw exception :' + e);
}
}
function onMicrophoneDenied() {
alert('Stream generation failed.');
}
var mediaStreamSource = null;
function onMicrophoneGranted(stream) {
// Create an AudioNode from the stream.
mediaStreamSource = audioContext.createMediaStreamSource(stream);
// Create a new volume meter and connect it.
meter = createAudioMeter(audioContext);
mediaStreamSource.connect(meter);
// kick off the visual updating
onLevelChange();
}
function onLevelChange( time ) {
// clear the background
canvasContext.clearRect(0,0,WIDTH,HEIGHT);
// check if we're currently clipping
if (meter.checkClipping())
canvasContext.fillStyle = "red";
else
canvasContext.fillStyle = "green";
console.log(meter.volume);
// draw a bar based on the current volume
canvasContext.fillRect(0, 0, meter.volume * WIDTH * 1.4, HEIGHT);
// set up the next visual callback
rafID = window.requestAnimationFrame( onLevelChange );
}

Предыдущий код должен отображать простой холст в стиле бара, который изменяется при использовании микрофона:

Уровень входа микрофона

Вы можете проверить рабочий скрипт, который показывает Базовая реализация измерителя громкости в вашем браузере здесь (и отображает его на холсте).

Standalone

Если вы хотите отобразить пользовательский измеритель громкости в своем собственном стиле, вам понадобятся только значения измерителя громкости, а не их отображение на холсте. Чтобы получить только значения, вы можете просто удалить весь код, связанный с элементом canvas из предыдущего скрипта.

Следующий фрагмент покажет, после запуска, значение громкости объекта счетчика (от 0,00 до 1,00) в консоли (соответственно с console.log если уровень «нормальный» или с console.warn если объем «обрезается») с onLevelChange функция:

/**
* Create global accessible variables that will be modified later
*/
var audioContext = null;
var meter = null;
var rafID = null;
var mediaStreamSource = null;
// Retrieve AudioContext with all the prefixes of the browsers
window.AudioContext = window.AudioContext || window.webkitAudioContext;
// Get an audio context
audioContext = new AudioContext();
/**
* Callback triggered if the microphone permission is denied
*/
function onMicrophoneDenied() {
alert('Stream generation failed.');
}
/**
* Callback triggered if the access to the microphone is granted
*/
function onMicrophoneGranted(stream) {
// Create an AudioNode from the stream.
mediaStreamSource = audioContext.createMediaStreamSource(stream);
// Create a new volume meter and connect it.
meter = createAudioMeter(audioContext);
mediaStreamSource.connect(meter);
// Trigger callback that shows the level of the "Volume Meter"
onLevelChange();
}
/**
* This function is executed repeatedly
*/
function onLevelChange(time) {
// check if we're currently clipping
if (meter.checkClipping()) {
console.warn(meter.volume);
} else {
console.log(meter.volume);
}
// set up the next callback
rafID = window.requestAnimationFrame(onLevelChange);
}
// Try to get access to the microphone
try {
// Retrieve getUserMedia API with all the prefixes of the browsers
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Ask for an audio input
navigator.getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
},
onMicrophoneGranted,
onMicrophoneDenied
);
} catch (e) {
alert('getUserMedia threw exception :' + e);
}

onLevelChange это функция, на которую нужно обратить внимание.

Создайте свою собственную обертку

Поскольку реализация кода будет немного запутанной, вы можете создать собственный скрипт, чтобы сделать его использование довольно простым, просто выполнив одну функцию. Посмотрите на следующий пример, он создаст microphoneLevel функция в окне и ожидает 2 обратных вызовов (onResult а также onError):

(function(){
function wrapperAudioMeter(OPTIONS){
var audioContext = null;
var meter = null;
var rafID = null;
var mediaStreamSource = null;
// Retrieve AudioContext with all the prefixes of the browsers
window.AudioContext = window.AudioContext || window.webkitAudioContext;
// Get an audio context
audioContext = new AudioContext();
function onMicrophoneDenied() {
if(typeof(OPTIONS["onError"]) == "function"){
OPTIONS.onError('Stream generation failed.');
}
}
function onMicrophoneGranted(stream) {
// Create an AudioNode from the stream.
mediaStreamSource = audioContext.createMediaStreamSource(stream);
// Create a new volume meter and connect it.
meter = createAudioMeter(audioContext);
mediaStreamSource.connect(meter);
// Trigger callback that
onLevelChange();
}
function onLevelChange(time) {
if(typeof(OPTIONS["onResult"]) == "function"){
OPTIONS.onResult(meter, time);
}
// set up the next callback
rafID = window.requestAnimationFrame(onLevelChange);
}
// Try to get access to the microphone
try {
// Retrieve getUserMedia API with all the prefixes of the browsers
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Ask for an audio input
navigator.getUserMedia(
{
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
},
onMicrophoneGranted,
onMicrophoneDenied
);
} catch (e) {
if(typeof(OPTIONS["onError"]) == "function"){
OPTIONS.onError(e);
}
}
}
window["microphoneLevel"] = wrapperAudioMeter;
})();

Этот скрипт может быть использован следующим образом:

/**
* Execute the script once the window loads
**/
window.onload = function(){
// Request microphone to display level
window.microphoneLevel({
onResult: function(meter , time){
if (meter.checkClipping()) {
console.warn(meter.volume);
} else {
console.log(meter.volume);
}
},
onError: function(err){
console.error(err);
}
});
};

onResult обратный вызов срабатывает повторно и получает объект счетчика с информацией и методами AudioContext, С ним легко читать и работать, не так ли?

Ссылка на основную публикацию
Adblock
detector