- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在开发一个同时做两件事的 iOS 应用:
不幸的是,当我们使用音频单元配置应用程序以启用回声消除时,录音功能会中断:我们用来编码音频的 AVAssetWriterInput
实例拒绝传入样本。当我们不设置音频单元时,录音工作正常,但回声很糟糕。
为了启用回声消除,我们像这样配置一个音频单元(为简洁起见解释):
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
AudioComponent comp = AudioComponentFindNext(NULL, &desc);
OSStatus status = AudioComponentInstanceNew(comp, &_audioUnit);
status = AudioUnitInitialize(_audioUnit);
这对于视频聊天来说效果很好,但它破坏了录音功能,录音功能是这样设置的(再次解释——实际的实现分散在几个方法中)。
_captureSession = [[AVCaptureSession alloc] init];
// Need to use the existing audio session & configuration to ensure we get echo cancellation
_captureSession.usesApplicationAudioSession = YES;
_captureSession.automaticallyConfiguresApplicationAudioSession = NO;
[_captureSession beginConfiguration];
AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self audioCaptureDevice] error:NULL];
[_captureSession addInput:audioInput];
_audioDataOutput = [[AVCaptureAudioDataOutput alloc] init];
[_audioDataOutput setSampleBufferDelegate:self queue:_cameraProcessingQueue];
[_captureSession addOutput:_audioDataOutput];
[_captureSession commitConfiguration];
captureOutput
的相关部分看起来像这样:
NSLog(@"Audio format, channels: %d, sample rate: %f, format id: %d, bits per channel: %d", basicFormat->mChannelsPerFrame, basicFormat->mSampleRate, basicFormat->mFormatID, basicFormat->mBitsPerChannel);
if (_assetWriter.status == AVAssetWriterStatusWriting) {
if (_audioEncoder.readyForMoreMediaData) {
if (![_audioEncoder appendSampleBuffer:sampleBuffer]) {
NSLog(@"Audio encoder couldn't append sample buffer");
}
}
}
调用 appendSampleBuffer
失败了,但是——这是奇怪的部分——只有当我没有将耳机插入我的手机时。检查发生这种情况时产生的日志,我发现在没有连接耳机的情况下,日志消息中报告的 channel 数为3,而有耳机时, channel 数为1
.这解释了编码操作失败的原因,因为编码器被配置为只需要一个 channel 。
我不明白的是为什么我在这里得到三个 channel 。如果我注释掉初始化音频单元的代码,我只能得到一个 channel 并且录音工作正常,但回声消除不起作用。此外,如果我删除这些行
// Need to use the existing audio session & configuration to ensure we get echo cancellation
_captureSession.usesApplicationAudioSession = YES;
_captureSession.automaticallyConfiguresApplicationAudioSession = NO;
录音有效(无论有无耳机,我只能得到一个 channel ),但同样,我们失去了回声消除。
所以,我的问题的症结在于:当我配置一个音频单元以提供回声消除时,为什么我会得到三个音频 channel ?此外,是否有任何方法可以防止这种情况发生或使用 AVCaptureSession
解决此问题?
我考虑过将麦克风音频直接从低级音频单元回调传输到编码器以及聊天管道,但似乎需要必要的 Core Media 缓冲区才能做到这一点如果可能,我想避免的工作。
请注意,聊天和录音功能是由不同的人编写的——他们都不是我——这就是这段代码没有更加集成的原因。如果可能的话,我想避免重构整个困惑局面。
最佳答案
最终,我通过 I/O 音频单元从麦克风收集音频样本,将这些样本重新打包到 CMSampleBuffer
,并传递新构建的 来解决这个问题CMSampleBuffer
进入编码器。
进行转换的代码如下所示(为简洁起见进行了缩写)。
// Create a CMSampleBufferRef from the list of samples, which we'll own
AudioStreamBasicDescription monoStreamFormat;
memset(&monoStreamFormat, 0, sizeof(monoStreamFormat));
monoStreamFormat.mSampleRate = 48000;
monoStreamFormat.mFormatID = kAudioFormatLinearPCM;
monoStreamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved;
monoStreamFormat.mBytesPerPacket = 2;
monoStreamFormat.mFramesPerPacket = 1;
monoStreamFormat.mBytesPerFrame = 2;
monoStreamFormat.mChannelsPerFrame = 1;
monoStreamFormat.mBitsPerChannel = 16;
CMFormatDescriptionRef format = NULL;
OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &monoStreamFormat, 0, NULL, 0, NULL, NULL, &format);
// Convert the AudioTimestamp to a CMTime and create a CMTimingInfo for this set of samples
uint64_t timeNS = (uint64_t)(hostTime * _hostTimeToNSFactor);
CMTime presentationTime = CMTimeMake(timeNS, 1000000000);
CMSampleTimingInfo timing = { CMTimeMake(1, 48000), presentationTime, kCMTimeInvalid };
CMSampleBufferRef sampleBuffer = NULL;
status = CMSampleBufferCreate(kCFAllocatorDefault, NULL, false, NULL, NULL, format, numSamples, 1, &timing, 0, NULL, &sampleBuffer);
// add the samples to the buffer
status = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer,
kCFAllocatorDefault,
kCFAllocatorDefault,
0,
samples);
// Pass the buffer into the encoder...
请注意,我已经删除了分配对象的错误处理和清理。
关于ios - 一起使用 AVCaptureSession 和音频单元会导致 AVAssetWriterInput 出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31283122/
我正在开发一个视频录制应用程序,需要能够使用蓝牙麦克风作为音频输入(如果已连接)。 我有以下代码来配置 AVCaptureSession 的音频输入: self.captureSession.uses
对于这个“愚蠢”的问题,我提前表示歉意,但我觉得我已经用尽了所有资源。我对 Swift 和一般编码几乎没有经验,但根据过去的经验和基于对象的编程(如 MAX MSP)的使用,我了解了很多。 我正在尝试
我正在尝试将捕获的帧记录为视频,同时并行地对帧执行图像处理任务。 我有一个 AVCaptureSession,我已将两个单独的输出添加到 - AVCaptureVideoDataOutput AVCa
当我尝试构建我的应用程序时,XCode 向我显示此错误 AVCaptureSession 之前应有“(” 有人可以帮我解决这个警告吗?这是我的代码: ViewController.h #import
我能够根据 http://developer.apple.com/iphone/library/qa/qa2010/qa1702.html 使用 AVCaptureSession 从相机捕获视频帧。但
我正在开发一个处理高清照片的应用程序。我正在使用 AVCaptureSession 拍照,停止它,然后对该照片应用效果。 让我疯狂的是,一切都运行良好,仪器告诉我,我正确且按时地释放了我使用的所有内存
我正在构建一个应用程序,允许用户使用 iPhone 相机拍照,并在可用时使用 AVFoundation (iOS4),以便用户可以使用点击对焦功能,即使使用自定义叠加层也是如此。 我遇到的问题是cap
所以这是一个普遍问题,但我们正在寻找有关如何让实时相机 View 能够在顶部添加图像并拍照的线索。所以基本上你可以选择像“帽子”一样覆盖在相机上的图像,调整其大小和位置,然后拍照,“帽子”将出现在你拍
我正在做一个 iOS 应用程序,需要使用这样的层次结构对 QR 码进行验证: View ---Scan View ---Image View - cardBG ---Inside View 加载 Vi
我正在尝试使用 AVCaptureSession 制作自定义相机。 代码和一切工作正常。唯一的问题是 VideoOutput 层被缩放。这使我的照片默认缩放。 我尝试了每件事,但无法找到解决方案。这是
我正在使用 AVCaptureSession 创建带有 AVCaptureMetadataOutput 的 QR 码扫描仪。 一切都按预期工作,但是我想在扫描仪上放置图形叠加层。这样做时,我希望扫描仪
弹出 View Controller 时,我在使用 AVCaptureSession 时遇到一些困难。我在导航 Controller 中有一个 View Controller ,用户可以在其中拍照。捕
有人知道如何使用 AVFoundation (AVCaptureStillImageOutput) 在自定义 iOS 相机中设置自定义分辨率吗? 我知道您可以使用 AVCaptureSession 选
我需要做这样的事情。我的应用程序使用 AVCapturesession 进行录制,但它应该能够流式传输带有我播放过的背景音乐的实时提要。 请记住,我可以使用 AVCapturesession 播放背景
当 AVCaptureSession 的 session 运行到本地 NSMutableArray 中捕获图像时,我收到 didReceiveMemoryWarning 调用。稍作测试后,我发现它发生
我正在尝试将 AVCaptureSession 的音频静音和取消静音。开始 session 后,我可以启用和禁用音频连接,但是一旦我播放视频,所有音频部分都会被推回视频的前面,只留下视频的结尾没有声音
我已经为 ios 应用程序添加了二维码阅读器代码现在我想使用可以用作 ios 中的 Today 扩展的相同代码。我已将以下代码用于应用程序和扩展。该应用程序运行良好,但不适用于扩展程序。 我用过htt
如何使用 AVCaptureSession 录制方形视频?如果在录制时不可能,那么我如何在 didFinishRecordingTo 委托(delegate)方法中裁剪它? 提前致谢! 最佳答案 您可
我收到一条警告: (sending "ViewController *const_strong' to parameter of incompatible type 'id' 执行这行代码时 [out
在我的应用程序中,我录制长达 30 秒的视频。我使用以下行来执行此操作。 [imagePicker setVideoMaximumDuration:30]; 一切正常。然后我决定从 UIImagePi
我是一名优秀的程序员,十分优秀!