菜鸟教程小白 发表于 2022-12-13 05:21:13

ios - AVAudioRecorder - 如何从来电中恢复


                                            <p><p>我正在尝试实现一些我认为非常容易的事情,但事实证明并非如此。</p>

<p>我正在使用“react-native-audio”库的源代码。但是你可以假设我为了这个问题而在本地工作。 </p>

<p>这里是 <a href="https://github.com/jsierles/react-native-audio/blob/master/ios/AudioRecorderManager.m" rel="noreferrer noopener nofollow">reference for the source code</a>我在玩。</p>

<p>我的目标很简单,我正在使用 <code>AVAudioRecorder</code> 录制 session (大约需要 30 分钟)。如果在录音过程中有来电,我希望我的应用能够通过执行以下选项之一“恢复”:</p>

<p>1) 当应用回到前台时,“暂停”“来电”和“恢复”记录。</p>

<p>2) 来电时 - 关闭当前文件,当应用程序返回前台时,开始使用新文件进行新录制(第 2 部分)。 </p>

<p>显然选项 (1) 是首选。</p>

<p>请注意,我很清楚使用 <code>AVAudioSessionInterruptionNotification</code> 并在我的实验中使用它到目前为止没有运气,例如:</p>

<pre><code>- (void) receiveAudioSessionNotification:(NSNotification *) notification
{
    if () {
      NSLog(@&#34;AVAudioSessionInterruptionNotification&#34;);
      NSNumber *type = ;

      if (]) {
            NSLog(@&#34;*** InterruptionTypeBegan&#34;);
            ;
      } else {
            NSLog(@&#34;*** InterruptionTypeEnded&#34;);
            ;            
      }
    }
}
</code></pre>

<p>请注意,我将为这个问题设置赏金,但唯一可接受的答案将是真实世界的工作代码,而不是“理论上应该工作”的东西。非常感谢您的帮助:)</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我选择<code>AVAudioEngine</code>和<code>AVAudioFile</code>作为解决方案,因为代码很简短,AVFoundation的中断处理是<a href="https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html" rel="noreferrer noopener nofollow">particularly simple</a> (您的播放器/录音机对象已暂停,取消暂停会重新激活您的 Audio Session )。</p>

<p><strong>N.B</strong> <code>AVAudioFile</code> 没有明确的关闭方法,而是在 <code>dealloc</code> 期间写入标题并关闭文件,令人遗憾的是,这种选择会使内容复杂化否则将是一个简单的 API。</p>

<pre><code>@interface ViewController ()

@property (nonatomic) AVAudioEngine *audioEngine;
@property AVAudioFile *outputFile;

@end

@implementation ViewController

- (void)viewDidLoad {
    ;

    AVAudioSession *session = ;
    NSError *error;
    if (!){
      NSLog(@&#34;Failed to set session category: %@&#34;, error);
    }

    [ addObserver:self selector:@selector(audioInterruptionHandler:) name:AVAudioSessionInterruptionNotification object:nil];

    NSURL *outputURL = [[ URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] URLByAppendingPathComponent:@&#34;output.aac&#34;];

    __block BOOL outputFileInited = NO;

    self.audioEngine = [ init];

    AVAudioInputNode *inputNode = self.audioEngine.inputNode;

    [inputNode installTapOnBus:0 bufferSize:512 format:nil block:^(AVAudioPCMBuffer *buffer, AVAudioTime * when) {
      NSError *error;

      if (self.outputFile == nil &amp;&amp; !outputFileInited) {
            NSDictionary *settings = @{
               AVFormatIDKey: @(kAudioFormatMPEG4AAC),
               AVNumberOfChannelsKey: @(buffer.format.channelCount),
               AVSampleRateKey: @(buffer.format.sampleRate)
            };

            self.outputFile = [ initForWriting:outputURL settings:settings error:&amp;error];

            if (!self.outputFile) {
                NSLog(@&#34;output file error: %@&#34;, error);
                abort();
            }

            outputFileInited = YES;
      }

      if (self.outputFile &amp;&amp; !) {
            NSLog(@&#34;AVAudioFile write error: %@&#34;, error);
      }
    }];

    if (!) {
      NSLog(@&#34;engine start error: %@&#34;, error);
    }

    // To stop recording, nil the outputFile at some point in the future.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      NSLog(@&#34;Finished&#34;);
         self.outputFile = nil;
    });
}

// https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html
- (void)audioInterruptionHandler:(NSNotification *)notification {
    NSDictionary *info = notification.userInfo;
    AVAudioSessionInterruptionType type = unsignedIntegerValue];

    switch (type) {
      case AVAudioSessionInterruptionTypeBegan:
            NSLog(@&#34;Begin interruption&#34;);
            break;
      case AVAudioSessionInterruptionTypeEnded:
            NSLog(@&#34;End interruption&#34;);
            // or ignore shouldResume if you&#39;re really keen to resume recording
            AVAudioSessionInterruptionOptions endOptions = unsignedIntegerValue];
            if (AVAudioSessionInterruptionOptionShouldResume == endOptions) {
                NSError *error;
                if (!) {
                  NSLog(@&#34;Error restarting engine: %@&#34;, error);
                }
            }
            break;
    }
}
@end
</code></pre>

<p>注意您可能想要启用背景音频(当然,在 Info.plist 中添加 <code>NSMicrophoneUsageDescription</code> 字符串)。 </p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - AVAudioRecorder - 如何从来电中恢复,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/54169447/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/54169447/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - AVAudioRecorder - 如何从来电中恢复