AVAssetExportSession - Join 2 mp4 files in IOS
Asked Answered
W

2

2

I am trying to join 2 preexisting mpeg4 video's together on an ipad2 with the following code.

-(void)mergeTestVideos
{

    //setup asset
    NSString *firstassetpath = [NSString stringWithFormat:@"%@mpeg4-1.mp4", NSTemporaryDirectory()];
    NSString *secondassetpath = [NSString stringWithFormat:@"%@mpeg4-2.mp4", NSTemporaryDirectory()];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    AVAsset *firstAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:firstassetpath]];
    AVAsset *secondAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:secondassetpath]];

    NSLog(@"FirstAsset Is Readable = %d", firstAsset.isReadable);
    NSLog(@"FirstAsset Is playable = %d", firstAsset.isPlayable);
    NSLog(@"FirstAsset Is exportable = %d", firstAsset.exportable);
    NSLog(@"SecondAsset Is Readable = %d", secondAsset.isReadable);
    NSLog(@"SecondAsset Is playable = %d", secondAsset.isPlayable);
    NSLog(@"SecondAsset Is exportable = %d", secondAsset.exportable);

    //setup composition and track
    AVMutableComposition *composition = [[AVMutableComposition alloc]init];
    AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVAssetExportPresetPassthrough preferredTrackID:kCMPersistentTrackID_Invalid];

    //add assets to track
    [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstAsset.duration) ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] atTime:kCMTimeZero error:nil];

    [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, secondAsset.duration) ofTrack:[[secondAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] atTime:firstAsset.duration error:nil];

    // 5 - Create exporter
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc]initWithAsset:composition presetName:AVAssetExportPresetPassthrough];

    NSString *outputURL = [NSString stringWithFormat:@"%@mergedvid.mp4", NSTemporaryDirectory()];

    NSLog(@"%@", exporter.supportedFileTypes);
    exporter.outputURL=[NSURL fileURLWithPath:outputURL];

    exporter.outputFileType = AVFileTypeMPEG4;
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self exportDidFinish:exporter];
        });
    }];

}

-(void)exportDidFinish:(AVAssetExportSession*)session {

    NSLog(@"export method");
    NSLog(@"%i", session.status);
    NSLog(@"%@", session.error);
}

and output is as follows:

- FirstAsset Is Readable = 1
- FirstAsset Is playable = 1
- FirstAsset Is exportable = 1
- SecondAsset Is Readable = 1
- SecondAsset Is playable = 1
- SecondAsset Is exportable = 1
- (
"com.apple.quicktime-movie",
"com.apple.m4a-audio",
"public.mpeg-4",
"com.apple.m4v-video",
"public.3gpp",
"org.3gpp.adaptive-multi-rate-audio",
"com.microsoft.waveform-audio",
"public.aiff-audio",
"public.aifc-audio",
"com.apple.coreaudio-format"
)
-export method
- 4
- Error Domain=AVFoundationErrorDomain Code=-11838 "Operation Stopped" UserInfo=0x155f76f0 {NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The operation is not supported for this media.}

Ok so according to the output my files are ok and exportable and mp4 is a supported output type.

Does anybody have any idea why it is giving me the error 'The operation is not supported for this media'

While answered 13/12, 2013 at 3:16 Comment(0)
D
3

I think this statement is your culprit

AVMutableCompositionTrack *track = [composition addMutableTrackWithMediaType:AVAssetExportPresetPassthrough preferredTrackID:kCMPersistentTrackID_Invalid];

Here you are passing AVAssetExportPresetPassthrough where you should have used AVMediaTypeVideo or AVMediaTypeAudio

Diphosgene answered 13/12, 2013 at 9:44 Comment(3)
Ok thanks I have tried this but unfortunately I don't think it is correct because the AVAssetExportSession object fails to build (is equal to null) when I change the code to this. This is what happens -> NSLog(@"Exporter: %@\n",exporter); Exporter: (null)While
What do you mean by it is not correct? You are using a wrong constant value. You can check apple documentation for the supported values in that method. I think you should check AVSimpleEditor project from Apple. developer.apple.com/library/ios/samplecode/AVSimpleEditoriOS/…Diphosgene
Sorry I messed up (Changed the exporter to AVMediaTypeVideo rather than the track) you were dead right. I will award you the prize :) Thanks for your help Gaurav.While
S
1

If you are joining two videos then why you are using kCMTimeZero at both place while inserting time range. I think it should be

 [track insertTimeRange:CMTimeRangeMake(kCMTimeZero, firstAsset.duration) ofTrack:[[firstAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] atTime:kCMTimeZero error:nil];

[track insertTimeRange:CMTimeRangeMake(kCMTimeZero, secondAsset.duration) ofTrack:[[secondAsset tracksWithMediaType:AVMediaTypeVideo]objectAtIndex:0] atTime:firstAsset.duration error:nil];

See changes in atTime while inserting time range for secondAsset

Skees answered 13/12, 2013 at 11:16 Comment(2)
Good spotting! Thanks for that. Unfortunately I am still stuck with the original issue after changing this.While
Have you try changing AVAssetExportPresetPassthrough to AVMediaTypeVideo.?Skees

© 2022 - 2024 — McMap. All rights reserved.