从图像创建视频并保存到相册
Posted
技术标签:
【中文标题】从图像创建视频并保存到相册【英文标题】:create video from images and save to photo album 【发布时间】:2012-10-31 21:54:12 【问题描述】:我正在用一组图像和一个音频文件制作视频
但我似乎无法将其保存到相机胶卷
有时它会保存,但有时它不会并给我一个奇怪的错误
outputFile.mp4 无法保存到已保存的相册中:Error Domain=NSOSStatusErrorDomain Code=-12848 “电影无法播放。” UserInfo=0x7bd7370 NSLocalizedDescription=电影无法播放。
此函数从图像数组创建视频:
-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size
NSLog(@"Write Started");
NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
[NSURL fileURLWithPath:path] fileType:AVFileTypeMPEG4
error:&error];
NSParameterAssert(videoWriter);
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:size.width], AVVideoWidthKey,
[NSNumber numberWithInt:size.height], AVVideoHeightKey,
nil];
AVAssetWriterInput* videoWriterInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
sourcePixelBufferAttributes:nil];
NSParameterAssert(videoWriterInput);
NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
videoWriterInput.expectsMediaDataInRealTime = YES;
[videoWriter addInput:videoWriterInput];
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
//convert uiimage to CGImage.
int frameCount = 16;
int kRecordingFPS = 30;
UIImage * im = [UIImage imageNamed:@"IMG_0103.JPG"];
NSArray * imageArray = [[NSArray alloc]initWithObjects:im,im,im,im,im,im,im,im,im,im,im,im,im,im,im,im, nil];
for(UIImage * img in imageArray)
buffer = [self pixelBufferFromCGImage:[img CGImage] andSize:size];
BOOL append_ok = NO;
int j = 0;
while (!append_ok && j < 30)
if (adaptor.assetWriterInput.readyForMoreMediaData)
printf("appending %d attemp %d\n", frameCount, j);
CMTime frameTime = CMTimeMake(frameCount,(int32_t) kRecordingFPS);
append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
if(buffer)
CVBufferRelease(buffer);
[NSThread sleepForTimeInterval:0.05];
else
printf("adaptor not ready %d, %d\n", frameCount, j);
[NSThread sleepForTimeInterval:0.1];
j++;
if (!append_ok)
printf("error appending image %d times %d\n", frameCount, j);
frameCount++;
//Finish the session:
[videoWriterInput markAsFinished];
[videoWriter finishWriting];
NSLog(@"Write Ended");
[videoWriterInput release];
[videoWriter release];
[imageArray release];
此函数添加音频:
-(void)CompileFilesToMakeMovie
AVMutableComposition* mixComposition = [AVMutableComposition composition];
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* audio_inputFileName = @"Rihanna-Take a Bow.mp3";
NSString* audio_inputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,audio_inputFileName];
NSURL* audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];
NSString* video_inputFileName = @"a.mp4";
NSString* video_inputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,video_inputFileName];
NSURL* video_inputFileUrl = [NSURL fileURLWithPath:video_inputFilePath];
NSString* outputFileName = @"outputFile.mp4";
NSString* outputFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,outputFileName];
NSURL* outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
[[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];
CMTime nextClipStartTime = kCMTimeZero;
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:video_inputFileUrl options:nil];
CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[a_compositionVideoTrack insertTimeRange:video_timeRange ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];
//nextClipStartTime = CMTimeAdd(nextClipStartTime, a_timeRange.duration);
AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:audio_inputFileUrl options:nil];
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration);
AVMutableCompositionTrack *b_compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[b_compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:nextClipStartTime error:nil];
AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];
_assetExport.outputFileType = AVFileTypeMPEG4;
_assetExport.outputURL = outputFileUrl;
[_assetExport setTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)];
[_assetExport exportAsynchronouslyWithCompletionHandler:nil];
[audioAsset release];
[videoAsset release];
[_assetExport release];
函数调用:
- (void)viewDidLoad
[super viewDidLoad];
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * i = [UIImage imageNamed:@"IMG_0103.JPG"];
[self writeImagesToMovieAtPath:[NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mp4"] withSize:CGSizeMake(i.size.width, i.size.height)];
NSString* exportVideoPath1 = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mp4"];
NSString* exportVideoPath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"outputFile.mp4"];
UISaveVideoAtPathToSavedPhotosAlbum (exportVideoPath,self, @selector(video:didFinishSavingWithError: contextInfo:), nil);
【问题讨论】:
你能再清楚一点。你做了一个应用程序,将图片转换为视频,然后保存视频?有时它并没有拯救他们?你有什么代码可以分享一下你的 dong 方法吗? 我添加的代码主要是我在这篇文章中使用的代码:***.com/a/6094407/1708270 这正是发生的事情,有时它会保存,有时它也不会自行将错误代码更改为 (Code=-12893) 不确定这是否有帮助。但是在将图像保存到 ALAssetsGroup 时我遇到了类似的问题(图像到画廊,类似于你正在做的事情),它有时会起作用,但有时会不起作用。问题似乎是操作系统在一段时间内阻止了调用。我通过添加代码以在等待(例如 0.1 秒)后再次尝试失败来解决这个问题。这解决了我的问题。如果遇到错误,请尝试添加呼叫以在延迟一段时间后重试。 我让它休眠 1 秒然后尝试保存增益,但它一直在尝试并给出相同的错误@Bergasms THX 任何方式:D 【参考方案1】:就我而言,原因是 AVAssetWriter 尚未完成写入。使用以下代码解决了它:
__block BOOL _finished = NO;
[assetWriter finishWritingWithCompletionHandler:^
_finished = YES;
];
while (!_finished)
[NSThread sleepForTimeInterval:0.1];
【讨论】:
以上是关于从图像创建视频并保存到相册的主要内容,如果未能解决你的问题,请参考以下文章
如何将图像保存到具有来自先前视图控制器的 id 的单独相册中
如何使用 PHPhotoLibrary 将视频/图像写入保存的相册?
将图像保存在 iOS 相册(我的文件夹)中并存储图像 url