【问题标题】:Play audio from AVCaptureAudioDataOutputSampleBufferDelegate从 AVCaptureAudioDataOutputSampleBufferDelegate 播放音频
【发布时间】:2023-12-18 11:29:02
【问题描述】:

我正在使用 AVCaptureAudioDataOutputSampleBufferDelegate 捕获音频

  _captureSession = [[AVCaptureSession alloc] init];
  [self.captureSession setSessionPreset:AVCaptureSessionPresetLow];


  // Setup Audio input
  AVCaptureDevice *audioDevice = [AVCaptureDevice
                                defaultDeviceWithMediaType:AVMediaTypeAudio];
  AVCaptureDeviceInput *captureAudioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
  if(error){
      NSLog(@"Error Start capture Audio=%@", error);
  }else{
      if ([self.captureSession canAddInput:captureAudioInput]){
          [self.captureSession addInput:captureAudioInput];
      }
  }


  // Setup Audio output
  AVCaptureAudioDataOutput *audioCaptureOutput = [[AVCaptureAudioDataOutput alloc] init];
  if ([self.captureSession canAddOutput:audioCaptureOutput]){
      [self.captureSession addOutput:audioCaptureOutput];
  }
  [audioCaptureOutput release];


  //We create a serial queue 
  dispatch_queue_t audioQueue= dispatch_queue_create("audioQueue", NULL);
  [audioCaptureOutput setSampleBufferDelegate:self queue:audioQueue];
  dispatch_release(audioQueue);


  /*We start the capture*/
  [self.captureSession startRunning];

代表:

  - (void)captureOutput:(AVCaptureOutput *)captureOutput  didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

  // do something with sampleBuffer
  }

问题是如何从 sampleBuffer 播放音频?

【问题讨论】:

  • 嗨,您找到解决方案了吗?如果是这样,请更新答案。
  • 嗨,Newbee,不,仍在搜索
  • 任何解决方案。我也陷入了这个问题
  • 没有,还没有解决办法

标签: iphone objective-c ios avfoundation


【解决方案1】:

您可以使用以下代码从CMSampleBufferRef 创建NSData,然后使用AVAudioPlayer 播放。

- (void)captureOutput:(AVCaptureOutput *)captureOutput  didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

    AudioBufferList audioBufferList;
    NSMutableData *data= [NSMutableData data];
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);

    for( int y=0; y< audioBufferList.mNumberBuffers; y++ ){

        AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
        Float32 *frame = (Float32*)audioBuffer.mData;

        [data appendBytes:frame length:audioBuffer.mDataByteSize];

    }

    CFRelease(blockBuffer);

    AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:data error:nil];
    [player play];
}

我担心这会如何提高性能。可能有更好的方法来完成您想要完成的工作。

【讨论】:

  • 有一个问题 - 'player' 总是为零。你有什么想法吗?
  • 传入一个错误,看看有没有。还要确保数据不为零
  • 错误:错误域=NSOSStatusErrorDomain Code=1954115647“操作无法完成。(OSStatus错误1954115647。)怎么了?
  • 您必须添加一个标题,例如用于 AVAudioPlayer 的 WAV 标头,以了解它是一个声音文件。请参阅 Selwyn 在*.com/questions/8504620/… 的回答以了解功能正常的标题
  • CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer 为我返回 -12737 的 OSStatus,根据文档,它是 kCMSampleBufferError_ArrayTooSmall。然后代码在appendBytes:length: 上崩溃。有什么想法吗?