- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我正在尝试使用 AVAssetWriter 将 CGImages 写入文件以从图像创建视频。
我已经让它在模拟器上以三种不同的方式成功运行,但在运行 iOS 4.3 的 iPhone 4 上,每种方法都失败了。
这都与像素缓冲区有关。
我的第一个方法是只根据需要创建像素缓冲区,而不使用池。这行得通,但内存占用太大,无法在设备上运行。
我的第二种方法是使用推荐的 AVAssetWriterInputPixelBufferAdaptor,然后使用 CVPixelBufferPoolCreatePixelBuffer 从适配器 pixelBufferPool 中提取像素缓冲区。
这也适用于模拟器,但在设备上失败,因为从未分配适配器的像素缓冲池。我没有收到任何错误消息。
最后,我尝试使用 CVPixelBufferPoolCreate 创建自己的像素缓冲池。这也适用于模拟器,但在设备上,一切正常,直到我尝试使用 appendPixelBuffer 附加像素缓冲区,但每次都失败。
我在网上找到的这方面信息非常少。我的代码基于我发现的示例,但现在好几天都没有运气。如果任何人有成功使用 AVAssetWriter 执行此操作的经验,请看一下,如果您发现任何不合适的地方,请告诉我。
注意:您会看到注释掉的尝试 block 。
首先,设置
- (BOOL) openVideoFile: (NSString *) path withSize:(CGSize)imageSize {
size = CGSizeMake (480.0, 320.0);//imageSize;
NSError *error = nil;
videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie
error:&error];
if (error != nil)
return NO;
NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:size.width], AVVideoCleanApertureWidthKey,
[NSNumber numberWithDouble:size.height], AVVideoCleanApertureHeightKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
nil];
NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], AVVideoPixelAspectRatioHorizontalSpacingKey,
[NSNumber numberWithInt:1],AVVideoPixelAspectRatioVerticalSpacingKey,
nil];
NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
//[NSNumber numberWithInt:960000], AVVideoAverageBitRateKey,
// [NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
videoCleanApertureSettings, AVVideoCleanApertureKey,
videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
//AVVideoProfileLevelH264Main31, AVVideoProfileLevelKey,
nil];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
codecSettings,AVVideoCompressionPropertiesKey,
[NSNumber numberWithDouble:size.width], AVVideoWidthKey,
[NSNumber numberWithDouble:size.height], AVVideoHeightKey,
nil];
writerInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
NSMutableDictionary * bufferAttributes = [[NSMutableDictionary alloc] init];
[bufferAttributes setObject: [NSNumber numberWithInt: kCVPixelFormatType_32ARGB]
forKey: (NSString *) kCVPixelBufferPixelFormatTypeKey];
[bufferAttributes setObject: [NSNumber numberWithInt: 480]
forKey: (NSString *) kCVPixelBufferWidthKey];
[bufferAttributes setObject: [NSNumber numberWithInt: 320]
forKey: (NSString *) kCVPixelBufferHeightKey];
//NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil];
//[bufferAttributes setObject: [NSNumber numberWithInt: 640]
// forKey: (NSString *) kCVPixelBufferWidthKey];
//[bufferAttributes setObject: [NSNumber numberWithInt: 480]
// forKey: (NSString *) kCVPixelBufferHeightKey];
adaptor = [[AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:nil] retain];
//CVPixelBufferPoolCreate (kCFAllocatorSystemDefault,NULL,(CFDictionaryRef)bufferAttributes,&pixelBufferPool);
//Create buffer pool
NSMutableDictionary* attributes;
attributes = [NSMutableDictionary dictionary];
int width = 480;
int height = 320;
[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_32ARGB] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithInt:width] forKey: (NSString*)kCVPixelBufferWidthKey];
[attributes setObject:[NSNumber numberWithInt:height] forKey: (NSString*)kCVPixelBufferHeightKey];
CVReturn theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (CFDictionaryRef) attributes, &pixelBufferPool);
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
[videoWriter addInput:writerInput];
writerInput.expectsMediaDataInRealTime = YES;
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
buffer = NULL;
lastTime = kCMTimeZero;
presentTime = kCMTimeZero;
return YES;
}
接下来,追加写入器和创建要追加的像素缓冲区的两个方法。
- (void) writeImageToMovie:(CGImageRef)image
{
if([writerInput isReadyForMoreMediaData])
{
// CMTime frameTime = CMTimeMake(1, 20);
// CMTime lastTime=CMTimeMake(i, 20); //i is from 0 to 24 of the loop above
// CMTime presentTime=CMTimeAdd(lastTime, frameTime);
buffer = [self pixelBufferFromCGImage:image];
BOOL success = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
if (!success) NSLog(@"Failed to appendPixelBuffer");
CVPixelBufferRelease(buffer);
presentTime = CMTimeAdd(lastTime, CMTimeMake(5, 1000));
lastTime = presentTime;
}
else
{
NSLog(@"error - writerInput not ready");
}
}
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
CVPixelBufferRef pxbuffer;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
if (pixelBufferPool == NULL) NSLog(@"pixelBufferPool is null!");
CVReturn status = CVPixelBufferPoolCreatePixelBuffer (NULL, pixelBufferPool, &pxbuffer);
/*if (pxbuffer == NULL) {
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width,
size.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,
&pxbuffer);
}*/
//NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
//NSParameterAssert(pxdata != NULL);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, size.width,
size.height, 8, 4*size.width, rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
//NSParameterAssert(context);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake(90, 10, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
最佳答案
我已经找到了这个问题的解决方案。
如果你想让 AVAudioPlayer 和 AVAssetWriter 一起正确运行,你必须有一个“可混合”的 Audio Session 类别。
您可以使用可混合的类别,例如 AVAudioSessionCategoryAmbient。
但是,我需要使用 AVAudioSessionCategoryPlayAndRecord。
您可以通过实现此设置将任何类别设置为可混合:
OSStatus propertySetError = 0;
UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers, // 1
sizeof (allowMixing), // 2
&allowMixing // 3
);
关于iphone - AVAssetWriter 困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6189535/
有人知道如何在 AVFoundation 中使用 AVAssetWriter 将未压缩的帧存储到 mov 中吗?对于 ProRes4444 内容,我实际上使用了以下片段: NSDictionary *
我在iOS上使用AVAssetWriter编码MP4视频。我目前正在使用AVAssetWriterInputPixelBufferAdaptor传递数据,但是在这方面我很灵活。 如何指定哪些输入框是关
我使用以下代码附加PixelBuffer,但输出视频是黑屏(CIImage 是正常的)。我认为问题出现在 newPixelBuffer 中。 func recordRealTimeFilterVide
为什么当您加载纵向 JPGS 并尝试使用 AVAssetWriter 时,生成的 mov 文件旋转了 90? 其他人看到了吗? 最佳答案 如果肖像 jpg 是在 iphone 上制作的,则它们的原始像
此代码适用于从图像创建视频。 AVAssetWritter 工作正常,没有错误并导出输出视频 - (.mov)。但在某些图像大小的情况下它会失败。120 x 160 - 失败180 x 640、240
我正在尝试将多个视频文件合并到一个具有特定编解码器设置的文件中。我曾经为此使用 AVAssetExportSession,但现在我需要比 AVAssetExportSession 提供更多的编解码器控
我正在 iOS 上编写一个视频编辑小应用。我关注了 this question 中评价最高的答案想用AVAssetwriter,最后写入还是失败了。当我进入 complete 回调时 [videoWr
创建 assetwriter 后,我的 friend 在他的设备上收到此错误 - 日志:AVAssetWriter:0x1e051900,outputURL = file://localhost/va
我有以下代码在 AVAssetWriter 中写入日期元数据,这在 iOS 13 中完全错误。需要知道这是 iOS 13 错误还是我做错了什么。 private var metadataIt
我正在完成一个将电影保存到相册的 iPhone 应用程序。电影源是一组图像。我用它制作电影并将它们很好地放入相册,但它总是在开始时有一个额外的绿色框架。 有什么想法吗? 我重新阅读了 Apple
我正在尝试使用 OSX AVAsset 类从电影文件中读取视频帧,调整颜色,然后将它们写出到新的电影文件中。我已经完成了所有工作,除了出于某种奇怪的原因,当我正在阅读以每秒 29.97 帧播放的视频时
我有几种方法可以将 mov 文件中的视频写入临时目录,但在大约 15 秒后。我收到错误: 收到内存警告。 收到内存警告。 收到内存警告。 收到内存警告。 然后应用程序崩溃了。我被卡住了,不知道出了什么
你好,我是 ios 开发的新手,我遇到了一些问题 我做了一些 AVAssetWriter 的设置,比如对象(我用它来写像素图作为视频的帧 - 它工作正常) self.assetWriter =
我录制音频和视频文件。用户可以只从视频切换到音频,也可以从音频切换到视频。但是当我从音频切换到视频时,第一帧是黑色的。 切换 func switch_to_audio(){ capture_s
我正在使用 AVAssetWriter 通过委托(delegate)从 ARSession 写入视频帧。 func session(_ session: ARSession, didUpdate fr
我正在开发一个使用 AVAssetWriter 录制视频的应用程序(源媒体是从 captureOutput(_ output: AVCaptureOutput, didOutput sampleBuf
我正在制作一个录制视频的应用程序。到目前为止,我已经能够使用 AVCaptureMovieFileOutput 成功录制视频和音频,但是,我现在需要实时编辑视频帧以将一些数据叠加到视频上。我开始切换到
是否可以在 iPhone 上使用 avassetwriter 合成绿屏图像——绿色背景下的动画 Actor 和背景照片并制作视频。 我有一个应用程序可以在绿色背景下创建动画角色的一系列屏幕截图。我想将
我正在使用 AVAssetWriter 将音频(和/或视频)写入 quicktime 电影格式。如何在不停止 session (即继续记录)的情况下定期(每隔几分钟)保存(或备份)此文件? 这是我在录
如果我包含的图像没有填满整个渲染区域,我用 AVAssetWriter 编写的每个文件都有黑色背景。有什么方法可以写透明吗?这是我用来获取像素缓冲区的方法: - (CVPixelBufferRef)p
我是一名优秀的程序员,十分优秀!