Como acceder al microfono en safari IOS, chrome android con javascript y html5


hace unos dias trate de acceder al microfono con javascript para detectar el ruido en decibeles y mostrarle un mensaje al usuario encontre un modulo en internet DecibelMeter sin embargo solo era compatible con chrome pero no podia acceder al microfono en safari para IOS o chrome para android, o safari desktop

pueden ver el ejemplo en el siguiente link https://herelodin.com/example-microphone-access-all-browsers-and-devices/

entonces me dia a la tarea de investigar un poco mas y ver si era posible acceder al microfono en todos los dispositivos tango IOS, ANDROID Y WEB

encontre que para poder accerder al microfono en safari IOS, firefox se debe hacer el requets con la siguiente funcion:

navigator.mediaDevices.getUserMedia({ audio: true, video : false })

Ahora bien hasta aqui todos los browser pedian el permiso sin embargo no podia acceder al stream que emite el dispotivo ya que se debe contar con un certificado SSL al menos para safari y firefox

El unico dispositivo donde no se puede accerder al microfono es en chrome para IOS, en chrome para android no tuve problemas para accerder.

para poder analizar el audio y saber la cantidad de ruido en decibles debemos utilzar la funcion AudioContext sin embargo solo esta disponible en chrome en otros navegadores no mandara un error que nos indica que no esta definido entonces debemos utiliazar el siguiente codigo

const AudioContext = window.AudioContext || window.webkitAudioContext;

si nos encontramos en otro navegador que no sea chrome podemos acceder a audioContext a travez de webkit

<!DOCTYPE html>
<html>
    <head>
        <title>Microphone access safari IOS, chrome android, safari mac</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">
         <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
        <style>
            body{
                font-family: 'Lato', sans-serif;
                background-color: #222;
                margin: 0px;
                padding: 0px;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                min-height: calc(100vh);
            }

            .microphone{
                margin-top: 50px;
                margin-bottom: 50px;
                border-radius: 100%;
                width: 100px;
                height: 100px;
                cursor: pointer;
                display: flex;
                flex-direction: row;
                margin: 0px auto;
                align-items: center;
                justify-content: center;
                background-color: rgba(0,0,0,0.3);
                border:4px solid rgba(0,0,0,0.3);
                position: relative;
                position: relative;
                overflow: hidden;
                margin-top: 100px;
                margin-bottom: 100px;
            }
            .microphone.active{
                background-color: black;
                border-color: black;
            }
            .microphone.active i{
                color: red;
            }
            .microphone i{
                color: gray;
                font-size: 40px;
                position: relative;
                z-index: 1;
            }
            
            .microphone .decibel{
                display: none;
                background-color: white;
                position: absolute;
                left: 0px;
                bottom: 0px;
                right: 0px;
                height: 0px;
            }
            .microphone.active .decibel{
                display: block;
            }
        </style>
    </head>
    <body>

        <div class="microphone" id="microphone">
            <i class="material-icons">keyboard_voice</i>
            <div class="decibel" id="microphonebar"></div>
        </div>
        
        <script type="text/javascript">
            var timer;
            var connection             = {};
            var connect             = false;
            var microphonebar         = document.getElementById("microphonebar");
            //safari webkit compatibilidad window.webkitAudioContext
            const AudioContext         = window.AudioContext || window.webkitAudioContext;
            //use chrome navigator.getUserMedi other browsers mobile navigator.mediaDevices.getUserMedia
            function onMicrophoneCaptured(stream){
                
                    connection.stream         = stream;
                    connection.context         = new AudioContext();
                    connection.source         = connection.context.createMediaStreamSource(stream);
                    connection.analyser     = connection.context.createAnalyser();
                    connection.analyser.smoothingTimeConstant = .5;
                    connection.analyser.frequencyBinCount = 16;
                    connection.lastSample     = new Uint8Array(1);
                    connection.source.connect(connection.analyser);
                    connect = true;

                    document.getElementById("microphone").classList.add("active");
                    function loop(){

                        connection.analyser.getByteFrequencyData(connection.lastSample);
                        var value = connection.lastSample[0],
                            percent = value / 255,
                            dB = connection.analyser.minDecibels + ((connection.analyser.maxDecibels - connection.analyser.minDecibels) * percent);

                        microphonebar.style.height = `${percent * 100}%`;
                    }


                    timer =  setInterval(loop, 100);
            }

            function onMicrophoneError(err){
                alert('Acepta los permisos para acceder a tu microfono');
            }

            function toogleMicroPhone(){
                if(connect){
                    connection.source.disconnect(connection.analyser);
                    connection.stream = null;
                    clearInterval(timer);
                    microphonebar.style.height = `0%`;
                    document.getElementById("microphone").classList.remove("active");
                    connect = false;
                }else
                    navigator.mediaDevices.getUserMedia({ audio: true, video : false  })
                        .catch(onMicrophoneError)
                        .then(onMicrophoneCaptured)
            }

            document.getElementById("microphone").addEventListener("click",toogleMicroPhone);
        </script>
    </body>
</html>

En el siguiente enlace puden probar desde sus dispositivos el funcionamiento recuerda que solo en CHROME IOS no podras acceder al microfono

https://herelodin.com/example-microphone-access-all-browsers-and-devices/

Gracias por comentar y compartir este post.