Onaudioprocess не вызван на ios11

Я пытаюсь получить аудиозапись с микрофона, работающего над Safari на iOS11 после того, как поддержка была добавлена ​​недавно

Однако обратный вызов onaudioprocess никогда не вызывается. Вот пример страницы:

<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>

На большинстве платформ вы увидите элементы, добавляемые в список сообщений, когда вызывается обратный вызов onaudioprocess. Однако в iOS этот обратный вызов никогда не вызывается.

Есть ли что-то еще, что я должен сделать, чтобы попытаться заставить его вызвать iOS 11 с Safari?

Ответ 1

Есть две проблемы. Основным является то, что Safari на iOS 11, кажется, автоматически приостанавливает новый AudioContext который не создается в ответ на нажатие. Вы можете resume() их, но только в ответ на нажатие.

(Обновление: Chrome Mobile также делает это, и настольный компьютер Chrome будет иметь то же ограничение, начиная с версии 70/декабрь 2018 года.)

Таким образом, вы должны либо создать его до того, как получите MediaStream, либо MediaStream пользователя снова нажать позже.

Другая проблема с вашим кодом заключается в том, что AudioContext в Safari имеет префикс webkitAudioContext.

Вот рабочая версия:

<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>

(Вы можете установить onaudioprocess вызов onaudioprocess раньше, но затем вы получите пустые буферы, пока пользователь не одобрит доступ к микрофону.)

Да, и еще одна ошибка iOS, за которой нужно следить: Safari на iPod touch (начиная с iOS 12.1.1) сообщает, что у него нет микрофона (он есть). Таким образом, getUserMedia будет отклонен с Error: Invalid constraint если вы попросите аудио там.

К сведению: я поддерживаю пакет микрофонного потока на npm, который делает это для вас и предоставляет аудио в ReadableStream в стиле Node.js. Я только что обновил его этим исправлением, если вы или кто-либо другой предпочли бы использовать его вместо исходного кода.

Ответ 2

Пробовал это на iOS 11.0.1, и, к сожалению, эта проблема все еще не исправлена.

Как обходной вопрос, интересно, имеет ли смысл заменить ScriptProcessor функцией, которая берет паровые данные из буфета, а затем обрабатывает его каждые x миллисекунд. Но это большое изменение в функциональности.

Ответ 3

Просто интересно... у вас есть параметр, включенный в настройках Safari? Он включен по умолчанию в iOS11, но, возможно, вы просто отключили его, не заметив.

введите описание изображения здесь