使用 Obj-C 插件和 AVAssetWriterInput 向视频添加音频
Posted
技术标签:
【中文标题】使用 Obj-C 插件和 AVAssetWriterInput 向视频添加音频【英文标题】:Adding audio to a video using Obj-C plugin and AVAssetWriterInput 【发布时间】:2012-10-17 18:28:24 【问题描述】:我正在尝试拍摄使用 iVidCap 插件创建的视频并向其添加音频。基本上与这个问题完全相同:Writing video + generated audio to AVAssetWriterInput, audio stuttering。我使用这篇文章中的代码作为基础尝试自己修改 iVidCap.mm 文件,但应用程序总是在 endRecordingSession 中崩溃。
我不确定我需要如何修改 endRecordingSession 以适应音频(原始插件只是创建一个视频文件)。这是函数:
- (int) endRecordingSession: (VideoDisposition) action
NSLog(@"Start endRecordingSession");
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Auto released pool");
NSString *filePath;
BOOL success = false;
[videoWriterInput markAsFinished];
NSLog(@"Mark video writer input as finished");
//[audioWriterInput markAsFinished];
// Wait for the video status to become known.
// Is this really doing anything?
int status = videoWriter.status;
while (status == AVAssetWriterStatusUnknown)
NSLog(@"Waiting for video to complete...");
[NSThread sleepForTimeInterval:0.5f];
status = videoWriter.status;
NSLog(@"Video completed");
@synchronized(self)
success = [videoWriter finishWriting];
NSLog(@"Success: %@", success);
if (!success)
// We failed to successfully finalize the video file.
NSLog(@"finishWriting returned NO");
else
// The video file was successfully written to the Documents folder.
filePath = [[self getDocumentsFileURL:videoFileName] path];
if (action == Save_Video_To_Album)
// Move the video to an accessible location on the device.
NSLog(@"Temporary video filePath=%@", filePath);
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath))
NSLog(@"Video IS compatible. Adding it to photo album.");
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector(copyToPhotoAlbumCompleteFromVideo: didFinishSavingWithError: contextInfo:), nil);
else
NSLog(@"Video IS NOT compatible. Could not be added to the photo album.");
success = NO;
else if (action == Discard_Video)
NSLog(@"Video cancelled. Removing temporary video file: %@", filePath);
[self removeFile:filePath];
[self cleanupWriter];
isRecording = false;
[pool drain];
return success;
现在它在 [videoWriter finishWriting] 上崩溃。我尝试添加 [audioWriterInput markAsFinished],但随后它崩溃了。我会联系原始发帖者,因为他们似乎可以正常工作,但似乎没有办法发送私人消息。
是否有人对我如何使其工作或为什么会崩溃有任何建议?我已经尽力解决这个问题,但我对 Obj-C 还是很陌生。如果需要,我可以发布其余代码(其中很多都在前面引用的原始帖子中)。
【问题讨论】:
【参考方案1】:问题实际上可能出在 writeAudioBuffer 函数中。
如果你从那篇文章中复制了代码但没有更改它,那么你肯定会遇到一些问题。
你需要做这样的事情:
if ( ![self waitForAudioWriterReadiness])
NSLog(@"WARNING: writeAudioBuffer dropped frame after wait limit reached.");
return 0;
OSStatus status;
CMBlockBufferRef bbuf = NULL;
CMSampleBufferRef sbuf = NULL;
size_t buflen = n * nchans * sizeof(float);
CMBlockBufferRef tmp_bbuf = NULL;
status = CMBlockBufferCreateWithMemoryBlock(
kCFAllocatorDefault,
samples,
buflen,
kCFAllocatorDefault,
NULL,
0,
buflen,
0,
&tmp_bbuf);
if (status != noErr || !tmp_bbuf)
NSLog(@"CMBlockBufferCreateWithMemoryBlock error");
return -1;
// Copy the buffer so that we get a copy of the samples in memory.
// CMBlockBufferCreateWithMemoryBlock does not actually copy the data!
//
status = CMBlockBufferCreateContiguous(kCFAllocatorDefault, tmp_bbuf, kCFAllocatorDefault, NULL, 0, buflen, kCMBlockBufferAlwaysCopyDataFlag, &bbuf);
//CFRelease(tmp_bbuf); // causes abort?!
if (status != noErr)
NSLog(@"CMBlockBufferCreateContiguous error");
//CFRelease(bbuf);
return -1;
CMTime timestamp = CMTimeMake(sample_position_, 44100);
status = CMAudiosampleBufferCreateWithPacketDescriptions(
kCFAllocatorDefault, bbuf, TRUE, 0, NULL, audio_fmt_desc_, 1, timestamp, NULL, &sbuf);
sample_position_ += n;
if (status != noErr)
NSLog(@"CMSampleBufferCreate error");
return -1;
BOOL r = [audioWriterInput appendSampleBuffer:sbuf];
if (!r)
NSLog(@"appendSampleBuffer error");
//CFRelease(bbuf); // crashes, don't know why.. Is there a leak here?
//CFRelease(sbuf);
return 0;
我在这里不确定与内存管理有关的一些事情。
另外一定要使用:
audioWriterInput.expectsMediaDataInRealTime = YES;
【讨论】:
以上是关于使用 Obj-C 插件和 AVAssetWriterInput 向视频添加音频的主要内容,如果未能解决你的问题,请参考以下文章
如何将 obj-c NSDictionary 传递给 dart
如何在 IOS/SWIFT/OBJ-C/CORDOVa 上获取手指 ID(哪个手指用于触摸 ID)或唯一触摸 ID
OBJ-C 操作方法:在同一设备中使用 BLE 连接和 iBeacon 的应用程序