Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Try this code</h1> <p><pre><code></p> <ul> <li><p>(IBAction)createVideo:(id)sender {</p> <p>///////////// setup OR function def if we move this to a separate function //////////// // this should be moved to its own function, that can take an imageArray, videoOutputPath, etc... // - (void)exportImages:(NSMutableArray *)imageArray // asVideoToPath:(NSString *)videoOutputPath // withFrameSize:(CGSize)imageSize // framesPerSecond:(NSUInteger)fps {</p> <p>NSError *error = nil;</p> <p>// set up file manager, and file videoOutputPath, remove "test_output.mp4" if it exists... //NSString *videoOutputPath = @"/Users/someuser/Desktop/test_output.mp4"; NSFileManager *fileMgr = [NSFileManager defaultManager]; NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:@"test_output.mp4"]; //NSLog(@"-->videoOutputPath= %@", videoOutputPath); // get rid of existing mp4 if exists... if ([fileMgr removeItemAtPath:videoOutputPath error:&amp;error] != YES) NSLog(@"Unable to delete file: %@", [error localizedDescription]);</p> <p>CGSize imageSize = CGSizeMake(400, 200); NSUInteger fps = 30;</p> <p>//NSMutableArray *imageArray; //imageArray = [[NSMutableArray alloc] initWithObjects:@"download.jpeg", @"download2.jpeg", nil]; NSMutableArray <em>imageArray; NSArray</em> imagePaths = [[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:nil]; imageArray = [[NSMutableArray alloc] initWithCapacity:imagePaths.count]; NSLog(@"-->imageArray.count= %i", imageArray.count); for (NSString* path in imagePaths) { [imageArray addObject:[UIImage imageWithContentsOfFile:path]]; //NSLog(@"-->image path= %@", path); }</p> <p>////////////// end setup ///////////////////////////////////</p> <p>NSLog(@"Start building video from defined frames.");</p> <p>AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: [NSURL fileURLWithPath:videoOutputPath] fileType:AVFileTypeQuickTimeMovie error:&amp;error]; NSParameterAssert(videoWriter);</p> <p>NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:imageSize.width], AVVideoWidthKey, [NSNumber numberWithInt:imageSize.height], AVVideoHeightKey, nil];</p> <p>AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];</p> <p>AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput sourcePixelBufferAttributes:nil];</p> <p>NSParameterAssert(videoWriterInput); NSParameterAssert([videoWriter canAddInput:videoWriterInput]); videoWriterInput.expectsMediaDataInRealTime = YES; [videoWriter addInput:videoWriterInput];</p> <p>//Start a session: [videoWriter startWriting]; [videoWriter startSessionAtSourceTime:kCMTimeZero];</p> <p>CVPixelBufferRef buffer = NULL;</p> <p>//convert uiimage to CGImage. int frameCount = 0; double numberOfSecondsPerFrame = 6; double frameDuration = fps * numberOfSecondsPerFrame;</p> <p>//for(VideoFrame * frm in imageArray) NSLog(@"<strong><em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>***</strong>"); for(UIImage * img in imageArray) { //UIImage * img = frm._imageFrame; buffer = [self pixelBufferFromCGImage:[img CGImage]];</p> <pre><code>BOOL append_ok = NO; int j = 0; while (!append_ok &amp;&amp; j &lt; 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++; </code></pre> <p>} NSLog(@"<strong><em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>**<em>*</em>***</strong>");</p> <p>//Finish the session: [videoWriterInput markAsFinished]; [videoWriter finishWriting]; NSLog(@"Write Ended");</p> <p>//////////////////////////////////////////////////////////////////////////// ////////////// OK now add an audio file to move file ///////////////////// AVMutableComposition* mixComposition = [AVMutableComposition composition];</p> <p>NSString *bundleDirectory = [[NSBundle mainBundle] bundlePath]; // audio input file... NSString *audio_inputFilePath = [bundleDirectory stringByAppendingPathComponent:@"30secs.mp3"]; NSURL *audio_inputFileUrl = [NSURL fileURLWithPath:audio_inputFilePath];</p> <p>// this is the video file that was just written above, full path to file is in --> videoOutputPath NSURL *video_inputFileUrl = [NSURL fileURLWithPath:videoOutputPath];</p> <p>// create the final video output file as MOV file - may need to be MP4, but this works so far... NSString *outputFilePath = [documentsDirectory stringByAppendingPathComponent:@"final_video.mp4"]; NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];</p> <p>if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath]) [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];</p> <p>CMTime nextClipStartTime = kCMTimeZero;</p> <p>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];</p> <p>//nextClipStartTime = CMTimeAdd(nextClipStartTime, a_timeRange.duration);</p> <p>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];</p> <p>//AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; __block AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetPassthrough];</p> <p>NSLog(@"support file types= %@", [_assetExport supportedFileTypes]); _assetExport.outputFileType = @"com.apple.quicktime-movie"; NSLog(@"support file types= %@", [_assetExport supportedFileTypes]); _assetExport.outputURL = outputFileUrl;</p> <p>[_assetExport exportAsynchronouslyWithCompletionHandler:^{ switch (_assetExport.status) { case AVAssetExportSessionStatusCompleted: // Custom method to import the Exported Video NSLog(@"completed!!!"); break; case AVAssetExportSessionStatusFailed: // NSLog(@"Failed:%@",_assetExport.error); break; case AVAssetExportSessionStatusCancelled: // NSLog(@"Canceled:%@",_assetExport.error); break; default: break; } }];</p> <p>///// THAT IS IT DONE... the final video file will be written here... NSLog(@"DONE.....outputFilePath--->%@", outputFilePath);</p> <p>// 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</p></li> </ul> <p>} </pre></code></p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload