2017-02-03 67 views
3

我正在製作一個支持視頻播放和錄製的應用程序。除了視頻播放期間,我總是希望允許背景音頻混音(播放期間,背景音頻應該靜音)。因此,我在改變播放狀態的同時使用了以下兩種方法。當我的AVPlayer開始加載時,我打電話給MuteBackgroundAudio,當我關閉包含它的視圖控制器時,我打電話給ResumeBackgroundAudio。這按預期工作,離開播放後音頻成功返回。更改AVAudioSession後AVCaptureSession沒有音頻

問題在於,至少在執行此操作後,每當使用AVCaptureSession記錄任何內容時,都不會錄製聲音。我的會話配置,像這樣:

AVCaptureDevice *audioDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject]; 
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error]; 

if (error) 
{ 
    NSLog(@"%@", error); 
} 

if ([self.session canAddInput:audioDeviceInput]) 
{ 
    [self.session addInput:audioDeviceInput]; 
} 

[self.session setAutomaticallyConfiguresApplicationAudioSession:NO]; 

// ... videoDeviceInput 

請注意,我沒有設置usesApplicationAudioSession,所以它默認爲YES

void MuteBackgroundAudio(void) 
{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
     if ([[AVAudioSession sharedInstance] isOtherAudioPlaying] && !isMuted) 
     { 
      isMuted = YES; 

      NSError *error = nil; 
      [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord 
              withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker 
                error:&error]; 
      if (error) 
      { 
       NSLog(@"DEBUG - Set category error %ld, %@", (long)error.code, error.localizedDescription); 
      } 

      NSError *error2 = nil; 
      [[AVAudioSession sharedInstance] setActive:YES 
              withOptions:0 
               error:&error2]; 
      if (error2) 
      { 
       NSLog(@"DEBUG - Set active error 2 %ld, %@", (long)error.code, error.localizedDescription); 
      } 
     } 
    }); 
} 

void ResumeBackgroundAudio(void) 
{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 
     if (isMuted) 
     { 
      AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 

      NSError *deactivationError = nil; 
      [audioSession setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&deactivationError]; 

      if (deactivationError) 
      { 
       NSLog(@"DEBUG - Failed at deactivating audio session, retrying..."); 
       ResumeBackgroundAudio(); 
       return; 
      } 

      isMuted = NO; 
      NSLog(@"DEBUG - Audio session deactivated"); 

      NSError *categoryError = nil; 
      [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord 
          withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionMixWithOthers 
           error:&categoryError]; 

      if (categoryError) 
      { 
       NSLog(@"DEBUG - Failed at setting category"); 
       return; 
      } 

      NSLog(@"DEBUG - Audio session category set to mix with others"); 

      NSError *activationError = nil; 
      [audioSession setActive:YES error:&activationError]; 

      if (activationError) 
      { 
       NSLog(@"DEBUG - Failed at activating audio session"); 
       return; 
      } 

      NSLog(@"DEBUG - Audio session activated"); 
     } 
    }); 
} 

調試

我已經注意到,audioSession總是需要兩個嘗試調用ResumeBackgroundAudio後,成功關閉。看來我的AVPlayer沒有得到釋放或及時制止,由於AVAudioSession.h此評論:如果會話設置爲無效,而

注意,此方法將拋出iOS中8後或 關聯應用異常它已經運行或暫停了I/O(例如音頻隊列,播放器,記錄器,轉換器,遠程I/O等等)。

沒有聲音被錄製帶給我相信audioSession實際上並沒有得到激活,但我的記錄說,它(總是在遞歸的第二次迭代)的事實。

我得到了使用遞歸來解決這個問題的想法從this post

爲了澄清,引起該問題的流動如下:與Spotify的播放

  • 開始任何內容的重放在應用
  • Spotify的

    1. 打開應用被靜音時,開始播放(MuteBackgroundAudio
    2. 播放結束時,Spotify的再次開始播放(ResumeBackgroundAudio
    3. 開始錄製
    4. 停止錄音,生氣是沒有音頻
  • +0

    我有這個確切的問題。無論情況如何,只有我的音頻無法第一次工作,我需要刪除並重新添加音頻輸入/輸出以獲取任何內容。 – thedeveloper3124

    回答

    3

    如你所描述的,下降到最後的細節我有完全相同的問題([audioSession setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&deactivationError];第一次失敗不管什麼)

    對我而言,唯一可以接受的方式是停止然後啓動AVCaptureSession。我不完全確定,但我認爲這與Whatsapp處理它的方式完全相同 - 他們的相機與我建議的解決方案完全相同。

    在正在運行的會話中刪除和添加相同的音頻輸入也似乎可行,但我得到了一個可怕的相機凍結 - 與會話啓動/停止相比沒有任何效果。

    遞歸解決方案很不錯,但我認爲如果出於正當原因該集合失敗,那麼'調節'遞歸調用(添加短暫延遲&某種排序的最大重試次數)是一個好主意時間。否則,你的堆棧會溢出,你的應用會崩潰。

    如果您或任何人找到了更好的解決方案,我很想知道它。