PhoneGap/Cordova iOS 播放声音禁用麦克风

Posted

技术标签:

【中文标题】PhoneGap/Cordova iOS 播放声音禁用麦克风【英文标题】:PhoneGap/Cordova iOS playing sound disables microphone 【发布时间】:2015-07-17 16:14:32 【问题描述】:

我目前正在开发一个 PhoneGap 应用程序,该应用程序在按下按钮后应该播放 8 秒长的声音片段,同时通过使用 Cordova 插件将声音从麦克风通过 RTMP 流式传输到 Wowza 服务器ios 库VideoCore。

我的问题是(仅在 iOS 上)当声音剪辑停止播放时,麦克风 - 出于某种原因 - 也会停止录制声音。但是,流仍然处于活动状态,导致服务器端的声音剪辑包含 8 秒的麦克风输入,然后完全静音。

注释掉播放声音的行会导致麦克风重新录制声音没有问题,但是我们需要能够播放声音。

定义媒体变量:

_alarmSound = new Media("Audio/alarm.mp3")

播放声音并启动流:

if(_streamAudio)
    startAudioStream(_alarmId); 

if(localStorage.getItem("alarmSound") == "true")
    _alarmSound.play();

在我看来,当 PhoneGap 停止播放声音剪辑时,会发生某种内部资源使用冲突,但我不知道我能做些什么来解决它。

【问题讨论】:

【参考方案1】:

我在iOS上也遇到过同样的问题,我通过做两件事解决了:

AVAudioSession 类别

在 iOS 中,应用程序应使用单例 AVAudioSession 指定其对声音资源的要求。使用 Cordova 时,有一个插件可以让您执行此操作:https://github.com/eworx/av-audio-session-adapter

例如,当您只想播放声音时,您可以将类别设置为 PLAYBACK:

audioSession.setCategoryWithOptions(
        AVAudioSessionAdapter.Categories.PLAYBACK,
        AVAudioSessionAdapter.CategoryOptions.MIX_WITH_OTHERS,
        successCallback, 
        errorCallback
    );

当您想使用麦克风录制声音并且仍然能够播放声音时,您将类别设置为 PLAY_AND_RECORD:

audioSession.setCategoryWithOptions(
        AVAudioSessionAdapter.Categories.PLAY_AND_RECORD,
        AVAudioSessionAdapter.CategoryOptions.MIX_WITH_OTHERS,
        successCallback, 
        errorCallback
    );

cordova-plugin-media 杀死 AVAudioSession

您用于播放的媒体插件以一种无法与其他声音插件和网络音频 API 结合的方式处理录制和播放。每次播放或录制完成时,它都会停用 AVAudioSession。由于您的应用只有一个这样的会话,因此这实际上会停用您应用中的所有声音。

为此注册了一个错误:https://issues.apache.org/jira/browse/CB-11026

由于该错误仍未修复,并且您仍想使用媒体插件,因此解决此问题的唯一方法是下载插件代码并注释掉/删除停用 AVAudioSession 的行:

[self.avSession setActive:NO error:nil];

【讨论】:

【参考方案2】:

我发现使用我的代码来获得有关此主题的现有答案需要付出一些努力,因此我希望这对需要更明确解决方案的人有所帮助。


从Cordova Media plugin 的 5.0.2 版开始,此问题仍然存在。如果你想使用这个插件,我发现的最直接的解决方案是 fork 插件存储库并对src/ios/CDVSound.m 进行以下更改。经过几个小时的研究,我无法在不修改插件源的情况下找到可行的解决方案,也找不到合适的替代插件。

强制会话类别

Edin 的回答中提到的插件的作者解释了 AVAudioSession 类别on a similar question 的问题。由于无论如何都需要更改CDVSound.m,我发现以下更改比让eworx/av-audio-session-adapter 插件正常工作更容易。

找到以下代码行:

NSString* sessionCategory = bPlayAudioWhenScreenIsLocked ? AVAudioSessionCategoryPlayback : AVAudioSessionCategorySoloAmbient;
[self.avSession setCategory:sessionCategory error:&err];

将它们替换为:

[self.avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&err];

防止会话停用

此外,Edin 的回答中建议的更改对于防止停用其他音频会话是必要的,但是,并非所有实例都需要删除。

从函数audioRecorderDidFinishRecording()audioPlayerDidFinishPlayingitemDidFinishPlaying() 中删除以下行和周围的条件语句:

[self.avSession setActive:NO error:nil];

代码的其他实例用于错误处理和资源释放,根据我的经验,不需要也不应该删除。

更新:播放音量

应用这些更改后,我们在播放过程中遇到了音量过低的问题(录制处于活动状态时)。在上面的相应setCategory 行之后添加以下行,允许以全音量播放。 the answer from which this fix was sourced 中解释了这些更改。

[self.avSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];

[weakSelf.avSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];

【讨论】:

以上是关于PhoneGap/Cordova iOS 播放声音禁用麦克风的主要内容,如果未能解决你的问题,请参考以下文章

Phonegap / Cordova 改变个别声音的音量?

Phonegap / Cordova 在后台 IOS 一段时间后停止音频

在 iOs 和 Android 的 PhoneGap/Cordova-app 中播放视频

是否支持在 phonegap (cordova) 中使用声音捕获视频?

Phonegap 插件延迟初始化

PhoneGap/Cordova:如何使用 cookie (iOS)?