首页 > 解决方案 > 如果在播放音频时初始化麦克风,Safari 上的 iPhone 会混淆将音频输出到哪个扬声器

问题描述

iPhone 在 Safari 中通过免提扬声器播放音频时出现问题。初始化麦克风后,我们会在播放后播放一段简短的音频片段(大约三秒),然后我们用麦克风记录用户的响应——这种事件模式发生了 3 次。第一个音频剪辑通过听筒扬声器播放 - 使音量变小。然后在麦克风记录第一个用户响应后,随后的音频剪辑将通过免提电话播放(这对于所有三个音频剪辑都是所需的)。就音频上下文目标而言,iOS/Safari 可能会混淆什么?是否可以设置一个设置来确保免提电话,或者我可以使用其他事件模式来实现我想要的行为。 期望的行为:iPhone 将通过免提电话播放所有音频片段,即使麦克风已初始化。

1:在“功能集”(音频播放和录音响应)之前播放一个短音频片段 2:在麦克风初始化后设置超时,并启动麦克风流。3:我们已经按照开始录制/播放音频的顺序进行了播放。4:如果没有麦克风被初始化并且从未开始录制,则会发生所需的行为。

audio = new Audio();
this.audio.src = audioUrl;
const audioFileLoadedPromise = this.audio.play()
//////////////////////////////////////////////////
const mediaStreamConstraints: MediaStreamConstraints = {
        audio: !enableAudio ? false : {
            echoCancellation: true,
            volume: 1.0
        },
        video: false : (enableVideo === true ? 

this.getCameraConstraints() : enableVideo),
};

navigator.mediaDevices.getUserMedia(mediaStreamConstraints)
/////////////////////////////////////////////////


await this.microphoneComponent.initComponent();
await this.microphoneComponent.startRecording();
await sleep(1000); //this pause was to test if timing somehow affected playback
this.beginAudio(); //this is the audio clip that is played through handset

////from here the pattern continues switching off between playing audio and recording user response and audio is played through speakerphone (as desired)

期望行为: iPhone 将通过免提电话播放所有音频剪辑,即使麦克风已初始化。

标签: mobile-safarihtml5-audioweb-audio-api

解决方案


这是 iOS 的一个已知问题,记录在这里 https://bugs.webkit.org/show_bug.cgi?id=230902

我尝试和工作的解决方法是这样的(TypeScript)

public connectToSpeaker(remoteAudioStream: MediaStream, gain: number) {
        try {
            const AudioCtx = window.AudioContext || window['webkitAudioContext'];
            const context = new AudioCtx();
            const audioNode = context.createMediaStreamSource(remoteAudioStream);
            const gainNode: GainNode = context.createGain();
            // some device volume too low ex. iPad
            gainNode.gain.value = gain;
            audioNode.connect(gainNode);
            gainNode.connect(context.destination);
        } catch (ex) {
            // will throw an exception if no audio track exists
            console.error(ex)
        }
    }

推荐阅读