Реализация нового AudioContext () в iOS - Возможна ли отправка нескольких записей в одном контексте? - PullRequest
0 голосов
/ 04 февраля 2020

Я не знаю, возможно ли то, что я хочу сделать, в iOS 13. Я хочу иметь возможность отправлять на мой сервер несколько аудиозаписей всего за одно взаимодействие с пользователем. Я использую API Web Audio.

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

Он должен быть вызван перед getUserMedia, так как он возвращает Promise, и каждый фрагмент кода, который выполняется здесь после, рассматривается как автоматически созданный сценарий, в результате чего контекст остается приостановленным.

function WzRecorder(config) {

        var self = this;
        var recording = false;

        this.start = function() {

            // reset any previous data
            recordedData = [];
            recordingLength = 0;

            // webkit audio context shim
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();

            if (audioCtx.createJavaScriptNode) {
                audioNode = audioCtx.createJavaScriptNode(bufferSize, 1, 1);
            } else if (audioCtx.createScriptProcessor) {
                audioNode = audioCtx.createScriptProcessor(bufferSize, 1, 1);
            } else {
                throw 'WebAudio not supported!';
            }

            audioNode.connect(audioCtx.destination);

            navigator.mediaDevices.getUserMedia({audio: true})
                .then(onMicrophoneCaptured)
                .catch(onMicrophoneError);
        };



        function onMicrophoneCaptured(microphone) {

            // save the stream so we can disconnect it when we're done
            window.localStream = microphone;

            audioInput = audioCtx.createMediaStreamSource(microphone);
            audioInput.connect(audioNode);

            audioNode.onaudioprocess = onAudioProcess;

            recording = true;
            self.startDate = new Date();

            config.onRecordingStart && config.onRecordingStart();
            sampleRate = audioCtx.sampleRate;

            var source = audioCtx.createMediaStreamSource(microphone);
            var analyser = audioCtx.createAnalyser();
            analyser.fftSize = 2048;
            var bufferLength = analyser.frequencyBinCount;
            var dataArray = new Uint8Array(bufferLength);
            source.connect(analyser);

        }

        function stopRecording(callback) {
            // stop recording
            recording = false;

            // to make sure onaudioprocess stops firing
            window.localStream.getTracks().forEach( (track) => { track.stop(); });
            audioInput.disconnect();
            audioNode.disconnect();

            exportWav({
               sampleRate: sampleRate,
               recordingLength: recordingLength,
               data: recordedData
            }, function(buffer, view) {
               self.blob = new Blob([view], { type: 'audio/wav' });
               callback && callback(self.blob);
            });
        }

        function onAudioProcess(e) {
            if (!recording) {
                return;
            }

            recordedData.push(new Float32Array(e.inputBuffer.getChannelData(0)));
            recordingLength += bufferSize;
         }
}

Так что прямо сейчас, если пользователь нажимает кнопку, которая запускает WzRecorder.start, он начнет, а затем остановит запись через X секунд. Я хочу, чтобы это повторялось без нажатия пользователем кнопки.

У меня есть другой код, который вызывает WzRecorder.start и WzRecorder.stop каждые X секунд. Проблема заключается в том, что после вызова WzRecorder.start с этим кодом он достигает на MicrophoneCaptured, но звук остается пустым. Однако красный микрофон в моем браузере показывает, что он останавливается и запускается соответствующим образом.

Я попытался разделить new AudioContext() и getUserMedia, но когда я хотел вызвать getUserMedia, у него все еще было предыдущее аудио.

Если onMicrophoneCapture нужно использовать audioCtx, это делает значит, я не могу делать то, что хочу?

или если пользователь запускает new AudioContext(), должен быть способ запустить и остановить рекордер?

...