你好傢伙需要在這裏快速幫助;我正嘗試使用在線教程將圖像轉換爲視頻。該過程在iphone/i-devices和quicktime上完成並正確播放,然而,當在任何其他播放器(如VLC realplayer,網絡播放器等)上播放時,它不會播放。看完最後生成的文件後,我可以看到視頻範圍在0到0.16之間的fps(理想情況下應該在24-30fps之間)。任何人都可以請建議一種方法來修復fps。我使用的代碼是下面:轉換圖像到視頻有錯誤的FPS ios
+ (void)createVideoWithImages:(NSArray <NSString *> *)images withDuration:(long int)duration completion:(void (^) (BOOL success, NSString *output, NSError *error))completion
{
__block BOOL success = NO;
__block NSString *videoOutputPath = [ViewController newfNameWithPath];
NSError *error = nil;
double width = 0;
double height = 0;
CGSize imageSize = CGSizeZero;
NSUInteger framesPerSecond = 30;
NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:images.count];
for (NSUInteger i = 0; i < [images count]; i++)
{
NSString *imagePath = [images objectAtIndex:i];
[imageArray addObject:[UIImage imageWithContentsOfFile:imagePath]];
UIImage *newImage = [ViewController createImage:((UIImage *)[imageArray objectAtIndex:i])];
UIImage *img = [ViewController imageOrientation:newImage];
[imageArray replaceObjectAtIndex:i withObject:img];
width = (width > ((UIImage *)[imageArray lastObject]).size.width) ? width : ((UIImage *)[imageArray lastObject]).size.width;
height = (height > ((UIImage *)[imageArray lastObject]).size.height) ? height : ((UIImage *)[imageArray lastObject]).size.height;
}
imageSize = CGSizeMake(1280, 720);
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[ViewController getURL:videoOutputPath] fileType:AVFileTypeQuickTimeMovie error:&error];
NSParameterAssert(videoWriter);
NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1280], AVVideoCleanApertureWidthKey,
[NSNumber numberWithInt:720], AVVideoCleanApertureHeightKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
nil];
NSDictionary *aspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:3], AVVideoPixelAspectRatioHorizontalSpacingKey,
[NSNumber numberWithInt:3],AVVideoPixelAspectRatioVerticalSpacingKey,
nil];
NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:960000], AVVideoAverageBitRateKey,
[NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
videoCleanApertureSettings, AVVideoCleanApertureKey,
aspectRatioSettings, AVVideoPixelAspectRatioKey,
//AVVideoProfileLevelH264Main30, AVVideoProfileLevelKey,
nil];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
codecSettings,AVVideoCompressionPropertiesKey,
[NSNumber numberWithInt: 1280], AVVideoWidthKey,
[NSNumber numberWithInt: 720], AVVideoHeightKey,
nil];
AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput sourcePixelBufferAttributes:nil];
NSParameterAssert(videoWriterInput);
NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
videoWriterInput.expectsMediaDataInRealTime = YES;
[videoWriter addInput:videoWriterInput];
videoWriterInput.transform = CGAffineTransformMakeRotation(M_PI_2 * 2);
if (![videoWriter startWriting])
{
completion(success, nil, videoWriter.error);
}
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
int frameCount = 0;
double numberOfSecondsPerFrame = duration/[imageArray count];
double frameDuration = framesPerSecond * numberOfSecondsPerFrame;
for(UIImage *image in imageArray)
{
buffer = [ViewController pixelBufferFromCGImage:[image CGImage] withSize:imageSize];
BOOL completeWitnNoError = NO;
int counter = 0;
while (!completeWitnNoError && counter < 30)
{
NSLog(@"writing image: %ld at frame: %d",(long)frameCount, counter);
if (adaptor.assetWriterInput.readyForMoreMediaData)
{
CMTime frameTime = CMTimeMake(frameCount*frameDuration, (int32_t)framesPerSecond);
CMTimeShow(frameTime);
completeWitnNoError = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
if(!completeWitnNoError)
{
if(buffer)
CVPixelBufferRelease(buffer);
completion(!completion, nil, videoWriter.error);
}
}
else
{
if(buffer)
CVPixelBufferRelease(buffer);
NSLog(@"adaptor not ready %d, %d\n", frameCount, counter);
[NSThread sleepForTimeInterval:0.1];
}
counter++;
}
if(buffer)
CVPixelBufferRelease(buffer);
if (!completeWitnNoError)
{
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Error\n", nil),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Images to video writing failed ", nil),
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Images to video writing failed ", nil)
};
NSError *error = [NSError errorWithDomain:@"Images to video error" code: -1005 userInfo:userInfo];
completion(!completion, nil, error);
}
frameCount++;
}
[videoWriterInput markAsFinished];
[videoWriter finishWritingWithCompletionHandler:^{
switch ([videoWriter status])
{
case AVAssetReaderStatusReading:
break;
case AVAssetReaderStatusCompleted:
{
NSLog(@"IMAGES TO VIDEO WRITE SUCCESS");
success = !success;
completion(success, videoOutputPath, videoWriter.error);
break;
}
case AVAssetReaderStatusCancelled:
{
NSLog(@"IMAGES TO VIDEO WRITE FAILURE");
completion(success, nil, videoWriter.error);
[videoWriter cancelWriting];
break;
}
case AVAssetReaderStatusFailed:
{
NSLog(@"IMAGES TO VIDEO WRITE FAILURE");
completion(success, nil, videoWriter.error);
[videoWriter cancelWriting];
break;
}
case AVAssetReaderStatusUnknown:
{
NSLog(@"IMAGES TO VIDEO WRITE FAILURE");
completion(success, nil, videoWriter.error);
[videoWriter cancelWriting];
break;
}
}
}];
return;
}
和緩衝液:
+ (CVPixelBufferRef) pixelBufferFromCGImage:(CGImageRef)image withSize:(CGSize)size
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
size.width,
size.height,
kCVPixelFormatType_32ARGB,
(__bridge CFDictionaryRef) options,
&pxbuffer);
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
if (status != kCVReturnSuccess)
{
NSString *description = [NSString stringWithFormat:@"Failed to create pixel buffer."];
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(description, nil),
NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Could create buffer", nil),
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Try again", nil)
};
NSError *error = [NSError errorWithDomain:@"CVPixelBufferRef" code: -1005 userInfo:userInfo];
NSLog(@"ALERT: %@", [error localizedDescription]);
}
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,
kCGImageAlphaPremultipliedFirst);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake((size.width/(CGImageGetWidth(image)/2)), (size.height/(CGImageGetWidth(image)/2)), 1280, 720), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
任何建議??
我們知道您的'framesPerSecond'是'30',但.. 。'duration'的值是多少,[imageArray count]是多少?你也可能想要一個2500000的視頻比特率,因爲960k/b對於720p來說圖像質量很低。 –
** _「......任何人都可以請建議一種方法來修復fps?」_ **。沒關係,我有一個愚蠢的想法,也許如果你分享這些數字,那麼一些志願者可以幫助你找出什麼是錯的。我懷疑你的輸入數字與你的分而號碼的問題。另外一個視頻總是有**一個FPS速率**,它不會做一個_「...視頻範圍在0到0.16之間的fps」_所以發生了什麼?提供重現問題所需的所有事實(不僅僅是具有未知神祕輸入的代碼轉儲)... –