web-dev-qa-db-fra.com

onaudioprocess non appelé sur ios11

J'essaie d'obtenir une capture audio du microphone fonctionnant sous Safari sous iOS11 après la prise en charge du support récemment ajouté

Cependant, le callback onaudioprocess n'est jamais appelé. Voici un exemple de page:

<html>
    <body>
        <button onclick="doIt()">DoIt</button>
        <ul id="logMessages">
        </ul>
        <script>
            function debug(msg) {
                if (typeof msg !== 'undefined') {
                    var logList = document.getElementById('logMessages');
                    var newLogItem = document.createElement('li');
                    if (typeof  msg === 'function') {
                        msg = Function.prototype.toString(msg);
                    } else if (typeof  msg !== 'string') {
                        msg = JSON.stringify(msg);
                    }
                    var newLogText = document.createTextNode(msg);
                    newLogItem.appendChild(newLogText);
                    logList.appendChild(newLogItem);
                }
            }
            function doIt() {
                var handleSuccess = function (stream) {
                    var context = new AudioContext();
                    var input = context.createMediaStreamSource(stream)
                    var processor = context.createScriptProcessor(1024, 1, 1);

                    input.connect(processor);
                    processor.connect(context.destination);

                    processor.onaudioprocess = function (e) {
                        // Do something with the data, i.e Convert this to WAV
                        debug(e.inputBuffer);
                    };
                };

                navigator.mediaDevices.getUserMedia({audio: true, video: false})
                        .then(handleSuccess);
            }
        </script>
    </body>
</html>

Sur la plupart des plates-formes, vous verrez que des éléments sont ajoutés à la liste des messages à l'appel du rappel onaudioprocess. Cependant, sur iOS, ce rappel n'est jamais appelé.

Y a-t-il autre chose que je devrais faire pour essayer de l'appeler sur iOS 11 avec Safari? 

16
John Farrelly

Il y a deux problèmes. Le principal est que Safari sur iOS 11 semble suspendre automatiquement les nouveaux AudioContext qui ne sont pas créés en réponse à un tapotement. Vous pouvez les resume(), mais uniquement en réponse à un tapotement. 

(Mise à jour: Chrome mobile effectue également cette opération, et Chrome Desktop aura la même limitation à partir de la version 70/décembre 2018.)

Vous devez donc le créer avant d’obtenir le MediaStream ou bien demander à l’utilisateur de taper à nouveau plus tard.

L'autre problème avec votre code est que AudioContext est préfixé par webkitAudioContext dans Safari.

Voici une version de travail:

<html>
<body>
<button onclick="beginAudioCapture()">Begin Audio Capture</button>
<script>
  function beginAudioCapture() {

    var AudioContext = window.AudioContext || window.webkitAudioContext;    
    var context = new AudioContext();
    var processor = context.createScriptProcessor(1024, 1, 1);
    processor.connect(context.destination);

    var handleSuccess = function (stream) {
      var input = context.createMediaStreamSource(stream);
      input.connect(processor);

      var recievedAudio = false;
      processor.onaudioprocess = function (e) {
        // This will be called multiple times per second.
        // The audio data will be in e.inputBuffer
        if (!recievedAudio) {
          recievedAudio = true;
          console.log('got audio', e);
        }
      };
    };

    navigator.mediaDevices.getUserMedia({audio: true, video: false})
      .then(handleSuccess);
  }
</script>
</body>
</html>

(Vous pouvez définir le rappel onaudioprocess plus tôt, mais vous obtenez des tampons vides jusqu'à ce que l'utilisateur approuve l'accès au microphone.)

Oh, et un autre bogue iOS à surveiller: le Safari sur iPod touch (à partir de iOS 12.1.1) signale qu’il n’a pas de microphone (c’est le cas). Donc, getUserMedia rejettera avec un Error: Invalid constraint si vous demandez de l'audio à cet endroit.

FYI: Je maintiens le paquet microphone-stream sur NPM qui le fait pour vous et fournit l’audio dans un ReadableStream de style Node.js. Je viens de le mettre à jour avec ce correctif, si vous ou une autre personne préférez l’utiliser par rapport au code brut.

19
Nathan Friedly

J'ai essayé sur iOS 11.0.1, et malheureusement ce problème n'est toujours pas résolu. 

Pour contourner le problème, je me demande s’il est judicieux de remplacer le ScriptProcessor par une fonction qui extrait les données Steam d’un buffet, puis les traite toutes les x millisecondes. Mais c'est un grand changement à la fonctionnalité.

4
Daniel Wu

Vous vous demandez si le paramètre est activé dans les paramètres Safari? Il est activé par défaut dans iOS11, mais vous l'avez peut-être simplement désactivé sans vous en rendre compte.

 enter image description here

1
damianmr