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 后音乐更柔和?的主要内容,如果未能解决你的问题,请参考以下文章

HTML 5 audio标签 多首背景音乐

audio标签怎么实现多首音乐的播放啊?

为啥audio静音才可以播放音乐

最简单的向HTML网页添加背景音乐的方法

自定义audio样式做音乐播放器

audio音乐播放