onaudioprocess no llamado en ios11

Estoy intentando get la captura de audio del micrófono que funciona en Safari en iOS 11 después de que el soporte se agregó recientemente

Sin embargo, nunca se llama a la callback onaudioprocess . Aquí hay una página de ejemplo:

 <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, ie Convert this to WAV debug(e.inputBuffer); }; }; navigator.mediaDevices.getUserMedia({audio: true, video: false}) .then(handleSuccess); } </script> </body> </html> 

En la mayoría de las plataforms, verá elementos que se agregan a la list de posts a medida que se onaudioprocess callback onaudioprocess . Sin embargo, en iOS, esta callback nunca se llama.

¿Hay algo más que deba hacer para intentar llamarlo en iOS 11 con Safari?

Hay dos problemas La principal es que Safari en iOS 11 parece suspender automáticamente nuevos AudioContext que no se crean en respuesta a un toque. Puede resume() , pero solo en respuesta a un toque.

Por lo tanto, debe crearlo antes de get el MediaStream , o hacer que el usuario vuelva a tocar más tarde.

El otro problema con su código es que AudioContext tiene el prefijo webkitAudioContext en Safari.

Aquí hay una versión funcional:

 <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 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); processor.onaudioprocess = function (e) { // Do something with the data, ie Convert this to WAV debug(e.inputBuffer); }; }; navigator.mediaDevices.getUserMedia({audio: true, video: false}) .then(handleSuccess); } </script> </body> </html> 

(Puede configurar la onaudioprocess llamada onaudioprocess antes, pero luego obtendrá búferes vacíos hasta que el usuario apruebe el acceso del micrófono).

Ah, y otro error de iOS para tener cuidado: el Safari en iPod touch (iOS 11) cree que no tiene un micrófono (lo hace). Entonces, getUserMedia rechazará con un Error: Invalid constraint válida si solicita audio allí.

FYI: Mantengo el package de transmisión de micrófono en npm que hace esto por ti y proporciona el audio en un file ReadableStream de Node.js. Acabo de actualizarlo con esta solución, si usted o alguien más preferiría usar eso sobre el código sin formatting.

Solo me pregunto … ¿tienes la configuration habilitada en la configuration de Safari? Viene habilitado por defecto en iOS 11, pero tal vez simplemente lo deshabilitó sin darse count.

introduzca la descripción de la imagen aquí

Lo probé en iOS 11.0.1 y, lamentablemente, este problema aún no está arreglado.

Como solución alternativa, me pregunto si tiene sentido replace el ScriptProcessor con una function que toma los datos de vapor de un buffet y luego los procesa cada x milisegundos. Pero eso es un gran cambio en la funcionalidad.