PhoneGap/Cordova iOS 播放声音会禁用麦克风
PhoneGap/Cordova iOS playing sound disables microphone
我目前正在开发一个 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 停止播放声音片段时,似乎发生了某种内部资源使用冲突,但我不知道该如何解决。
我在 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
由于错误仍未修复,您仍想使用媒体插件,解决此问题的唯一方法是下载插件代码并注释 out/remove AVAudioSession 停用的行:
[self.avSession setActive:NO error:nil];
我发现用我的代码获得关于这个主题的现有答案需要一些努力,所以我希望这对需要更明确解决方案的人有所帮助。
从 Cordova Media plugin 的 5.0.2 版开始,这个问题仍然存在。如果你想使用这个插件,我找到的最直接的解决方案是 fork 插件存储库并对 src/ios/CDVSound.m
进行以下更改。经过几个小时的调查,我无法在不修改插件源的情况下找到可行的解决方案,也无法找到合适的替代插件。
强制会话类别
Edin 的回答中提到的插件的作者解释了 AVAudioSession 类别 on a similar question. Since changes to CDVSound.m
are necessary regardless, I found the following change easier than getting the eworx/av-audio-session-adapter 插件工作的问题。
找到以下代码行:
NSString* sessionCategory = bPlayAudioWhenScreenIsLocked ? AVAudioSessionCategoryPlayback : AVAudioSessionCategorySoloAmbient;
[self.avSession setCategory:sessionCategory error:&err];
将它们替换为:
[self.avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&err];
防止会话停用
此外,Edin 的回答中建议的更改对于防止停用其他音频会话是必要的,但是,并非所有实例都需要删除。
从函数 audioRecorderDidFinishRecording()
、audioPlayerDidFinishPlaying
和 itemDidFinishPlaying()
中删除以下行和周围的条件语句:
[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 应用程序,按下按钮后,它应该播放一个 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 停止播放声音片段时,似乎发生了某种内部资源使用冲突,但我不知道该如何解决。
我在 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
由于错误仍未修复,您仍想使用媒体插件,解决此问题的唯一方法是下载插件代码并注释 out/remove AVAudioSession 停用的行:
[self.avSession setActive:NO error:nil];
我发现用我的代码获得关于这个主题的现有答案需要一些努力,所以我希望这对需要更明确解决方案的人有所帮助。
从 Cordova Media plugin 的 5.0.2 版开始,这个问题仍然存在。如果你想使用这个插件,我找到的最直接的解决方案是 fork 插件存储库并对 src/ios/CDVSound.m
进行以下更改。经过几个小时的调查,我无法在不修改插件源的情况下找到可行的解决方案,也无法找到合适的替代插件。
强制会话类别
Edin 的回答中提到的插件的作者解释了 AVAudioSession 类别 on a similar question. Since changes to CDVSound.m
are necessary regardless, I found the following change easier than getting the eworx/av-audio-session-adapter 插件工作的问题。
找到以下代码行:
NSString* sessionCategory = bPlayAudioWhenScreenIsLocked ? AVAudioSessionCategoryPlayback : AVAudioSessionCategorySoloAmbient;
[self.avSession setCategory:sessionCategory error:&err];
将它们替换为:
[self.avSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&err];
防止会话停用
此外,Edin 的回答中建议的更改对于防止停用其他音频会话是必要的,但是,并非所有实例都需要删除。
从函数 audioRecorderDidFinishRecording()
、audioPlayerDidFinishPlaying
和 itemDidFinishPlaying()
中删除以下行和周围的条件语句:
[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];