问题
I use AVCaptureSession to write to a mov file using AVAssetWriter. The same code on a pre-iOS 13 devices does not have the crackle. On all iOS 13 devices, regardless of iPhone/iPad model, have the audio crackle.
I've submitted this to Apple as a bug, but I'm worried I'm missing something simple. Is there anyone else experiencing this? Any ideas of settings I could change?
Things I've tried
- Changed mov -> mpeg
- Tried multiple audio codecs (particularly AppleLossless and AAC)
- Pushed to main queue instead of a designated captureQueue
- Tried AVCaptureMovieFileOutput, crackle not present. Issue is specific to AVAssetWriter
- AVCaptureSession always gives audio in 44100, so I resampled it in AVAssetWriter to 48000. Crackle still present.
ANY ideas would be helpful!
Setup
self.session = [[AVCaptureSession alloc] init];
[self.session setSessionPreset:AVCaptureSessionPresetiFrame1280x720];
NSError *error;
AVCaptureDevice *inputVideoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *deviceVideoInput = [AVCaptureDeviceInput deviceInputWithDevice:inputVideoDevice error:&error];
if ([self.session canAddInput:deviceVideoInput]) {
[self.session addInput:deviceVideoInput];
}
AVCaptureDevice* mic = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput* micinput = [AVCaptureDeviceInput deviceInputWithDevice:mic error:nil];
if ([self.session canAddInput:micinput]) {
[self.session addInput:micinput];
}
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
output.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) };
[output setSampleBufferDelegate:self queue:_captureQueue];
[self.session addOutput:output];
AVCaptureAudioDataOutput* audioout = [[AVCaptureAudioDataOutput alloc] init];
[audioout setSampleBufferDelegate:self queue:_captureQueue];
[self.session addOutput:audioout];
[self setCameraPosition:NO];
[self.session startRunning];
self.preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];
self.preview.videoGravity = AVLayerVideoGravityResizeAspect;
AVAssetWriter init
_path = path;
[[NSFileManager defaultManager] removeItemAtPath:_path error:nil];
NSURL *url = [NSURL fileURLWithPath:self.path];
_writer = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeQuickTimeMovie error:nil];
NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithFloat: frameSize.width], AVVideoWidthKey,
[NSNumber numberWithFloat: frameSize.height], AVVideoHeightKey,
nil];
_videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:settings];
_videoInput.expectsMediaDataInRealTime = YES;
[_writer addInput:_videoInput];
AudioChannelLayout acl;
bzero( &acl, sizeof(acl));
acl.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
settings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt:(int)channels], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat:sampleRate], AVSampleRateKey,
[ NSNumber numberWithInt: 64000 ], AVEncoderBitRateKey,
nil];
_audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:settings];
_audioInput.expectsMediaDataInRealTime = YES;
[_writer addInput:_audioInput];
[_writer startWriting];
UPDATE:: iPhone 11+ devices do NOT have the crackle, seems like something they changed under the hood with the codecs that causes an issue with 'older' devices. I have submitted a bug with Apple and used a Tech Support. Tech support has verified iPhone 11's are fine while anything older has the issue. There has been zero response to the bug ticket.
If you can stay away from AVAssetWriter for the foreseeable future.
来源:https://stackoverflow.com/questions/58895544/avassetwriter-has-an-audio-crackle-only-on-ios-13-devices