Audio Ducking 后音乐更柔和?
Posted
技术标签:
【中文标题】Audio Ducking 后音乐更柔和?【英文标题】:Music is softer after Audio Ducking? 【发布时间】:2015-04-15 19:25:13 【问题描述】:我有一些代码用于在我的应用程序中实现音频闪避。当用户正在听一些音乐,然后进入某个位置时,就会播放一段特定的音乐片段。发生这种情况时,正在播放“鸭子”(或变得更加安静)的原始音乐和我的应用程序开始播放的新音乐剪辑会播放。然而,在音乐播放完之后,正在播放的原始音乐再次播放,但比以前柔和得多。有想法该怎么解决这个吗?以下是我的代码:
audioPlayer = AVAudioPlayer(data: NSData(contentsOfMappedFile: musicFilePath), error: nil)
//Before music is played, make sure background music is off and audio ducking is turned on
AVAudiosession.sharedInstance().setActive(false, withOptions: AVAudioSessionSetActiveOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setCategory("AVAudioSessionCategoryPlayback", withOptions: AVAudioSessionCategoryOptions.DuckOthers, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.play()
//Allows audio player to play in the background & turn back on previously played music.
AVAudioSession.sharedInstance().setCategory("AVAudioSessionCategoryAmbient", withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
我试图查看文档,但没有找到太多。任何帮助,将不胜感激。谢谢!
编辑:根据以下答案进行音频闪避时代码的外观:
audioPlayer = AVAudioPlayer(data: NSData(contentsOfMappedFile: musicFilePath), error: nil)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.play()
AVAudioSession.sharedInstance().setActive(false, error: nil)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
编辑2:
audioPlayer = AVAudioPlayer(data: NSData(contentsOfMappedFile: musicFilePath), error: nil)
audioPlayer.delegate = self
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.play()
然后在audioPlayerDidFinishPlaying
方法中,我放置了代码来避开音频:
func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool)
//Prepare to play after Sound finished playing
AVAudioSession.sharedInstance().setActive(false, error: nil)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
【问题讨论】:
【参考方案1】:set audiosession active :YES 读取时,完成读取后,在 didfinish 委托处设置回 NO
-(void)createAVSpeech : (NSString*) readString
audioSession_ = [AVAudioSession sharedInstance];
NSError *setCategoryError = nil;
[audioSession_ setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
NSError *activationError = nil;
[audioSession_ setActive:YES error:&activationError];
speech_ = [[AVSpeechSynthesizer alloc] init];
speech_.delegate = self;
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc] initWithString:readString];
NSString *readLang = @"en-US";
float speedrate = 1;
utterance.rate = AVSpeechUtteranceDefaultSpeechRate * speedrate;
utterance.pitchMultiplier =0.8;
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:readLang];
[speech_ speakUtterance:utterance];
-(void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
NSLog(@"did finish speech");
[audioSession_ setActive:NO error:nil];
【讨论】:
【参考方案2】:你没有激活你的闪避会话,所以我不确定它为什么会起作用。你能这样躲吗?
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
要取消隐藏,停用会话就足够了:
AVAudioSession.sharedInstance().setActive(false, error: nil)
否则尝试停用您的会话并在关闭闪避后重新激活它?
AVAudioSession.sharedInstance().setActive(false, error: nil)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, withOptions: AVAudioSessionCategoryOptions.allZeros, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
附言使用类别符号而不是原始字符串!
【讨论】:
嗨,当我尝试你的方法时,会发生应用程序的音乐剪辑播放大约 1-2 秒,然后播放原始音频。我已经在原始帖子中包含了我所做的事情。 您需要等待您的音频完成后才能脱壳 我尝试实现audioPlayerDidFinishPlaying
方法并将用于躲避音频的代码放在那里,但我似乎仍然无法让它工作。我将在上面的编辑中说明我的意思。【参考方案3】:
我遇到了同样的问题,这篇文章确实帮助了我,但我不得不修改代码才能让它工作。我觉得我应该发布我的代码来帮助人们......
import AVFoundation
class TextToSpeechService: NSObject
let synth = AVSpeechSynthesizer()
let audioSession = AVAudioSession.sharedInstance()
override init()
super.init()
synth.delegate = self
do
try audioSession.setCategory(AVAudioSessionCategoryPlayback, withOptions: .DuckOthers)
catch
print("AVAudioSession: cannot set category")
func saySomething(text: String)
let myUtterance = AVSpeechUtterance(string: text)
do
try audioSession.setActive(true)
catch
print("AVAudioSession: cannot activate")
synth.speakUtterance(myUtterance)
extension TextToSpeechService: AVSpeechSynthesizerDelegate
func speechSynthesizer(synthesizer: AVSpeechSynthesizer, didFinishSpeechUtterance utterance: AVSpeechUtterance)
do
try audioSession.setActive(false)
catch
print("AVAudioSession: cannot deactivate")
我这段代码我使用了AVSpeechSynthesizer,但是它等于使用了AVAudioPlayer。 我开始使用正在闪避和未闪避的音频
let tts = TextToSpeechService()
tts.saySomething("Hello ***")
与之前的答案和 OP 的代码的不同之处在于,audioSession 仅在应用程序实际播放声音时激活,并在播放完声音后立即停用。其他示例包含各种额外代码(当您的应用确实也在播放环境声音时可能很有用,但我在 OP 的问题中没有看到任何提及。)
(在 iOS 9.3.2 上使用 Swift 2.2 在 XCode 7.3.1 中测试的代码)
【讨论】:
以上是关于Audio Ducking 后音乐更柔和?的主要内容,如果未能解决你的问题,请参考以下文章