AVFoundation + AssetWriter:使用图像和音频生成电影

编程入门 行业动态 更新时间:2024-10-28 00:14:31
本文介绍了AVFoundation + AssetWriter:使用图像和音频生成电影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我必须从我的iPhone应用程序导出一部电影,其中包含来自NSArray的UIImage,并添加一些必须以预先指定的时间开始的.caf格式的音频文件。 现在我已经能够使用AVAssetWriter(经过这个和其他网站上的许多问题和答案)导出包含图像的视频部分,但似乎无法找到添加音频文件的方法来完成电影。

I have to export a movie from my iPhone application which contains UIImage from an NSArray and add some audio files in .caf format that have to start at pre-specified times. Now I have been able to use the AVAssetWriter (after going through many questions and answers on this and other sites) to export the video portion containing the images but cant seem to find a way to add the audio files to complete the movie.

以下是我到目前为止所获得的信息

Here is what I have gotten so far

-(void) writeImagesToMovieAtPath:(NSString *) path withSize:(CGSize) size { NSLog(@"Write Started"); 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* 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 = 0; 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"); }

现在pixBufferFromCGImage的代码

And now the code for pixelBufferFromCGImage

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image andSize:(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, (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, size.width, size.height, 8, 4*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; }

那么你可以帮我解决一下如何添加音频文件以及如何为它们创建缓冲区以及适配器和输入设置等

So can you help me out regarding how to add the audio files and how to make buffers for them and the adaptor and input settings etc

如果这种方法可能会导致问题,请指导我如何使用AVMutableComposition将图像数组用于视频导出

If this approach might cause a problem guide me about how to use a AVMutableComposition to use the image array for video export

推荐答案

我最后使用上面的代码分别导出视频,并使用AVComposition& amp; AVExportSession。 这是代码

I ended up exporting the video separately using the above code and added the audio files separately using AVComposition & AVExportSession. Here is the code

-(void) addAudioToFileAtPath:(NSString *) filePath toPath:(NSString *)outFilePath { NSError * error = nil; AVMutableComposition * composition = [AVMutableComposition composition]; AVURLAsset * videoAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:filePath] options:nil]; AVAssetTrack * videoAssetTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID: kCMPersistentTrackID_Invalid]; [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,videoAsset.duration) ofTrack:videoAssetTrack atTime:kCMTimeZero error:&error]; CMTime audioStartTime = kCMTimeZero; for (NSDictionary * audioInfo in audioInfoArray) { NSString * pathString = [audioInfo objectForKey:audioFilePath]; AVURLAsset * urlAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:pathString] options:nil]; AVAssetTrack * audioAssetTrack = [[urlAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID: kCMPersistentTrackID_Invalid]; [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,urlAsset.duration) ofTrack:audioAssetTrack atTime:audioStartTime error:&error]; audioStartTime = CMTimeAdd(audioStartTime, CMTimeMake((int) (([[audioInfo objectForKey:audioDuration] floatValue] * kRecordingFPS) + 0.5), kRecordingFPS)); } AVAssetExportSession* assetExport = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality]; assetExport.videoComposition = mutableVideoComposition; assetExport.outputFileType =AVFileTypeQuickTimeMovie;// @"com.apple.quicktime-movie"; assetExport.outputURL = [NSURL fileURLWithPath:outFilePath]; [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; } }]; }

更多推荐

AVFoundation + AssetWriter:使用图像和音频生成电影

本文发布于:2023-07-11 12:36:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1094087.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:图像   音频   电影   AVFoundation   AssetWriter

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!