我正在尝试从存储在项目资源文件夹中的图像数组中生成视频。我使用此代码生成视频......
- (void)viewDidLoad
{
imagearray=[[NSMutableArray alloc]initWithObjects:@"Quiz pic1.jpg",@"Quiz pic2.jpg",@"Quiz pic3.jpg",@"Quiz pic6.jpg",@"Quiz pic7.jpg",nil];
image1array=[[NSMutableArray alloc]init];
for (int i=0; i<[imagearray count]; i++)
{
UIImage *aimage=[UIImage imageNamed:[imagearray objectAtIndex:i]];
[image1array addObject:aimage];
}
NSLog(@"%@",image1array);
ImageVideoPath=@"/Users/image/Library/Application Support/iPhone Simulator/4.3/Applications/6CC91208-5819-4BFF-B868-6605887861EB/Output";
FinalVideoPath=@"/Users/image/Library/Application Support/iPhone Simulator/4.3/Applications/6CC91208-5819-4BFF-B868-6605887861EB/VideoOutput";
CGSize size;
UIImage *image=[UIImage imageNamed:[imagearray objectAtIndex:0]];
size=image.size;
NSString *audioFilePath;
int duration=10;
//[self pixelBufferFromCGImage:[[image1array objectAtIndex:0] CGImage]];
[self writeImageAndAudioAsMovie:image andAudio:audioFilePath duration:duration];
//[self pixelBufferFromCGImage:[image CGImage] andSize:size];
[super viewDidLoad];
}
- (void)writeImageAndAudioAsMovie:(UIImage*)image andAudio:(NSString *)audioFilePath duration:(int)duration {
NSLog(@"start make movie: length:%d",duration);
NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:ImageVideoPath] fileType:AVFileTypeQuickTimeMovie
error:&error];
NSParameterAssert(videoWriter);
if ([[NSFileManager defaultManager] fileExistsAtPath:ImageVideoPath])
[[NSFileManager defaultManager] removeItemAtPath:ImageVideoPath error:nil];
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:image.size.width],AVVideoWidthKey,[NSNumber numberWithInt:image.size.height], AVVideoHeightKey,nil];
AVAssetWriterInput* writerInput = [[AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings] retain];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil];
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
writerInput.expectsMediaDataInRealTime = YES;
[videoWriter setShouldOptimizeForNetworkUse:YES];
[videoWriter addInput:writerInput];
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
for (int i=0; i<[image1array count]; i++)
{
int time = (int)i*(duration/[image1array count]);
CVPixelBufferRef buffer = [self pixelBufferFromCGImage:[[image1array objectAtIndex:i] CGImage]];
[adaptor appendPixelBuffer:buffer withPresentationTime:CMTimeMake(time, 1)];
}
//Finish the session:
[videoWriter endSessionAtSourceTime:CMTimeMake(duration, 1)];
[writerInput markAsFinished];
[videoWriter finishWriting];
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
[videoWriter release];
[writerInput release];
audioFilePath=[[NSBundle mainBundle]pathForResource:@"Video" ofType:@"mp3"];
NSLog(@"%@",audioFilePath);
[self addAudioToFileAtPath:ImageVideoPath andAudioPath:audioFilePath];
}
-(CVPixelBufferRef)pixelBufferFromCGImage: (CGImageRef) image{
float width = CGImageGetWidth(image);
float height = CGImageGetHeight(image);
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width,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,width,height,8,4*width,rgbColorSpace,kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextDrawImage(context, CGRectMake(0, 0,width, height), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
我发现有些文件是在我运行代码后创建的,但它支持我机器中的所有玩家。 我不知道我在这里失踪。任何建议让我的代码工作......
答案 0 :(得分:0)
您是否真的想将图像转换为视频?为什么不动画图像本身来模仿视频。卡通的制作方式? IT会是这样的 -
NSArray *animImages = [[NSArray alloc] initWithObjects:
[UIImage imageWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"SodaPour1" ofType:@"png"]],
[UIImage imageWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"SodaPour39" ofType:@"png"]],
nil];
imgGlass.animationImages = GlassAnim;
imgGlass.animationDuration = 2.5;
imgGlass.contentMode = UIViewContentModeScaleAspectFit;
imgGlass.animationRepeatCount=1;
[GlassAnim release];
您也可以查看此内容 - How to animate images using bitmaps / rgb data in iOS
答案 1 :(得分:0)
*
- (IBAction)makeMovieButtonTouchUpInside:(id)sender {
if (selectedImageArray.count == 0) {
[[[UIAlertView alloc]initWithTitle:@"please select at least one image" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]show];
return;
}
NSString *documentsDirectory = [NSHomeDirectory()
stringByAppendingPathComponent:@"Documents"];
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:@"30secs" ofType:@"mp3"];
NSString *videoPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"test_output.mp4"]];
NSString *finalVideoFilePath = [documentsDirectory stringByAppendingPathComponent:@"final_video.mp4"];
UIImage *img = [selectedImageArray objectAtIndex:0];
NSLog(@"h:%@,w:%@",[NSNumber numberWithFloat:img.size.height],[NSNumber numberWithFloat:img.size.width]);
[self writeImageAndAudioAsMovie:img andVideoPath:videoPath andAudio:audioFilePath andFinalVideoPath:finalVideoFilePath duration:30];
}
*
NSLog(@"start make movie: length:%d",duration);
NSError *error = nil;
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:videoPath] fileType:AVFileTypeQuickTimeMovie error:&error];
NSParameterAssert(videoWriter);
if ([[NSFileManager defaultManager] fileExistsAtPath:videoPath]){//ImageVideoPath
[[NSFileManager defaultManager] removeItemAtPath:videoPath error:nil];
}
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecH264, AVVideoCodecKey,
[NSNumber numberWithInt:image.size.width],AVVideoWidthKey,
[NSNumber numberWithInt:image.size.height], AVVideoHeightKey,
nil];
AVAssetWriterInput* writerInput = [AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:videoSettings];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput sourcePixelBufferAttributes:nil];
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
writerInput.expectsMediaDataInRealTime = YES;
[videoWriter setShouldOptimizeForNetworkUse:YES];
[videoWriter addInput:writerInput];
//Start a session:
[videoWriter startWriting];
[videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
NSUInteger fps = 30;
int frameCount = 0;
double numberOfSecondsPerFrame = 6;
double frameDuration = fps * numberOfSecondsPerFrame;
for(UIImage * img in selectedImageArray)
{
buffer = [self pixelBufferFromCGImage:[img CGImage]];
BOOL append_ok = NO;
int j = 0;
while (!append_ok && j < 30) {
if (adaptor.assetWriterInput.readyForMoreMediaData) {
//print out status:
NSLog(@"Processing video frame (%d,%d)",frameCount,[imageArray count]);
CMTime frameTime = CMTimeMake(frameCount*frameDuration,(int32_t) fps);
append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
if(!append_ok){
NSError *error = videoWriter.error;
if(error!=nil) {
NSLog(@"Unresolved error %@,%@.", error, [error userInfo]);
}
}
}
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, with error.", frameCount, j);
}
frameCount++;
}
//Finish the session:
[videoWriter endSessionAtSourceTime:CMTimeMake(60*8, 1)];//give a user defined duration and endthe session
[writerInput markAsFinished];
NSURL *refURL = [[NSURL alloc] initFileURLWithPath:videoPath];
[videoArray addObject:refURL];
//get the iOS version of the device
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version < 6.0){
[videoWriter finishWriting];
NSLog (@"finished writing iOS version:%f",version);
} else {
[videoWriter finishWritingWithCompletionHandler:^(){
NSLog (@"finished writing iOS version:%f",version);
}];
}
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
[self addAudioToFileAtPath:audioFilePath toVideoPath:videoPath andFinalVideoPath:finalVideoPath];
}
图像像素缓冲区的实用方法 *
- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image),
CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options,
&pxbuffer);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image),
CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace,
(CGBitmapInfo)kCGImageAlphaNoneSkipFirst);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
**
-(void) addAudioToFileAtPath:(NSString *) audiofilePath toVideoPath:(NSString
*)videoFilePath andFinalVideoPath:(NSString *)finalVideoPath
{
AVMutableComposition* mixComposition = [AVMutableComposition composition];
// audio input file...
NSURL *audio_inputFileUrl = [NSURL fileURLWithPath:audiofilePath];
// this is the video file that was just written above, full path to file is in --> videoOutputPath
NSURL *video_inputFileUrl = [NSURL fileURLWithPath:videoFilePath];
// create the final video output file as MOV file - may need to be MP4, but this works so far...
NSURL *outputFileUrl = [NSURL fileURLWithPath:finalVideoPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:finalVideoPath])
[[NSFileManager defaultManager] removeItemAtPath:finalVideoPath 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, audioAsset.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:AVAssetExportPresetHighestQuality];
//_assetExport.outputFileType = @"com.apple.quicktime-movie";
_assetExport.outputFileType = @"public.mpeg-4";
//NSLog(@"support file types= %@", [_assetExport supportedFileTypes]);
_assetExport.outputURL = outputFileUrl;
[_assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
switch (_assetExport.status)
{
case AVAssetExportSessionStatusCompleted:
// export complete
NSLog(@"Export Complete");
break;
case AVAssetExportSessionStatusFailed:
NSLog(@"Export Failed");
NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]);
// export error (see exportSession.error)
break;
case AVAssetExportSessionStatusCancelled:
NSLog(@"Export Failed");
NSLog(@"ExportSessionError: %@", [_assetExport.error localizedDescription]);
// export cancelled
break;
}
//If you want to save the video to Photo Album
UISaveVideoAtPathToSavedPhotosAlbum (finalVideoPath,self, @selector(video:didFinishSavingWithError: contextInfo:), nil);
}
];
///// THAT IS IT DONE... the final video file will be written here...
NSLog(@"DONE.....outputFilePath--->%@", finalVideoPath);
// the final video file will be located somewhere like here:
// /Users/caferrara/Library/Application Support/iPhone Simulator/6.0/Applications/D4B12FEE-E09C-4B12-B772-7F1BD6011BE1/Documents/outputFile.mov
}
**
**
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error
contextInfo:(void *)contextInfo
{
ALAssetsLibrary * library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:url completionBlock:^(NSURL *assetURL, NSError
*error){
if (error) {
NSLog(@"Video could not be saved ,Error:%@",error);
[[[UIAlertView alloc]initWithTitle:@"Sorry!!" message:@"Video data is Nil" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]show];
}else{
if (![videoArray containsObject:url]) {
[videoArray addObject:url];
}
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Done"
message:@"Movie succesfully exported."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
[alert show];
}
}];
} **