Ashraf Hussein
Ashraf Hussein

Reputation: 589

Creating Video from array of images and saving it to camera roll

I was trying to make a video from a set of images and I found some code and got it to work

but the video won't be saved to the photo library it gives me this error :

Documentsa.mov cannot be saved to the saved photos album: Error Domain=NSOSStatusErrorDomain Code=2 "This movie could not be played." UserInfo=0x922cf60 {NSLocalizedDescription=This movie could not be played.}

Here's the code I use :

 NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    UIImage * i = [UIImage imageNamed:@"IMG_1650.JPG"];
    CGAffineTransform  transform = CGAffineTransformMakeRotation((M_PI/180)*90);
    GPUImageTransformFilter * filter = [[GPUImageTransformFilter alloc]init];
    [filter setAffineTransform:transform];
   UIImage * im = [filter imageByFilteringImage:i];
    im = [filter imageByFilteringImage:im];

    [self writeImagesToMovieAtPath:[NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mov"] withSize:CGSizeMake(i.size.width, i.size.height)];

    NSString* exportVideoPath = [NSString stringWithFormat:@"%@%@",documentsDirectoryPath,@"a.mov"];

    UISaveVideoAtPathToSavedPhotosAlbum (exportVideoPath,self, @selector(video:didFinishSavingWithError: contextInfo:), nil);

And this is the code I use to create the video :

-(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 = 1;
    int kRecordingFPS = 30;
    UIImage * im = [UIImage imageNamed:@"IMG_1650.JPG"];

    CGAffineTransform  transform = CGAffineTransformMakeRotation((M_PI/180)*90);
    GPUImageTransformFilter * filter = [[GPUImageTransformFilter alloc]init];
    [filter setAffineTransform:transform];
    UIImage * i = [filter imageByFilteringImage:im];
    i = [filter imageByFilteringImage:im];
    NSArray * imageArray = [[NSArray alloc]initWithObjects:i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i, 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");
}

I tried to check if the video is compatible using

UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(videoPath)

and I found out that the video isn't compatible

but i don't know why or how to fix this

Upvotes: 2

Views: 4115

Answers (3)

iOSDeveloper-Ganesh
iOSDeveloper-Ganesh

Reputation: 11

The videoPath

NSString* exportVideoPath = [NSString stringWithFormat:@"%@%@",documentsDirectoryPath,@"a.mov"]; 

is wrong. You are missing '/' separator.

Change it to this

NSString* exportVideoPath = [NSString stringWithFormat:@"%@/%@",documentsDirectoryPath,@"a.mov"]; 

Hope this should sove your issue.

Upvotes: 1

A-Live
A-Live

Reputation: 8944

What do you mean by overcome ? I believe you are fine to send the file from documents to any backend server to store it and other devices with a better (you know what i mean) video support will be able to play it. But exceeding the OS limitations will not likely go well even if possible by some 'hack'.

I mean 1080p is the greatest video file resolution to be at library as the media at library must be playable. Still you could store the file at the app documents and decode it manually, sounds like an interesting task :) Make sure you are not going to sync it with iCloud though to avoid huge traffic leaks making the customers crazy.

Upvotes: 0

Ashraf Hussein
Ashraf Hussein

Reputation: 589

I tried the solution by A-Live in a previous comment

the problem turned out to be the size of the image was too big

is there a way to overcome this?

Upvotes: 0

Related Questions