0

I am really stuck on this, i have merged videos (mp4 kind that are saved in xcode, and mov - from users photo library) and audio (mp3 kind saved in xcode). On the simulator it works fine and shows the video and audio, but on the device it doesn't show the video only plays the sound . here is the code for merging:` AVMutableComposition* mixComposition = [AVMutableComposition composition];

//Audio
//Now first load your audio file using AVURLAsset. Make sure you give the correct path of your videos.
NSURL *audio_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:_video.musicFileName ofType:@"mp3"]];
AVURLAsset  *audioAsset = [[AVURLAsset alloc] initWithURL:audio_url options:nil];
CMTimeRange audio_timeRange = CMTimeRangeMake(kCMTimeZero, audioAsset.duration);

//Now we are creating the first AVMutableCompositionTrack containing our audio and add it to our AVMutableComposition object.
AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionAudioTrack insertTimeRange:audio_timeRange ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] atTime:kCMTimeZero error:nil];


//Video
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
NSString *fistPartMovieFilename = @"firstpart";
NSString *lastPartMovieFilename = @"lastpart";

//[_video.selectedVideosFileName insertObject:fistPartMovieFilename atIndex:0];
//[_video.selectedVideosFileName addObject:lastPartMovieFilename];
NSMutableArray *timeRanges = [NSMutableArray arrayWithCapacity:_video.selectedVideosFileName.count];
NSMutableArray *tracks = [NSMutableArray arrayWithCapacity:_video.selectedVideosFileName.count];

NSLog(@"_video.selectedVideosFileName %@",_video.selectedVideosFileName);
for (int i=0; i<[_video.selectedVideosFileName count]; i++)
{
    AVURLAsset *assetClip;
    NSString *fileName = [_video.selectedVideosFileName objectAtIndex:i];

    if ([[_video.selectedVideosFileName objectAtIndex:i] isKindOfClass:[NSURL class]])
    {
        assetClip = [AVAsset assetWithURL:[_video.selectedVideosFileName objectAtIndex:i]];
    }
    else
    {
        assetClip = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithString:fileName] ofType:@"mp4"]] options:nil];

    }

    AVAssetTrack *clipVideoTrack = [[assetClip tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    [timeRanges addObject:[NSValue valueWithCMTimeRange:CMTimeRangeMake(kCMTimeZero, assetClip.duration)]];
    [tracks addObject:clipVideoTrack];

    NSLog(@"timeRanges %@",timeRanges);
    NSLog(@"tracks %@",tracks);
    NSLog(@"assetClip %@",assetClip);
    NSLog(@"clipVideoTrack %@",clipVideoTrack);


}

NSError *error = nil;
BOOL sucsess = [compositionVideoTrack insertTimeRanges:timeRanges
                                              ofTracks:tracks
                                                atTime:kCMTimeZero
                                                 error:&error];

if (!sucsess || error) {
    NSLog(@"video error %@", error);


}

the error i get when trying on device is : video error Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo=0x1704707c0 {NSUnderlyingError=0x174247050 "The operation couldn’t be completed. (OSStatus error -12780.)", NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed

 NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsDir = [dirPaths objectAtIndex:0];
    NSString *outputFilePath =  [docsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"Zagoori-%d.mov",arc4random() % 1000]];
    NSURL *outputFileUrl = [NSURL fileURLWithPath:outputFilePath];

    if ([[NSFileManager defaultManager] fileExistsAtPath:outputFilePath])
        [[NSFileManager defaultManager] removeItemAtPath:outputFilePath error:nil];

    //Now create an AVAssetExportSession object that will save your final video at specified path.
    AVAssetExportSession *_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                          presetName:AVAssetExportPresetLowQuality];

    NSLog(@"supportedFileTypes %@", [_assetExport supportedFileTypes]);
    _assetExport.outputFileType = @"com.apple.quicktime-movie";
    _assetExport.outputURL = outputFileUrl;
    [_assetExport exportAsynchronouslyWithCompletionHandler:^
     {
         dispatch_async(dispatch_get_main_queue(), ^{

             switch ([_assetExport status]) {
                 case AVAssetExportSessionStatusExporting:
                     NSLog(@"Export in progress ");
                 case AVAssetExportSessionStatusFailed:
                     NSLog(@"Export failed (%ld): %@", (long)[[_assetExport error] code], [[_assetExport error] localizedFailureReason]);
                     [_assetExport cancelExport];
                     break;
                 case AVAssetExportSessionStatusCancelled:
                     NSLog(@"Export canceled");
                     break;
                 case AVAssetExportSessionStatusCompleted:
                     NSLog(@"Export done");
                     [self exportDidFinish:_assetExport];

                   //  NSLog (@"finished writing %f", [dtStartDate timeIntervalSinceNow]);
                     break;
                 case AVAssetExportSessionStatusWaiting:
                     NSLog (@"AVAssetExportSessionStatusWaiting");
                     break;
                 case AVAssetExportSessionStatusUnknown:
                     NSLog (@"AVAssetExportSessionStatusUnknown");
                     break;
             }

         });


     }]; 

-(void)loadMoviePlayer:(NSURL*)moviePath {
    _moviePlayerController = [[MPMoviePlayerController alloc]
                   initWithContentURL:moviePath];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                  selector:@selector(introMovieFinished:)
                                                      name:MPMoviePlayerPlaybackDidFinishNotification
                                                    object:_moviePlayerController];

    _moviePlayerController.view.hidden = NO;
    _moviePlayerController.view.frame = CGRectMake(0, 0, _videoView.frame.size.width,
                                        _videoView.frame.size.height);
    _moviePlayerController.view.backgroundColor = [UIColor clearColor];
    _moviePlayerController.scalingMode = MPMovieScalingModeAspectFit;
    _moviePlayerController.fullscreen = NO;
    [_moviePlayerController prepareToPlay];
    [_moviePlayerController readyForDisplay];
    [_moviePlayerController setControlStyle:MPMovieControlStyleDefault];
    _moviePlayerController.shouldAutoplay = YES;
    [_videoView addSubview:_moviePlayerController.view];
    [_videoView setHidden:NO];
}

I am really clueless of what the problem could be, Help please! :)

1 Answers1

0

so i have found the problem,it is caused by the AVURLAsset instances

Since the AVURLAsset *assetClip is in inside the for loop, it is not valid outside of it and neither is the tracks that i extracted.

I kept my assetClip in an array and that solved the problem.