从 UIImages 数组创建视频并将视频保存到 iPhone 库。 AVAssetLibrary 和 AVFoundation
将视频保存到 iPhone 库时出现问题。 我有一组 UIImages 和两个按钮,“convertToVideo”和“saveToiPhoneLib”
-(IBAction) convertToVideo { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; NSString *savedVideoPath = [documentsDirectory stringByAppendingPathComponent:@"videoOutput"]; printf(" \n\n\n-Video file == %s--\n\n\n",[savedVideoPath UTF8String]); [self writeImageAsMovie:imageArray toPath:savedVideoPath size:self.view.frame.size duration:3]; } here i'm passing the imageArray and savedVideoPath to the function below -(void)writeImageAsMovie:(NSArray *)array toPath:(NSString*)path size:(CGSize)size duration:(int)duration { NSError *error = nil; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie error:&error]; NSParameterAssert(videoWriter); NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:size.width], AVVideoWidthKey, [NSNumber numberWithInt:size.height], AVVideoHeightKey, nil]; AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; // NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil]; AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil]; NSParameterAssert(writerInput); NSParameterAssert([videoWriter canAddInput:writerInput]); [videoWriter addInput:writerInput]; //Start a session: [videoWriter startWriting]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; CVPixelBufferRef buffer = NULL; //convert uiimage to CGImage. buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:0] CGImage]]; [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; //Write samples: ...... //Finish the session: [writerInput markAsFinished]; [videoWriter finishWriting]; } generate a CVPixelBufferRef here - (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image { NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; CVPixelBufferRef pxbuffer = NULL; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, self.view.frame.size.width, self.view.frame.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, self.view.frame.size.width, self.view.frame.size.height, 8, 4*self.view.frame.size.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); NSParameterAssert(context); CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer; }
保存到 iPhone 库,
-(IBAction) saveToiPhoneLib { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; NSString *getImagePath = [basePath stringByAppendingPathComponent:@"videoOutput"]; printf(" \n\n\n-Video file == %s--\n\n\n",[getImagePath UTF8String]); UISaveVideoAtPathToSavedPhotosAlbum ( getImagePath,self, @selector(video:didFinishSavingWithError: contextInfo:), nil); } - (void) video: (NSString *) videoPath didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo { NSLog(@"Finished saving video with error: %@", error); }
但在保存时收到错误消息:-
已完成保存视频,但出现错误:Error Domain=ALAssetsLibraryErrorDomain Code=-3302“无效数据" UserInfo=0x1d59f0 {NSLocalizedFailureReason=写入此资产时出现问题,因为数据无效且无法查看或播放。, NSLocalizedRecoverySuggestion=尝试使用不同的数据,NSLocalizedDescription=无效数据}
请让我知道我的错误。提前致谢
Problem in saving video to iPhone Library.
i have an array of UIImages,and two buttons ,"convertToVideo"&"saveToiPhoneLib"
-(IBAction) convertToVideo { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; NSString *savedVideoPath = [documentsDirectory stringByAppendingPathComponent:@"videoOutput"]; printf(" \n\n\n-Video file == %s--\n\n\n",[savedVideoPath UTF8String]); [self writeImageAsMovie:imageArray toPath:savedVideoPath size:self.view.frame.size duration:3]; } here i'm passing the imageArray and savedVideoPath to the function below -(void)writeImageAsMovie:(NSArray *)array toPath:(NSString*)path size:(CGSize)size duration:(int)duration { NSError *error = nil; AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: [NSURL fileURLWithPath:path] fileType:AVFileTypeQuickTimeMovie error:&error]; NSParameterAssert(videoWriter); NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:size.width], AVVideoWidthKey, [NSNumber numberWithInt:size.height], AVVideoHeightKey, nil]; AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; // NSDictionary *bufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:kCVPixelFormatType_32ARGB], kCVPixelBufferPixelFormatTypeKey, nil]; AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil]; NSParameterAssert(writerInput); NSParameterAssert([videoWriter canAddInput:writerInput]); [videoWriter addInput:writerInput]; //Start a session: [videoWriter startWriting]; [videoWriter startSessionAtSourceTime:kCMTimeZero]; CVPixelBufferRef buffer = NULL; //convert uiimage to CGImage. buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:0] CGImage]]; [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero]; //Write samples: ...... //Finish the session: [writerInput markAsFinished]; [videoWriter finishWriting]; } generate a CVPixelBufferRef here - (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image { NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; CVPixelBufferRef pxbuffer = NULL; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, self.view.frame.size.width, self.view.frame.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, self.view.frame.size.width, self.view.frame.size.height, 8, 4*self.view.frame.size.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); NSParameterAssert(context); CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer; }
saving to the iPhone library
-(IBAction) saveToiPhoneLib { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; NSString *getImagePath = [basePath stringByAppendingPathComponent:@"videoOutput"]; printf(" \n\n\n-Video file == %s--\n\n\n",[getImagePath UTF8String]); UISaveVideoAtPathToSavedPhotosAlbum ( getImagePath,self, @selector(video:didFinishSavingWithError: contextInfo:), nil); } - (void) video: (NSString *) videoPath didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo { NSLog(@"Finished saving video with error: %@", error); }
but while saving i m getting error message:-
Finished saving video with error: Error Domain=ALAssetsLibraryErrorDomain Code=-3302 "Invalid data" UserInfo=0x1d59f0 {NSLocalizedFailureReason=There was a problem writing this asset because the data is invalid and cannot be viewed or played., NSLocalizedRecoverySuggestion=Try with different data, NSLocalizedDescription=Invalid data}
please let me know my mistake. thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
代码太多,无法检查错误。确保您可以启动导出会话,您确实获得了图像的像素缓冲区,编写器已准备好接收更多数据,缓冲区已无错误地附加,导出会话成功完成,并且输出电影文件存在并且实际上包含一些数据。然后您可以尝试将其保存到系统相册中。沿途检查所有可用的错误信息,以便您知道第一次出现问题的位置。 (另一件事是,您只是从网络上获取代码并将其粘贴在一起,这根本不适用于 AV 编程。)
That’s simply too much code to check for errors. Make sure you can start the export session, that you really get pixel buffers for your images, that the writer is ready for receiving more data, that the buffer gets appended without errors, that the export session finishes with success and that the output movie file exists and actually contains some data. Only then you can try and save it to the system photo album. Check all the available error information along the way so that you know where the thing breaks for the first time. (Another thing is that you are simply taking code from the web and pasting it together, which is simply not going to work for AV programming.)
是的,我有同样的错误:
但仅在模拟器上,当我在设备上运行时,保存到照片库工作得很好。
Yes, I had the same error:
But only on simulator, when I ran on a device, the save to the photo library worked just fine.
使用下面的代码
Use the code Below