Хорошо, я пошел писать собственное видео. Оказывается, если вы пишете видео с изображением, которое вы хотите в первом и последнем ключевых кадрах (и это единственные ключевые кадры), тогда вы получите приятное компактное видео, которое не займет слишком много времени, чтобы писать.
Мой код выглядит следующим образом:
- (CVPixelBufferRef) createPixelBufferOfSize: (CGSize) size fromUIImage: (UIImage*) pImage
{
NSNumber* numYes = [NSNumber numberWithBool: YES];
NSDictionary* pOptions = [NSDictionary dictionaryWithObjectsAndKeys: numYes, kCVPixelBufferCGImageCompatibilityKey,
numYes, kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef retBuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)pOptions, &retBuffer);
CVPixelBufferLockBaseAddress(retBuffer, 0);
void* pPixelData = CVPixelBufferGetBaseAddress(retBuffer);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pPixelData, size.width, size.height, 8, 4 * size.width, colourSpace, (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);
CGSize inSize = pImage.size;
float inAspect = inSize.width/inSize.height;
float outAspect = size.width /size.height;
CGRect drawRect;
if (inAspect > outAspect)
{
float scale = inSize.width/size.width;
CGSize outSize = CGSizeMake(size.width, inSize.height/scale);
drawRect = CGRectMake(0, (size.height/2) - (outSize.height/2), outSize.width, outSize.height);
}
else
{
float scale = inSize.height/size.height;
CGSize outSize = CGSizeMake(inSize.width/scale, size.height);
drawRect = CGRectMake((size.width/2) - (outSize.width/2), 0, outSize.width, outSize.height);
}
CGContextDrawImage(context, drawRect, [pImage CGImage]);
CGColorSpaceRelease(colourSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(retBuffer, 0);
return retBuffer;
}
- (void) writeVideo: (NSURL*) pURL withImage: (UIImage*) pImage ofLength: (NSTimeInterval) length
{
[[NSFileManager defaultManager] removeItemAtURL: pURL error: nil];
NSError* pError = nil;
AVAssetWriter* pAssetWriter = [AVAssetWriter assetWriterWithURL: pURL fileType: AVFileTypeQuickTimeMovie error: &pError];
const int kVidWidth = 1920;//pImage.size.width;
const int kVidHeight = 1080;//pImage.size.height;
NSNumber* numVidWidth = [NSNumber numberWithInt: kVidWidth];
NSNumber* numVidHeight = [NSNumber numberWithInt: kVidHeight];
NSDictionary* pVideoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey,
numVidWidth, AVVideoWidthKey,
numVidHeight, AVVideoHeightKey,
nil];
AVAssetWriterInput* pAssetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo
outputSettings: pVideoSettings];
[pAssetWriter addInput: pAssetWriterInput];
AVAssetWriterInputPixelBufferAdaptor* pAssetWriterInputPixelBufferAdaptor =
[AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput: pAssetWriterInput
sourcePixelBufferAttributes: pVideoSettings];
__block volatile int finished = 0;
[pAssetWriter startWriting];
[pAssetWriter startSessionAtSourceTime: kCMTimeZero];
// Write the image.
CVPixelBufferRef pixelBuffer = [self createPixelBufferOfSize: CGSizeMake(kVidWidth, kVidHeight) fromUIImage: pImage];
[pAssetWriterInputPixelBufferAdaptor appendPixelBuffer: pixelBuffer withPresentationTime: kCMTimeZero];
[pAssetWriterInputPixelBufferAdaptor appendPixelBuffer: pixelBuffer withPresentationTime: CMTimeMake(length * 1000000, 1000000)];
CVPixelBufferRelease(pixelBuffer);
[pAssetWriterInput markAsFinished];
// Set end time accurate to micro-seconds.
[pAssetWriter endSessionAtSourceTime: CMTimeMake(length * 1000000, 1000000)];
[pAssetWriter finishWritingWithCompletionHandler:^
{
OSAtomicIncrement32(&finished);
}];
// Wait for the writing to complete.
while(finished == 0)
{
[NSThread sleepForTimeInterval: 0.01];
}
}
Вы можете заметить, что я устанавливаю видео, чтобы всегда быть 1920х1080 и Letterboxing изображение на месте.
Хорошая идея. Как бы я это сделал, если бы это было не кратно 1 секунде? – Goz
Почему бы вам просто не использовать и UIImageView для показа изображения? – kchromik
Не вариант к сожалению. – Goz